Gtk应用内嵌网页与原生代码交互方法

前置条件

  • Ubuntu 24.04.2 LTS

内容详情

在使用Gtk开发应用程序的过程中,如果需要内嵌网页,那么使用libwebkit2gtk是个非常自然和正确的选择。

那么这里就可能原生程序代码可能需要跟网页交互的问题。

Gtk程序跟网页的交互,主要有两个方面:

需求1,使用 webkit2gtk 的内置 webkit_web_view_run_javascript 函数即可解决

需求2,使用 webkit2gtk 的内置的 web extendsion 扩展支持功能解决 或 window.webkit.messageHandlers..postMessage(value)

不多说看代码吧!

Gtk嵌入网页Demo程序

webviewgtk.c

Web Extension Demo

内嵌的网页示例 webview.html

示例运行

安装依赖:

把webviewgtk.c,web_exten.c,webview.html 放在同一目录下。

编译程序:

运行程序:

参考链接


应用内嵌WebKitGTK报错“Unacceptable TLS certificate”

ubuntu 24.04 系统开发内嵌 webkit2gtk-4.1 的应用,打开部分 HTTPS 网页报错“Unacceptable TLS certificate”, 如下图:

但是相同的页面使用 FireFox/Safari/Chrome/IE/Edge 等主流浏览器打开都是正常显示的。

调试代码,发现是 WebKitWebViewon_load_failed_with_tls_errors 回调函数返回了错误 G_TLS_CERTIFICATE_GENERIC_ERROR64),如下图:

于是安装 Gnome 官方的浏览器 Epiphany 进行测试,该浏览器底层也是调用 WebKit2GTK,在 ubuntu 24.04 系统,可以执行如下命令进行安装:

打开相同的页面,同样报错,显示服务器不可信。

由于 WebKit2GTK 底层的 TLS 通信调用库调用的是 GnuTLS 。于是尝试通过命令行对 TLS 证书认证过程进行验证,执行如下命令:

可以看到,网站的根证书无法通过 GnuTLS 的验证,原因在于网站的证书链中的根证书使用的 RSA-SHA1 签名,该类型签名存在 “弱哈希算法签名的SSL证书(CVE-2004-2761)漏洞” 进而被 GnuTLS 拒绝。

针对此问题的更详细的描述参考 GnuTLS 文档 8.2 Disabling algorithms and protocols

针对此问题的解决方法:

  • 联系网站,更新证书,重新以 RSA-SHA256 签发证书。由于是公司内部网址,因此联系网络更新即可;

  • 应用内嵌网站证书,通过 webkit_web_context_allow_tls_certificate_for_host 要求 webkit 通过提供的证书进行网站验证。此种情况适用于 APP 内嵌自己网站页面的情况,同样适用于自签名证书的情况;

  • 如果纯粹测试,可以在加载页面之前调用

    要求 webkit 无视证书错误。此方法生产环境不可取,非常不安全,仅可用于内部测试

  • 此方案目前测试已经不可用调用 gnutls_sign_set_secure_for_certs API 许可部分不安全的证书签名算法

    相对来说,联系不上网站的情况下,又需要在保证安全的前提下,尽量兼容网站,推荐此种方式;

  • 自行接管证书验证过程,实现比较复杂,极其容易产生安全漏洞,不建议;

参考链接


VSCode GDB调试控制台报错"-var-create: unable to create variable object"

背景

在使用 Visual Studio Code (1.97.2) 进行 GDB 调试时,想使用 x 命令看一下某地址处的数值。出现如下报错:

解决方案

其实,在刚刚开始调试程序时,就以黄色字体给出了解决方案。

也就是说:

  • 如果是想查看某个变量的值,直接在输入框里输入变量名就好了;

  • 如果要执行GDB命令,则需要加-exec前缀,如下图:

参考链接


SM2格式数字信封加解密详解

0、参考链接

1、SM2数字信封格式:

2、代码中SM2数字信封加密解密步骤

解密(将SM2数字信封格式转换为加密私钥)

3、SM2数字信封格式详解

参考链接


解决在macOS上使用Flutter项目访问网络报错 "SocketException: Connection failed (OS Error: Operation not permitted, errno = 1)"

在Flutter应用中添加网络支持是一个非常常见的需求。

这主要是按照以下步骤进行。

  • pub.dev中安装一个网络包,如httpdio
  • 在您的 Flutter 应用程序中添加所有必要的网络代码
  • 如果需要,添加任何所需的API密钥

但是,如果你在macOS上运行该应用程序,你会被这个可怕的错误所欢迎。

SocketException错误已经来拜访你了

这就是它,以更可读的格式。

所以,让我们弄清楚为什么会发生这种情况,以及如何修复它。👇

注意:如果你要给一个旧的Flutter应用添加macOS支持,你可能需要运行flutter create --platforms macos . ,把macOS添加为构建目标。我在macOS上运行我的大部分应用程序,所以在构建响应式UI时,我可以轻松地调整窗口的大小。

macOS上的客户端联网权限

macOS应用程序默认为沙盒,如果你没有添加所需的权限,就会发生SocketException 的错误。

要解决这个问题,请打开名为macos/Runner/DebugProfile.entitlements 的文件并添加以下内容。

然后,打开macos/Runner/Release.entitlements ,做同样的事情。

那么iOS呢?

在iOS上,只要你连接到一个安全的https 终端,该应用就可以正常运行(不需要额外的配置)。

但请记住,在某些情况下,你可能需要定制应用程序的传输安全设置,如这里所解释的。

安卓的情况如何?

在安卓系统中,曾经需要AndroidManifest.xml 文件中添加INTERNET权限。

但根据这个答案,现在已经不需要了,因为大多数应用程序都需要互联网访问。

参考链接


如何解决 "SocketException:连接失败(操作不允许)",在macOS上使用Flutter

mdadm软Raid1升级容量

2块12TB做了软RAID1,需要升级成2块16TB盘

1. 查看磁盘信息,SerialNumber 等会儿会用到,防止换错盘

2. 运行 sync 命令刷写

3. 查看 md 状态

4. 查看 md 容量

剔除磁盘 /dev/sdc

5. 关机换盘(支持热插拔的可以开机更换)

6. 更换硬盘后加回硬盘

lsblk查看换回来的设备名称

由于是原位置更换,盘的名称还是 /dev/sdc

7. 等待同步完成后,依照第一块盘的方式,更换掉第二块盘再次等待同步完成。

8. mdadm 扩容

文件系统扩容

如果上述命令报错

则执行如下命令,观察一下是否分区是 LVM分区格式

并且检查文件系统是 btrfs 格式,如下:

如果类似上述情况,需要额外执行如下命令:

删除新添加硬盘分区,并且添加新分区,保持与原磁盘一致:

如果后续添加磁盘的时候报错:

则需要复制分区表,解决磁盘分区差异导致报错新硬盘空间不足问题,如下:

如果上述命令继续报错

那么就没办法与原始磁盘保持相同的分区模式了,只能是直接使用整个硬盘,不指定硬盘下的具体分区,修改命令如下:

再次检查磁盘分区情况:

参考链接


Python 实现国产SM3加密算法

SM3由国家密码管理局于2010年12月17日发布,主要用于数字签名及验证。

Python3代码如下:

参考链接


Python 实现国产SM3加密算法

解决Visual Studio Code在Raspberry Pi 4运行特别缓慢的问题

在树莓派4通过命令行安装 Visual Studio Code 如下:

但是运行特别缓慢,调试 Python 代码会持续卡住,CPU 长时间 100% 占用。

目前一个可用的办法就是在 Visual Studio Code 中禁用 GPU 加速。

具体操作如下:

  • Open Visual Studio Code

  • Open the Command Palette by hitting your F1 key or the key combo Ctrl+Shift+P,或者菜单中选择 “命令面板” 如下图:

  • Begin typing runtime and you should see “Preferences: Configure Runtime Arguments” appear (Pictured below). Click it or hit Enter to open a configuration file called argv.json which allows us to set runtime arguments.

  • There should be the line "disable-hardware-acceleration": true, commented out. (Pictured below)

  • Uncomment the line by deleting the preceding // or add the line if it is missing entirely.
    Tip: Be careful not forget the comma if the line is not the last uncommented one inside the curly braces.

  • Save the file and restart Visual Studio Code for the change to take effect.

参考链接


Python3-使用U盾完成数据的加解密(国密算法SKF接口)

如果身边有银行的U盾,或者其他Ukey产品,可以使用这些产品完成对数据的加解密,针对个人的敏感数据进行加密处理。

1-涉及的内容
  • ubuntu 24.04.2 LTS
  • Python 3.8 / 3.11
  • asn1crypto 1.5.1
  • 使用的 Python3ctypes 作用:

Python3 的外部函数库。提供与 C语言兼容的数据类型,并允许调用 DLL 或共享库中的函数。

  • 使用的 Python3asn1crypto 作用:

Python3 的外部函数库。ASN.1 格式解析组装 PKCS#7 格式的报文。版本不低于 1.5.1 ,否则可能编译错误。

  • 使用的Ukey:文鼎创的一款Key。

与Ukey使用会有配套的驱动程序(管理工具),安装之后会在【C:\Windows\System32】释放对应dll库文件,使用ctypes库调用这个dll文件。

  • dll的接口函数

现在各厂家的Ukey一般都支持国密算法(SKF),使用SKF中的函数,实现数据的加解密。了解到文鼎创这边提供的SKF的函数中有使用ECC非对称算法完成数据加解密。本文内容就是用里面的ECC算法完成数据分非对称加解密。

2-动态库涉及的函数及结构体
2.1 相关结构体

ECC签名结果结构体

C中的结构体声明:

Python的ctype库声明:

ECC公钥结构体

C中的结构体声明:

Python的ctype库声明:

密文数据结构体

C中的结构体声明:

Python的ctype库声明:

2.2 相关函数

3-Python3实现

要求:Ukey中有SM2容器,使用SM2加密密钥对,且默认在第一个容器名中,如果不是,请自行修改。

实现内容:

  • 使用ctype先定义好所需要到的结构体

  • 创建一个类,实现加解密的过程

    • 在类中在初始化中初始化句柄
    • 在对象结束的时候释放掉对应的句柄
    • 将句柄的获取放在一个函数中,获取句柄。
    • 将加密结果转换为Hex字符串形式。
    • 传入Hex密文字符进行解密。

  • 辅助函数:

    • def __IntList_ToHexStr(self, int_list):将int类型的列表转为Hex字符串
    • def __HexStr_ToIntList(self, str_hex):Hex字符串转为int类型的列表
    • def StrHex_ToCipherText(self, str_hex):Hex密文字符串转为密文结构体
    • def CipherText_ToStrHex(self, cipher_text):将密文结构体转为Hex密文字符串
    • def __BuildSm2SignP7DER(self, sig_text, der_cert, sm2_r, sm2_s): 构建 P7格式的SM2签名报文
  • 主要函数:

    • def ECCEncrypt(self, plain_text):返会的是密文结构类型数据
    • def ECCEncrypt_Hex(self, plain_text): 返会的是密文Hex字符串
    • def ECCDecrypt(self, cipher_text):传入密文结构体进行解密
    • def ECCDecrypt_Hex(self, cipher_hex): 传入密文Hex字符串进行解密
    • def VerifyPIN(self, user_pin): 验证UkeyPIN
    • def SM2Sign(self, plain_text): SM2签名
  • 其他函数:获取句柄相关,比较简单。

完整代码

4-测试结果

继续阅读Python3-使用U盾完成数据的加解密(国密算法SKF接口)

Error: Gradle build failed to produce an .apk file. It's likely that this file was generated under /xxxx/build, but the tool couldn't find it.

Flutter 升级到 3.27.3 版本,然后升级 Android 构建工具到最新的 AGP 8.8.0 版本,然后编译报错:

于是在项目的配置文件中寻找配置 "build" 目录的地方,于是在 Flutter 项目的 Android 工程根目录下找到,如下:

注意 getLayout().setBuildDirectory('../build') ,以前的 Gradle 版本是可以正常编译的,现在的版本需要需要改为 rootProject.buildDir = "../build" 。

修改后的结果如下: