2. 签名机制
签名相关的代码如developtools_hasigner: hapigner |应用程序签名工具-Gitee.com存储库。签名过程的整理如下:
签名步骤可以如下分组:
生成开发人员签名证书,包括,和。生成配置文件文件,包括和。生成签名的应用程序包括和。
2.1 生成开发者签名证书
生成开发人员的公共和私钥
通过华为的Deveco-Studio工具,您可以直接生成包含开发人员的公共和私钥的p12文件(有关详细信息,请参见特定文档中心。)
作者示例生成的p12文件(另存为my.p12)是标准PKCS12格式(在RFC 7292中定义)。它用于存储一个或多个组的公共密钥证书(包括公共密钥)及其相应的私钥(使用LocalKeyID字段来匹配公共和私钥)。它使用asn.1定义其数据结构,并使用编码规则将这些结构编码为二进制形式。
PEM文件的标签用于指示文件的内容类型。以下是一些普通的PEM标头和页脚(我将接一个地看到他们):
要解析特定的公共密钥证书信息,您可以使用以下命令(将公共密钥证书保存为文本中的my.pem文件):
openssl x509 -in my.pem -text -noout解析会在以下输出中结果(重要部分评论):
证书: DATA:版本: 3(0x2)//证书编号序列号: 2913163237517564203(0x286DA286DA287A8F6192B) ISSUER: C=,ST=,L=,O=,OU=,CN=testscr //证书发行者信息有效性不在: 9月23日1233:56056:37 2024 2024 GMT //证书的起点和有效期不到: SEP 17 123360 ELDITIO证书的期限为主题: c=,st=,l=,o=,o=,o=,o=,cn=testscr //证书持有人主题的信息公共密钥INFO:公共密钥算法: id-ecpublickey //公共密钥算法,这是Elliptic curve public-keike-key:(256 bebit)//pub: //证书持有人的公共密钥价值以十六进制表示04:3D:BC33333333333333333333333333333333333333333:CF3333:97:D43 3366095:A0333660913333333333333333333:01F3333333333333:1F3:000 1C:1D333333333333333333333333333333333333333333333333E33333333333333333333333333333:BA :fb:14:2a:56:6b:3f:1d:1a:45:7d:1e:8a:723:f63:0f6:0 13:95:AC33333333333333333333333333333333333333333333333333333333:CA3 3360F83:F43:2B33333333333333333333333333333333333333333333333:093:60 ASN1 OID: PRIME256V1 NIST曲线: P-256 X509V3 Extensions: X509V3主题密钥标识符: //证书持有人的标识6D:08:45:8C:8C:4A:FE:6E:75:E8:02:A4:39:A4:D5:BB:49:40签名算法:ECDSA-WITH-SHA256签名值: //证书的数字签名值30:45:02:2033333333:8833333333333333333333333:5E:033 3608C333333333333333333333333:B533333333333333333333333333333333:BC: 6A:A533:96:CC3:2233333333333333333333333333333333333333333333:56 :EB3:8:833600633:C93333333333333333333333333333333:16: 02:2133333:C53:DB3333333333333:673333333333333333333333333: E:FF3:CF:1633333333333333333333333333333333333333333333333333333333:0 4A:C2333333:A0333:94333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333334333343b83b83b83b83b83b833b83b83bar算法,公共密钥数字,公共密钥值等)是结构化的数据,很长,不利于识别和比较,因此需要一个简短的字符串来识别公共密钥的独特性。常见方法是使用公共密钥指纹(公共密钥PIN,也称为公共密钥),即对DER编码的公共密钥和Base64编码执行SHA-256计算。
应该在这里注意到,X509扩展字段中包含主题密钥标识符(SKID)字段,这也是证书持有人的身份。那么,为什么不直接使用证书中包含的SKID呢?您必须根据“链接”中的Skid的定义自己计算它:
对于CA证书,主题密钥标识符应源自公共密钥或生成唯一值的方法。
从公共密钥生成密钥标识符的两种常见方法为:
(1)关键识别仪由Bit String主题publickey值的160位SHA-1哈希(不包括标签,长度和未使用的位数)组成。
(2)关键识别仪由一个四个位类型字段组成,值0100,然后是位的sha-1 hash的最小值60位,位于位字符串主题publickey的值(不包括标签,长度和未使用的位字符串位位)。
可以通过公共密钥获得SKID的计算,但是计算方法不是唯一的,也可以通过任何算法获得,只要保证了唯一性。定义中建议使用两种基于SHA-1的算法。 OpenSSL使用的算法(请参阅Master·Openssl/openssl/openssl·GitHub)使用的算法(请参阅Openssl/crypto/x509/v3_skid.c)是在der-nected的公共密钥上执行SHA-1计算。
如果使用SKID来验证公钥的唯一性,则攻击者可以伪造证书,而其中的Skid与您的相同(SHA-1 Collision,或仅复制它)。这样的证书也是合法的,因此它可以轻松绕过公共密钥的验证。因此,Skid通常仅用于在证书链中找到亲子关系,并且不用于公共密钥的唯一标识。此外,还有一个授权密钥标识符(AKID)字段来识别证书的发行人。验证证书链时,验证程序会检查每个证书的AKID是否与上一个证书的滑动相匹配,以确保它们形成连续的信任链。
生成开发人员签署的叶子证书
证书的作用可以总结为:
发行人说:持有人的公钥是某某。
证书通常分为三个级别:根证书(根证书),中级证书(中级证书)和叶证书(LEAF证书)。
叶子证书由中级证书颁发(即发行人+叶证书的阿基德与中间证书的主题+Skid相同)。中级证书由根证书颁发(即,中间证书的发行人+AKID与根证书的主题+Skid相同)。根证书是由本身颁发的(即自签名,发行人和根证书的主题是相同的)
我们需要的是用于签署我们应用程序开发人员的叶子证书,该证书要求华为开发人员签署了中间证书才能为我们签发它。叶证书分为调试证书和发布证书。让我们以发布证书为例(有关详细信息,请参见文档中心):
根证书:
Certificate: Data: Version: 3 (0x2) Serial Number: 5339133492510690512 (0x4a18699f9d7d8cd0) Signature Algorithm: ecdsa-with-SHA384 Issuer: C=CN, O=Huawei, OU=华为CBG,CN=华为CBG根CA G2有效性不在: 3月16日033:04333:39 2020 GMT不到: MAR 16 033:04333339 2049 GMT OFFICENC : cn3360 cn,o=cn,o=cgn,o=cg=cg=cg y=cg hu=hu=hu=华为CBG根CA G2主题公共密钥:公共密钥算法: ID-ECPUBLICKEY public-key:(384位)PUB: 04:5a:27:64:1a:70:d2:3b:0d:ff:1c:4d:b2:d8:61:e5 :f93:fa:56:04:86:b93:4b:e23:25:9c:da:ec:193:4b: F0:0B33333333:413333333333:ED33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 6079:cc:a5:e23:3d:c9:5d:d5:55:78:7b:8a:f3:f3:00 7C:64333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333:A433333333333333333333333 600c:f83:0c:0d:24:80:70:8c:9b:fc:03:79:ce:0ce3: a4:38:7c:75:c6:f0:91 ASN1 OID: secp384r1 NIST CURVE: P-384 X509v3 extensions: X509v3 Key Usage: critical Certificate Sign, CRL Sign X509v3 Basic约束:关键CA:TRUE X509V3主题密钥标识符: A3:8E3:5A:F533:5A3333333333333333333333333333333:2A:6 A:25:72:7EE333:4833333333333333333333333333333:203:00签名算法:ECDSA-WITH-SHA384签名值: 30:64:02333333333333333:2A:5E33333:073333333333:F4 33366021:B63333333333333333333333333333333333333333333333333333333333: A5:85:1C:E7333333333333333333333333333333333333333333333333:A F:AC3:DB:B63333333333333333333333333333333333333333333333333333333:0 2A:AF3:78:E7333333333333333333333333333333333333333:CD3: 26:C83:8E:E733333333333333333333333333333333333:2333:33: 5B:9B3:C733333333333333333333333333333333933:CE3:AE3: 62:31333333333333:E83333333333:D43333333333333333:84336660 A2:C73333333333333333333333333333333333333333333333333333333333333333333333333:DF333333333 60C3:ED:283333333333333333333333333333333333333333333333333333333333:64:36036中级证书:
证书: DATA:版本: 3(0x2)序列号: 6803676100576229407(0x5E6B835DB5A9381F)签名算法算法: ECDSA-SHAITA-SHAITHITH-SHAITHITH-SHA384 ESSUEIRAWER=华为CBG,CN=Huawei CBG根Ca G2 ca G2在:年7月9日02:043:24 2020 GMT不到: JUL 7 02:043:24 2030 GMT ABSICEME=华为CBG开发人员关系CA G2主题公共密钥:公共密钥算法: ID-ECPUBLICKEY public-key:(384 bit)pub3: 04:eb:92:dd:a0:86:61:d6:19:69:67:68:0f:6c:9e: a0:3e:11:ec:bd:84:91:7b:6d:8a:11:38:1d:a9:e53: 5e:62:7a:db:44:72:3d:c:d3:e9:11:98:4b:ea:543 3360e23:6:e5:eb:c:73:80:2a:37:a4:983:fc:1a: 19:96:E833333333333333333333333333333333333333333333333333333333:F33 360A0:D23333333333333333333333333333333333333333333333333333333:8B33: AB:93:0D333333333:F633333333333333333:67 ASN1 OID3: SECP384R1 NIST CURVE3: P-384 A3:8E3:5A3:F533333333333333333333333333333333:8C:2A33:6A333 60253:72333333333333333333333333333333333333333333333333:0DC3:20:00 X509V3主题密钥标识符: DB:5EE333333333333333333333333333333333333333333333333:E433:FE3:713 33607A3:663360EE93:A43333333333333333333333333333333333333333333333:5E X509v3 Certificate Policies: Policy:X509v3 Any Policy CPS: http://cpki-caweb.huawei.com/cpki/cps X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Certificate Sign, CRL Sign X509V3 CRL分配点:全名: URI3:333333333333333333333333333333333333333333333333333: 30:64:23333333333333333:ED3:57:E6333:AD3: 8C:75:FA:513:D533333333333333333333333333333333:6A333660 54:1C33:66:CB3:D433333333333333333333333:AC33333:6C:85 :8:8:6a3:7733333333333333333333333333333333333333:5A3:0 59:DB3:F0333333333:B233333333333333333333333333333333333333:723360 8C:E0:A0:E533:606433333333333:9D3333333333333333333333: 4B:91:FF3:0D:3D333333333333333333333333333333333333:5A: 20:F73:CF:A2333333333333333333:EA3:DF3333333333333333333660 c9:d9:95:71:90:2c:64:9c:0f:58:86:21:d5:c9:77: f8:1c:f9:f9:b8:26:54:fb:ad:6e:e83:4:e13:7:3:77叶证书:
Certificate: Data: Version: 3 (0x2) Serial Number:cb:a2:fe:fb:f0:c6:a1:5f:fa:41:68:91:85 Signature Algorithm:ecdsa-with-SHA384 Issuer:c=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Developer Relations CA G2 Validity Not Before: Sep 23 12:58:04 2024 GMT Not After : Sep 23 123:58336004 2027 GMT Abjective: C=CN,O=\\ e5 \\ bc \\ a0 \\ a0 \\ e6 \\ e6 \\ a8,ou=1289676786065494977,cn=\’\\ e5 \\ bc \\ a0 \\ e6 \\ 99 \\ a8(1289676786065494977)\\\\,发行\’主题公共密钥Info:公共密钥algorithm: ID- ECPUBLICKEY publickey public public-key33:(256 BIT)BIT)PUB 04:3d:bc:b:bf:2b:17:cf:97:d433366095:a0333660913:7:1f:0 1C:1D333333333333333333333333333333333333333333333333E33333333333333333333333333333:BA :fb:14:2a:56:6b:3f:1d:1a:45:7d:1e:8a:723:f63:0f6:0 13:95:AC33333333333333333333333333333333333333333333333333333333:CA3: F8:F4333333333333333:5D333333333333333333333333333333333333333333333:60 ASN1 OID: PRIME256V1 NIST曲线: P-256 X509V3 Extensions: X509V3基本约束:关键CA:FALSE X509V3 CRL URI3:3http://H5Hosting-drcn.dbankcdn.cn/cch5/cch5/crl/hdrcag2/huaweicbghdrg2crl.crl.crl x509v3权威权威密钥标识符3: DB:5E3:9333333333333333333333333333333:D03:E433:FE33:7133 3607A3:66:E9:A433333333333333333333333333333333333333333:F3:5E X509V3主题密钥标识符: 6D:083:45:8C33333333333333333333333333333333333333333:75:E 8:02:A4333333333333339333333333:D533333333333333333333:49:40 X509V3密钥用法:关键数字签名X509V3扩展密钥用法:代码签名算法: ECDSA-WITH-SHA384签名sha384签名值: 30:64:023333333:5C:CD333333333333333333333333333333333333: 363360CE:DA:733:9C33:5E333333333333333333333333333333333: 09:E633333333333:463333333333333333333333333333333:A43:19:2533 3606D3:28:E5333333333:1D:4D3333333333333:2D3:02D3:0 F4:88:F5333333333333333333333333333333333333333333333333333:D7:2 1:FF33:19:6533333333333333333333333333333333333333333333333:02 :3360336033600:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:033 2A:EB3333333333333333:E23333333333:2C3333333333333333333333333333:24:5 1:0C3:EE3:D63:0A3:0E3333333333:0A33:0A:0A3:0 4D:E8333333333333333333333333333333333333333333333333333333333333333333:32:08 :99333333333333:0EE3333:62:5D33333333333333333336606433366600EE:6 21:90:4F3333333333333333333333:F033:ED3:70333333333333333333333333:26请注意,在发行的叶子证书中,该主题与CSR中使用的主题不同。叶证书是:
objuct: c=cn,o=\\ e5 \\ bc \\ a0 \\ e6 \\ 99 \\ a8,ou=128967676786065494977,cn=\’\\ e5 \\ e5 \\ bc \\ a0 \\ a0 \\ a0 \\ e6 \\ e6 \\ 99 \\ a8(
在CSR中,是:
苏
bject: C = , ST = , L = , O = , OU = , CN = testscr
说明华为在颁发叶子证书的时候,并没有使用我们CSR里的Subject,而是根据我们在开发者平台网站上登陆的账号信息,对Subject进行了填充。其中OU字段跟账号信息有关(类似iOS的Team ID,但在华为开发者网站上没有找到直接查看的地方)。叶子证书里的公钥信息还是和CSR保持一致,计算得到的公钥指纹也一样。
另外,华为目前给叶子证书的有效期是3年,3年以后需要续期成新证书。当然,如果续期新证书的时候使用的CSR不变,那么新证书的公钥指纹也依然会保持不变。
2.2 生成Profile文件
④ 登记App信息
这里主要是在华为开发者平台上登记一下App的各项信息,跟着文档中心来即可:
需要注意的是,包名填写的时候,平台会在线检查一下是否和已经存在的包名有重复(包括其他人申请的包名)。申请成功以后,会分配一个唯一的APP ID:
这个APP ID用来在网站上标识APP的唯一性。后面文章中会出现类似的名称,为了消除歧义,相似的字段用括号内容区分,这里称为APP ID(网站)。
⑤ 生成Profile文件
Profile文件是描述App的包名、签名、申请的权限列表、安装包类型、可安装设备等信息的文件(类似iOS的Provisioning Profile),签名后保存为Cryptographic Message Syntax格式(CMS,扩展的PKCS#7/格式,CMS定义在RFC 5652,PKCS#7定义在RFC 2315。)
跟着文档中心,选择之前的APP ID(网站)和证书,可以得到对应的Profile文件:
2.3 生成签名的App
⑥ 得到签名的App包
将生成的Profile文件、叶子证书文件等配置到项目的signingConfigs里,使用华为的IDE可以直接得到签名后的App包:
或者developtools_hapsigner: hapsigner | 应用签名工具手动给未签名的App包进行签名。
得到的签名的App包只是用于提供给华为商店进行审核和后续的拆包,并不能直接安装到手机上运行。App包实际上就是标准的ZIP格式,可以修改后缀为.zip进行解压:
可以看到里面包括了.hap包和描述App一些信息的pack.info文件。
那么对App包进行签名的内容以及Profile文件在哪里呢?根据对源码里VerifyHap.java类的verifyHap函数进行分析,发现鸿蒙上的签名机制类似Android V3,签名信息和Profile文件存储在自定义的HapSigningBlock区,放到了ZIP格式Central Directory区的前面,其结构如下:
HapSigningBlock区的魔数(转成string也就是):
/** * The value of lower 8 bytes of magic word */ public static final long HAP_SIG_BLOCK_MAGIC_LO_V3 = 0x676973207061683cL; /** * The value of higher 8 bytes of magic word */ public static final long HAP_SIG_BLOCK_MAGIC_HI_V3 = 0x3e6b636f6c62206eL; /** * Size of hap signature block header */ public static final int HAP_SIG_BLOCK_HEADER_SIZE = 32;通过hex工具直接打开App包也可以在Central Directory区前面找到:
其中SignatureSchemeBlock区存放了CMS格式的Hap包签名信息,而Profile文件就存储在SigningBlock区,Type是0x20000002:
/** * ID of profile block */ public static final int HAP_PROFILE_BLOCK_ID = 0x20000002;通过如下hap-sign-tool.jar的命令可以导出存储在App包或Hap包里的签名证书和Profile文件:
java -jar hap-sign-tool.jar verify-app -inFile my-signed.app -outCertChain my-signed.cer -outProfile my-signed.p7b⑦ 签名校验、拆包、重签名
这里再和之前的证书对比一下(红色和黄色底色表示内容分别相同):
三者的根证书都一样,Profile签名证书和Hap签名证书的中间证书一样,三者的叶子证书均不一样。
另外,如果在上架应用市场的时候,勾选了加密:
根据《文档中心》描述,只是对Hap包里的代码做加密,然后重新签名,所以证书和Profile文件的解析均不受影响。
3. 校验机制
签名相关的代码在security_appverify仓库里,签名校验流程梳理如下(图上所有判断条件在失败情况下均会导致签名校验失败,为了直观不画出此流程):
签名校验步骤可以分成三组,分别是:
SignatureSchemeBlock区校验。Profile校验和解析。Hap包完整性校验。
3.1 SignatureSchemeBlock区校验
校验Hap包时首先在ZIP的Central Directory区前32个字节寻找是否有HapSigningBlock区的Header,找到以后定位到SignatureSchemeBlock区,解析其CMS格式,并校验SignatureSchemeBlock区证书链的完整性。证书链完整性校验流程如下:
校验叶子证书时,需要按证书指定算法重新计算证书的hash,并使用上一级证书(中间证书)的公钥对叶子证书里的证书签名进行解密,与重新计算的hash比对是否相同,相同则认为证书可信。中间证书继续通过根证书的公钥校验自己的证书签名。根证书用自己的公钥校验自己。
我们走应用市场分发的Hap包会匹配到Huawei App Gallery这个证书。
3.2 Profile解析和校验
接下来在SigningBlock区寻找Profile,这里注意到不同Hap包签名方式会影响Profile的存储格式。对于走应用市场分发的Hap包,Profile是直接把其配置以字符串的格式保存,而对于其他情况,则是用CMS的格式保存。那么应用市场分发的Hap包也就不需要Profile的文件签名校验了。
对于其他情况,首先会使用Profile里保存的叶子证书公钥校验Profile的文件签名,然后会校验叶子证书Subject是否和匹配的同组内Profile签名证书Subject相同。
校验通过后解析Profile里的配置信息,根据type不同走不同的校验逻辑:
调试,会校验待安装的设备UDID是否在Profile的device-ids列表中。都校验通过后,再继续看Profile文件签名证书和Hap的签名正式是否相同,并继续对Profile配置的字段规则合法性进行检测。走完这一步,就可以认为Profile是可信的。
随后会生成App ID(公钥)和Fingerprint两个新的字段和验证结果一并返回。其中APP ID(公钥)是根据Profile配置里开发者签名证书公钥生成的(详见GenerateAppId函数),fingerprint是根据Profile配置里开发者签名证书直接计算整个证书的指纹(注意不是上一章的公钥指纹,详见GenerateFingerprint函数)。至此完成Profile的解析和校验。
另外,在文档中心中,会返回三个参数:
其中API返回的appId为了消除歧义,这里称为APP ID(接口)。
根据包管理子系统bundle_install_checker.cpp的ParseHapFiles函数、inner_bundle_info.h的SetProvisionId函数和这个PR来看:
// bundle_install_checker.cpp newInfo.SetProvisionId(provisionInfo.appId); // inner_bundle_info.h void SetProvisionId(const std::string &provisionId) { baseBundleInfo_->appId = baseBundleInfo_->name + Constants::FILE_UNDERLINE + provisionId; }APP ID(接口)的值实际上是APP ID(公钥)加上了{bundleName}_的前缀。
3.3 Hap包完整性校验
这一步的过程和Hap包签名类似,将ZIP包中数据和HapSigningBlock区里非SignatureSchemeBlock的部分拼接,重新计算hash,与使用Hap签名叶子证书公钥解密SignatureSchemeBlock区签名后的hash比较,相同则认为Hap包未被篡改。具体可以参考interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp · OpenHarmony/security_appverify – Gitee.com,这里就不展开了。
总结
从鸿蒙单框架应用的签名和校验机制的种种细节中可以看出,HarmonyOS NEXT的安全设计非常务实,融合了Anroid和iOS双端的特性,有借鉴Android成熟的部分(签名格式),但更多的是参考了iOS的设计思路(双层签名机制),甚至更加严格。期待HarmonyOS NEXT给我们带来一个新的未来。
阅读更多
用户评论
莫阑珊
终于有人写了关于鸿蒙应用签名的具体步骤和机制!我一直在找这种信息很久了,之前很多资料都过于抽象,不太好理解。这篇文章非常详细,通俗易懂,让我对这个重要的概念有了深入的了解!
有11位网友表示赞同!
疲倦了
看标题直接知道这是一篇硬核文章,毕竟是“实操”和“机制探究”。我比较好奇鸿蒙应用签名的安全性到底怎么样?会不会出现像其他系统的类似漏洞?
有16位网友表示赞同!
眼角有泪°
我最近在学习鸿蒙OS开发,正好碰上这篇文章。这篇博文内容丰富,对签名机制的分析很到位,让我明白了为什么签名这么重要, 对提高应用安全性和信任度有关键作用!
有14位网友表示赞同!
雁過藍天
文章写的不错,但个人感觉有些专业术语用词较多,不太适合入门小白阅读。能把一些更基础的概念解释清楚一点就好了!
有18位网友表示赞同!
笑叹★尘世美
终于看到一篇深入细致的鸿蒙应用签名指南了!之前网上关于这个方面的资料比较少见,这篇博文很及时也很有价值,希望能吸引更多开发者关注和学习!
有13位网友表示赞同!
疯人疯语疯人愿
写这篇文章的人水平很高啊,对技术理解很透彻,把复杂的概念解释得清晰易懂。对于想深入了解鸿蒙OS架构的用户来说,这绝对是一篇必读文章!
有18位网友表示赞同!
暮染轻纱
感觉这篇文章太理论了,能不能举一些具体的应用场景来讲解?这样更容易理解和记忆!
有17位网友表示赞同!
陌離
鸿蒙OS发展越来越快,学习相关的技术也很重要。这篇博文让我了解到应用程序签名的重要性,以后開發app的时候会更加重视安全性和可靠性!
有7位网友表示赞同!
*巴黎铁塔
对这个话题很有想法,但感觉文章的表达有点过于单调,可以加入一些图片或图表来增强可读性!
有11位网友表示赞同!
稳妥
希望能看到作者针对不同开发经验级别写的鸿蒙应用签名教程。对于初学者来说,一篇基础入门指南会更有帮助!
有7位网友表示赞同!
君临臣
作为一名软件工程师,我对这个标题非常感兴趣。很期待这篇博文能提供关于鸿蒙应用签名的详细解释和实践案例!
有15位网友表示赞同!
温柔腔
文章分析得很到位,但我觉得对于一些不太熟悉技术基础的用户来说,某些概念的解释可能不够全面。可以考虑在文中添加更多解释和示例!
有6位网友表示赞同!
命里缺他
学习鸿蒙OS开发一直是我的目标,这篇博文正好提供了一些关键信息。现在我对应用签名的机制有了更深刻的理解!
有20位网友表示赞同!
青墨断笺み
说实话,我平时不太关注技术细节,但这篇文章写的很有意思,让我对鸿蒙OS的安全性有了新的认识!
有15位网友表示赞同!
巷雨优美回忆
我对应用安全的重视程度非常高,所以对这篇博文非常感兴趣。希望作者能够继续分享更多关于鸿蒙系统的安全知识!
有12位网友表示赞同!
我就是这样一个人
感谢作者分享这种宝贵的经验和知识!对于想要深入学习鸿蒙OS开发的开发者来说,这篇文章非常实用!
有15位网友表示赞同!
全网暗恋者
文章写得不错,但缺少一些实践相关的教程或代码示例。如果有这些内容,相信会更加吸引读者!
有8位网友表示赞同!
西瓜贩子
我觉得这篇文章最大的作用在于能够让人明白应用签名的重要性和意义。希望更多的开发者都能重视这个环节,提高应用程序的安全性!
有20位网友表示赞同!