diff --git a/README.en.md b/README.en.md deleted file mode 100644 index d7c32c6498f0da8d135f6dfda2bae9f6b9fe34b1..0000000000000000000000000000000000000000 --- a/README.en.md +++ /dev/null @@ -1,63 +0,0 @@ -# developtools_hapsigner - -* Description -* Installation -* Instructions -* Auto generate script - -#### Description -In order to ensure the integrity and reliability of the OpenHarmony application, the application needs to be signed when the application is built, so that the application can be installed, run, and debugged on a real device. This warehouse provides a jar toolkit with functions such as certificate generation and hap package signature. -#### Installation -1. Clone this git -2. Configure the operating environment :Gradle 7.1, JDK 8 -3. Command to locate developtools_hapsigner/hapsigntool/ -4. Compile project with **gradle build** or **gradle jar** -5. You can find jar at ./hap_sign_tool/build/libs/hap_sign_tool-xxxx.jar - - -#### Instructions -Command example: - -```shell -java -jar -``` - -Complete usage example: -```shell -java -jar hap_sign_tool.jar generate-csr -keyAlias "oh-app1-key-v1" -keyPwd ***** -subject "C=CN,O=OpenHarmony,OU=OpenHarmony Community,CN=App1 Release" -signAlg SHA256withECDSA -keystoreFile "D:\OH\ohtest.jks" -keystorePwd ***** -outFile "D:\OH\oh-app1-key-v1.csr" -``` -You can also use -help to view the complete instructions -```shell -java -jar hap_sign_tool.jar -help -``` -**** -#### Auto generate script -You can also find a script in **autosign** folder -* start_create.sh/start_create.bat -* start_sign.sh/start_sign.bat -* auto_sign_main.py -* auto_sign.conf - -Steps: -1. Environment python3.x is required -2. Also related hap_sign_tool.jar -3. Get your unsigned hap package and Provision profile templates -4. Edit auto_sign.conf and replace it with your information -5. Run start_create.sh and start_sign.sh in Linux os -6. Or run start_create.bat and start_sign.bat in Window os - -**** - -#### Command description: - -* generate-keypair : generate key pair -* generate-csr : generate certificate signing request -* generate-cert : generate certificate in full, large and complete, any certificate can be generated -* generate-ca : generate root/subject CA certificate, if the key does not exist, generate the key together -* generate-app-cert : generate application debug/release certificate -* generate-profile-cert : generate application debug/release certificate -* sign-profile : Provision Profile file signature -* verify-profile : Provision Profile file verification -* sign-app : application package signature -* verify-app : application package file verification - diff --git a/README.md b/README.md index 553dede0144eb51437c5392a26b1417e2890ea14..d7c32c6498f0da8d135f6dfda2bae9f6b9fe34b1 100644 --- a/README.md +++ b/README.md @@ -1,183 +1,63 @@ -# Hap包签名工具 +# developtools_hapsigner -* 介绍 -* 安装教程 -* 使用说明 -* 一键签名脚本 -* (附)命令说明 +* Description +* Installation +* Instructions +* Auto generate script -#### 介绍 -为了保证OpenHarmony应用的完整性和来源可靠,在应用构建时需要对应用进行签名,才能在使用真机设备上安装、运行和调试该应用。本仓提供了一个具有证书生成、hap包签名等功能的jar工具包。 +#### Description +In order to ensure the integrity and reliability of the OpenHarmony application, the application needs to be signed when the application is built, so that the application can be installed, run, and debugged on a real device. This warehouse provides a jar toolkit with functions such as certificate generation and hap package signature. +#### Installation +1. Clone this git +2. Configure the operating environment :Gradle 7.1, JDK 8 +3. Command to locate developtools_hapsigner/hapsigntool/ +4. Compile project with **gradle build** or **gradle jar** +5. You can find jar at ./hap_sign_tool/build/libs/hap_sign_tool-xxxx.jar -#### 安装教程 -1. 配置编译环境 :Gradle 7.1,JDK 8 -2. 下载代码 -3. 命令行打开文件至developtools_hapsigner/hapsigntool目录下 -4. **gradle build** 或 **gradle jar**编译生成jar -5. 文件在./hap_sign_tool/build/libs/hap_sign_tool-xxxx.jar -#### 使用说明 -命令示例: +#### Instructions +Command example: ```shell -java -jar <签名工具.jar> <命令> <参数...> +java -jar ``` -完整使用示例: +Complete usage example: ```shell java -jar hap_sign_tool.jar generate-csr -keyAlias "oh-app1-key-v1" -keyPwd ***** -subject "C=CN,O=OpenHarmony,OU=OpenHarmony Community,CN=App1 Release" -signAlg SHA256withECDSA -keystoreFile "D:\OH\ohtest.jks" -keystorePwd ***** -outFile "D:\OH\oh-app1-key-v1.csr" ``` - -也可以使用 -help 查看完整使用说明 +You can also use -help to view the complete instructions ```shell java -jar hap_sign_tool.jar -help ``` **** - -#### 一键签名脚本 -使用一键签名脚本,免于输入繁杂的命令 - -打开本项目子目录autosign可见: +#### Auto generate script +You can also find a script in **autosign** folder * start_create.sh/start_create.bat * start_sign.sh/start_sign.bat * auto_sign_main.py * auto_sign.conf -操作流程 -1. 脚本依赖环境python3.x -2. 脚本依赖hap_sign_tool.jar(参照上文编译生成的产物) -3. 准备好待签名的应用hap包和Provision profile模板文件 -4. 使用文本编辑器编辑auto_sign.conf,补全配置文件中的配置 -5. Linux运行start_create.sh、Windows运行start_create.bat生成签名所需文件 -6. Linux运行start_sign.sh、Windows运行start_sign.bat对hap包进行签名 +Steps: +1. Environment python3.x is required +2. Also related hap_sign_tool.jar +3. Get your unsigned hap package and Provision profile templates +4. Edit auto_sign.conf and replace it with your information +5. Run start_create.sh and start_sign.sh in Linux os +6. Or run start_create.bat and start_sign.bat in Window os **** -#### (附)命令说明: -##### 生成密钥对 -* generate-keypair : 生成密钥对 - * -keyAlias : 密钥别名,必填项; - * -keyPwd : 密钥口令,可选项; - * -keyAlg : 密钥算法,必填项,包括RSA/ECC; - * -keySize : 密钥长度,必填项,RSA算法的长度为2048/3072/4096,ECC算法的长度NIST-P-256/NIST-P-384; - * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; - * -keystorePwd : 密钥库口令,可选项; - -##### 生成证书签名请求 -* generate-csr : 生成证书签名请求 - * -keyAlias : 密钥别名,必填项; - * -keyPwd : 密钥口令,可选项; - * -subject : 证书主题,必填项; - * -signAlg : 签名算法,必填项,包括SHA256withRSA / SHA384withRSA / SHA256withECDSA / SHA384withECDSA; - * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; - * -keystorePwd : 密钥库口令,可选项; - * -outFile : 输出文件,可选项,如果不填,则直接输出到控制台; - -##### 生成根CA/子CA证书 -* generate-ca : 生成根CA/子CA证书,如果密钥不存在,一起生成密钥 - * -keyAlias : 密钥别名,必填项; - * -keyPwd : 密钥口令,可选项; - * -keyAlg : 密钥算法,必填项,包括RSA/ECC; - * -keySize : 密钥长度,必填项,RSA算法的长度为2048/3072/4096,ECC算法的长度NIST-P-256/NIST-P-384; - * -issuer : 颁发者的主题,可选项,如果不填,表示根CA - * -issuerKeyAlias : 颁发者的密钥别名,可选项,如果不填,表示根CA; - * -issuerKeyPwd : 颁发者的密钥口令,可选项 - * -subject : 证书主题,必填项; - * -validity : 证书有效期,可选项,默认为3650天; - * -signAlg : 签名算法,必填项,包括SHA256withRSA / SHA384withRSA / SHA256withECDSA / SHA384withECDSA; - * -basicConstraintsPathLen : 路径长度,可选项,默认为0; - * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; - * -keystorePwd : 密钥库口令,可选项; - * -outFile : 输出证书文件,可选项,如果不填,则直接输出到控制台; - -##### 生成应用调试/发布证书 -* generate-app-cert : 生成应用调试/发布证书 - * -keyAlias : 密钥别名,必填项; - * -keyPwd : 密钥口令,可选项; - * -issuer : 颁发者的主题,必填项; - * -issuerKeyAlias : 颁发者的密钥别名,必填项; - * -issuerKeyPwd : 颁发者的密钥口令,可选项; - * -subject : 证书主题,必填项; - * -validity : 证书有效期,可选项,默认为1095天; - * -signAlg : 签名算法,必填项,包括SHA256withRSA / SHA384withRSA / SHA256withECDSA / SHA384withECDSA; - * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; - * -keystorePwd : 密钥库口令,可选项; - * -outForm: 输出证书文件的格式,包括 cert / certChain,可选项,默认为cert; - * -rootCaCertFile: outForm为certChain时必填,根CA证书文件; - * -subCaCertFile: outForm为certChain时必填,二级子CA证书文件; - * -outFile : 输出证书文件(证书或证书链),可选项,如果不填,则直接输出到控制台; - -##### 生成应用调试/发布证书 -* generate-profile-cert : 生成profile调试/发布证书 - * -keyAlias : 密钥别名,必填项; - * -keyPwd : 密钥口令,可选项; - * -issuer : 颁发者的主题,必填项; - * -issuerKeyAlias : 颁发者的密钥别名,必填项; - * -issuerKeyPwd : 颁发者的密钥口令,可选项; - * -subject : 证书主题,必填项; - * -validity : 证书有效期,可选项,默认为1095天; - * -signAlg : 签名算法,必填项,包括SHA256withRSA / SHA384withRSA / SHA256withECDSA / SHA384withECDSA; - * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; - * -keystorePwd : 密钥库口令,可选项; - * -outForm: 输出证书文件的格式,包括 cert / certChain,可选项,默认为cert; - * -rootCaCertFile: outForm为certChain时必填,根CA证书文件; - * -subCaCertFile: outForm为certChain时必填,二级子CA证书文件; - * -outFile : 输出证书文件(证书或证书链),可选项,如果不填,则直接输出到控制台; - -##### 通用证书生成,可以生成自定义证书 -* generate-cert : 通用证书生成,可以生成自定义证书 - * -keyAlias : 密钥别名,必填项; - * -keyPwd : 密钥口令,可选项; - * -issuer : 颁发者的主题,必填项; - * -issuerKeyAlias : 颁发者的密钥别名,必填项; - * -issuerKeyPwd : 颁发者的密钥口令,可选项; - * -subject : 证书主题,必填项; - * -validity : 证书有效期,可选项,默认为1095天; - * -keyUsage : 密钥用法,必选项,包括digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, certificateSignature, crlSignature, encipherOnly和decipherOnly,如果证书包括多个密钥用法,用逗号分隔; - * -keyUsageCritical : keyUsage是否为关键项,可选项,默认为是; - * -extKeyUsage : 扩展密钥用法,可选项,包括clientAuthentication,serverAuthentication,codeSignature,emailProtection,smartCardLogin,timestamp,ocspSignature; - * -extKeyUsageCritical : extKeyUsage是否为关键项,可选项,默认为否; - * -signAlg : 签名算法,必填项,包括SHA256withRSA / SHA384withRSA / SHA256withECDSA / SHA384withECDSA; - * -basicConstraints : 是否包含basicConstraints,可选项,默认为否; - * -basicConstraintsCritical : basicConstraints是否包含为关键项,可选项,默认为否; - * -basicConstraintsCa : 是否为CA,可选项,默认为否; - * -basicConstraintsPathLen : 路径长度,可选项,默认为0; - * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; - * -keystorePwd : 密钥库口令,可选项; - * -outFile : 输出证书文件,可选项,如果不填,则直接输出到控制台; - -##### ProvisionProfile文件签名 -* sign-profile : ProvisionProfile文件签名 - * -mode : 签名模式,必填项,包括localSign,remoteSign; - * -keyAlias : 密钥别名,必填项; - * -keyPwd : 密钥口令,可选项; - * -profileCertFile : Profile签名证书(证书链,顺序为三级-二级-根),必填项; - * -inFile : 输入的原始Provision Profile文件,必填项; - * -signAlg : 签名算法,必填项,包括SHA256withRSA / SHA384withRSA / SHA256withECDSA / SHA384withECDSA; - * -keystoreFile : 密钥库文件,localSign模式时为必填项,JKS或P12格式; - * -keystorePwd : 密钥库口令,可选项; - * -outFile : 输出签名后的Provision Profile文件,p7b格式,必填项; -##### ProvisionProfile文件验签 -* verify-profile : ProvisionProfile文件验签 - * -inFile:已签名的Provision Profile文件,p7b格式,必填项; - * -outFile:验证结果文件(包含验证结果和profile内容),json格式,可选项;如果不填,则直接输出到控制台; +#### Command description: -##### hap应用包签名 -* sign-app : hap应用包签名 - * -mode:签名模式,必填项,包括localSign,remoteSign,remoteResign; - * -keyAlias:密钥别名,必填项; - * -keyPwd:密钥口令,可选项; - * -appCertFile:应用签名证书文件(证书链,顺序为三级-二级-根),必填项; - * -profileFile:签名后的Provision Profile文件名,p7b格式,必填项; - * -inFile:输入的原始APP包文件,hap格式或bin格式,必填项; - * -signAlg:签名算法,必填项,包括SHA256withRSA / SHA384withRSA / SHA256withECDSA / SHA384withECDSA; - * -keystoreFile:密钥库文件,localSign模式时为必填项,JKS或P12格式; - * -keystorePwd: 密钥库口令,可选项; - * -outFile: 输出签名后的包文件,必填项; +* generate-keypair : generate key pair +* generate-csr : generate certificate signing request +* generate-cert : generate certificate in full, large and complete, any certificate can be generated +* generate-ca : generate root/subject CA certificate, if the key does not exist, generate the key together +* generate-app-cert : generate application debug/release certificate +* generate-profile-cert : generate application debug/release certificate +* sign-profile : Provision Profile file signature +* verify-profile : Provision Profile file verification +* sign-app : application package signature +* verify-app : application package file verification -##### hap应用包文件验签 -* verify-app : hap应用包文件验签 - * -inFile:已签名的应用包文件,hap格式或bin格式,必填项; - * -outCertchain:签名的证书链文件,必填项; - * -outProfile:应用包中的profile文件,必填项; - \ No newline at end of file diff --git a/README_ZH.md b/README_ZH.md new file mode 100644 index 0000000000000000000000000000000000000000..e0a20590d1c37903edeb6560a8e4d8cc9051d742 --- /dev/null +++ b/README_ZH.md @@ -0,0 +1,185 @@ +# Hap包签名工具 + +* 介绍 +* 安装教程 +* 使用说明 +* 一键签名脚本 +* (附)命令说明 + +#### 介绍 +为了保证OpenHarmony应用的完整性和来源可靠,在应用构建时需要对应用进行签名,才能在使用真机设备上安装、运行和调试该应用。本仓提供了一个具有证书生成、hap包签名等功能的jar工具包。 + +#### 安装教程 +1. 配置编译环境 :Gradle 7.1,JDK 8 +2. 下载代码 +3. 命令行打开文件至developtools_hapsigner/hapsigntool目录下 +4. **gradle build** 或 **gradle jar**编译生成jar +5. 文件在./hap_sign_tool/build/libs/hap_sign_tool-xxxx.jar + +#### 使用说明 +命令示例: + +```shell +java -jar <签名工具.jar> <命令> <参数...> +``` + +完整使用示例: +```shell +java -jar hap_sign_tool.jar generate-csr -keyAlias "oh-app1-key-v1" -keyPwd ***** -subject "C=CN,O=OpenHarmony,OU=OpenHarmony Community,CN=App1 Release" -signAlg SHA256withECDSA -keystoreFile "D:\OH\ohtest.jks" -keystorePwd ***** -outFile "D:\OH\oh-app1-key-v1.csr" +``` + +也可以使用 -help 查看完整使用说明 +```shell +java -jar hap_sign_tool.jar -help +``` +**** + +#### 一键签名脚本 +使用一键签名脚本,免于输入繁杂的命令 + +打开本项目子目录autosign可见: +* start_create.sh/start_create.bat +* start_sign.sh/start_sign.bat +* auto_sign_main.py +* auto_sign.conf + +操作流程 +1. 脚本依赖环境python3.x +2. 脚本依赖hap_sign_tool.jar(参照上文编译生成的产物) +3. 准备好待签名的应用hap包和Provision profile模板文件 +4. 使用文本编辑器编辑auto_sign.conf,补全配置文件中的配置 +5. Linux运行start_create.sh、Windows运行start_create.bat生成签名所需文件 +6. Linux运行start_sign.sh、Windows运行start_sign.bat对hap包进行签名 + +**** +#### (附)命令说明: +##### 生成密钥对 +* generate-keypair : 生成密钥对 + * -keyAlias : 密钥别名,必填项; + * -keyPwd : 密钥口令,可选项; + * -keyAlg : 密钥算法,必填项,包括RSA/ECC; + * -keySize : 密钥长度,必填项,RSA算法的长度为2048/3072/4096,ECC算法的长度NIST-P-256/NIST-P-384; + * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; + * -keystorePwd : 密钥库口令,可选项; + +##### 生成证书签名请求 +* generate-csr : 生成证书签名请求 + * -keyAlias : 密钥别名,必填项; + * -keyPwd : 密钥口令,可选项; + * -subject : 证书主题,必填项; + * -signAlg : 签名算法,必填项,包括SHA256withRSA / SHA384withRSA / SHA256withECDSA / SHA384withECDSA; + * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; + * -keystorePwd : 密钥库口令,可选项; + * -outFile : 输出文件,可选项,如果不填,则直接输出到控制台; + +##### 生成根CA/子CA证书 +* generate-ca : 生成根CA/子CA证书,如果密钥不存在,一起生成密钥 + * -keyAlias : 密钥别名,必填项; + * -keyPwd : 密钥口令,可选项; + * -keyAlg : 密钥算法,必填项,包括RSA/ECC; + * -keySize : 密钥长度,必填项,RSA算法的长度为2048/3072/4096,ECC算法的长度NIST-P-256/NIST-P-384; + * -issuer : 颁发者的主题,可选项,如果不填,表示根CA + * -issuerKeyAlias : 颁发者的密钥别名,可选项,如果不填,表示根CA; + * -issuerKeyPwd : 颁发者的密钥口令,可选项 + * -subject : 证书主题,必填项; + * -validity : 证书有效期,可选项,默认为3650天; + * -signAlg : 签名算法,必填项,包括SHA256withRSA / SHA384withRSA / SHA256withECDSA / SHA384withECDSA; + * -basicConstraintsPathLen : 路径长度,可选项,默认为0; + * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; + * -keystorePwd : 密钥库口令,可选项; + * -outFile : 输出证书文件,可选项,如果不填,则直接输出到控制台; + +##### 生成应用调试/发布证书 +* generate-app-cert : 生成应用调试/发布证书 + * -keyAlias : 密钥别名,必填项; + * -keyPwd : 密钥口令,可选项; + * -issuer : 颁发者的主题,必填项; + * -issuerKeyAlias : 颁发者的密钥别名,必填项; + * -issuerKeyPwd : 颁发者的密钥口令,可选项; + * -subject : 证书主题,必填项; + * -validity : 证书有效期,可选项,默认为1095天; + * -signAlg : 签名算法,必填项,包括SHA256withECDSA / SHA384withECDSA; + * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; + * -keystorePwd : 密钥库口令,可选项; + * -outForm: 输出证书文件的格式,包括 cert / certChain,可选项,默认为certChain; + * -rootCaCertFile: outForm为certChain时必填,根CA证书文件; + * -subCaCertFile: outForm为certChain时必填,二级子CA证书文件; + * -outFile : 输出证书文件(证书或证书链),可选项,如果不填,则直接输出到控制台; + +##### 生成应用调试/发布证书 +* generate-profile-cert : 生成profile调试/发布证书 + * -keyAlias : 密钥别名,必填项; + * -keyPwd : 密钥口令,可选项; + * -issuer : 颁发者的主题,必填项; + * -issuerKeyAlias : 颁发者的密钥别名,必填项; + * -issuerKeyPwd : 颁发者的密钥口令,可选项; + * -subject : 证书主题,必填项; + * -validity : 证书有效期,可选项,默认为1095天; + * -signAlg : 签名算法,必填项,包括SHA256withECDSA / SHA384withECDSA; + * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; + * -keystorePwd : 密钥库口令,可选项; + * -outForm: 输出证书文件的格式,包括 cert / certChain,可选项,默认为certChain; + * -rootCaCertFile: outForm为certChain时必填,根CA证书文件; + * -subCaCertFile: outForm为certChain时必填,二级子CA证书文件; + * -outFile : 输出证书文件(证书或证书链),可选项,如果不填,则直接输出到控制台; + +##### 通用证书生成,可以生成自定义证书 +* generate-cert : 通用证书生成,可以生成自定义证书 + * -keyAlias : 密钥别名,必填项; + * -keyPwd : 密钥口令,可选项; + * -issuer : 颁发者的主题,必填项; + * -issuerKeyAlias : 颁发者的密钥别名,必填项; + * -issuerKeyPwd : 颁发者的密钥口令,可选项; + * -subject : 证书主题,必填项; + * -validity : 证书有效期,可选项,默认为1095天; + * -keyUsage : 密钥用法,必选项,包括digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, certificateSignature, crlSignature, encipherOnly和decipherOnly,如果证书包括多个密钥用法,用逗号分隔; + * -keyUsageCritical : keyUsage是否为关键项,可选项,默认为是; + * -extKeyUsage : 扩展密钥用法,可选项,包括clientAuthentication,serverAuthentication,codeSignature,emailProtection,smartCardLogin,timestamp,ocspSignature; + * -extKeyUsageCritical : extKeyUsage是否为关键项,可选项,默认为否; + * -signAlg : 签名算法,必填项,包括SHA256withRSA / SHA384withRSA / SHA256withECDSA / SHA384withECDSA; + * -basicConstraints : 是否包含basicConstraints,可选项,默认为否; + * -basicConstraintsCritical : basicConstraints是否包含为关键项,可选项,默认为否; + * -basicConstraintsCa : 是否为CA,可选项,默认为否; + * -basicConstraintsPathLen : 路径长度,可选项,默认为0; + * -keystoreFile : 密钥库文件,必填项,JKS或P12格式; + * -keystorePwd : 密钥库口令,可选项; + * -outFile : 输出证书文件,可选项,如果不填,则直接输出到控制台; + +##### ProvisionProfile文件签名 +* sign-profile : ProvisionProfile文件签名 + * -mode : 签名模式,必填项,包括localSign,remoteSign; + * -keyAlias : 密钥别名,必填项; + * -keyPwd : 密钥口令,可选项; + * -profileCertFile : Profile签名证书(证书链,顺序为三级-二级-根),必填项; + * -inFile : 输入的原始Provision Profile文件,必填项; + * -signAlg : 签名算法,必填项,包括SHA256withECDSA / SHA384withECDSA; + * -keystoreFile : 密钥库文件,localSign模式时为必填项,JKS或P12格式; + * -keystorePwd : 密钥库口令,可选项; + * -outFile : 输出签名后的Provision Profile文件,p7b格式,必填项; + +##### ProvisionProfile文件验签 +* verify-profile : ProvisionProfile文件验签 + * -inFile:已签名的Provision Profile文件,p7b格式,必填项; + * -outFile:验证结果文件(包含验证结果和profile内容),json格式,可选项;如果不填,则直接输出到控制台; + +##### hap应用包签名 +* sign-app : hap应用包签名 + * -mode:签名模式,必填项,包括localSign,remoteSign,remoteResign; + * -keyAlias:密钥别名,必填项; + * -keyPwd:密钥口令,可选项; + * -appCertFile:应用签名证书文件(证书链,顺序为三级-二级-根),必填项; + * -profileFile:签名后的Provision Profile文件名,p7b格式,必填项; + * -profileSigned:指示profile文件是否带有签名,1表示有签名,0表示没有签名,默认为1。可选项; + * -inForm:输入的原始文件的格式,zip格式或bin格式,默认zip格式;可选项; + * -inFile:输入的原始APP包文件,hap格式或bin格式,必填项; + * -signAlg:签名算法,必填项,包括SHA256withECDSA / SHA384withECDSA; + * -keystoreFile:密钥库文件,localSign模式时为必填项,JKS或P12格式; + * -keystorePwd: 密钥库口令,可选项; + * -outFile: 输出签名后的包文件,必填项; + +##### hap应用包文件验签 +* verify-app : hap应用包文件验签 + * -inFile:已签名的应用包文件,hap格式或bin格式,必填项; + * -outCertchain:签名的证书链文件,必填项; + * -outProfile:应用包中的profile文件,必填项; + \ No newline at end of file diff --git a/autosign/README.md b/autosign/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ea2d1a2aeb467f49f1171910c9e721d81838be3a --- /dev/null +++ b/autosign/README.md @@ -0,0 +1,45 @@ +# Instructions +Autosign help you to sign app more efficiently + + +## Dependency +This signature script depends on Python 3.x. + + + +## Configuration + +Use your favorite text editor to open `autosign.config` to configure everything. +Below config must be replaced: +* config.signtool +* All password + +### 1. For Windows + +1. Run the `start_creat.bat` file in the terminal to generate certs. +2. Prepare your unsigned app and provision profile. Make sure correct config file location. +3. Run the `start_sign.bat` file in the terminal to start signing. +4. The generated artifacts will be saved in the folder you set in `config.targetDir` as default. + +### 2. For Linux or MacOS + + +1. Add executable permission into `start_create.sh` and `start_sign.sh`. + + ```bash + chmod a+x start_sign.sh + + chmod a+x start_create.sh + ``` + +2. Run the `start_create.sh` file in the terminal to generate certs. + + ```bash + ./start_create.sh + ``` +3. Prepare your unsigned app and provision profile. Make sure correct config file location. +4. Run the `start_sign.sh` file in the terminal to start signing. + ```bash + ./start_sign.sh + ``` +5. The generated artifacts will be saved in the folder you set in `config.targetDir` as default. diff --git a/autosign/autosign.config b/autosign/autosign.config new file mode 100644 index 0000000000000000000000000000000000000000..08725d333c57d485cf3c5debe6bb5fa9d806dd24 --- /dev/null +++ b/autosign/autosign.config @@ -0,0 +1,90 @@ +// Base configuration +// +// Location of signtool.jar +config.signtool=../hapsigntool/hap_sign_tool/build/libs/hap_sign_tool-1.0-SNAPSHOT.jar +// All products would be put into folder +config.targetDir=result + +// Common configuration, will be overwrite by detail config +common.keystoreFile=ohtest.jks +common.keystorePwd=123456 +common.keyAlg=ECC +common.keySize=NIST-P-256 +common.signAlg=SHA256withECDSA +common.validity=365 +common.outForm=certChain +common.mode=localSign + +// You must change this instead of using default +common.keyPwd=123456 +common.issuerKeyPwd=123456 + +// keypair of app signature +app.keypair.keyAlias=oh-app1-key-v1 +app.keypair.keyPwd=123456 + +// keypair of profile signature +profile.keypair.keyAlias=oh-profile1-key-v1 +profile.keypair.keyPwd=123456 + +// Csr +csr.keyAlias=oh-app1-key-v1 +csr.subject=C=CN,O=OpenHarmony,OU=OpenHarmony Community,CN=App1 Release +csr.outFile=oh-app1-key-v1.csr + +// Root CA +root-ca.keyAlias=oh-root-ca-key-v1 +root-ca.subject=C=CN,O=OpenHarmony,OU=OpenHarmony Community,CN=Root CA +root-ca.outFile=root-ca1.cer + +// Sub APP CA +sub-ca.app.keyAlias=oh-app-sign-srv-ca-key-v1 +sub-ca.app.subject=C=CN,O=OpenHarmony,OU=OpenHarmony Community,CN= Application Signature Service CA +sub-ca.app.outFile=app-sign-srv-ca1.cer + +// Sub Profile CA +sub-ca.profile.keyAlias=oh-profile-sign-srv-ca-key-v1 +sub-ca.profile.subject=C=CN,O=OpenHarmony,OU=OpenHarmony Community,CN= Profile Signature Service CA +sub-ca.profile.outFile=profile-sign-srv-ca1.cer + +// App signature cert +cert.app.subject=C=CN,O=OpenHarmony,OU=OpenHarmony Community,CN=App1 Release +cert.app.outFile=app1.pem + +// Profile signature cert +cert.profile.subject=C=CN,O=OpenHarmony,OU=OpenHarmony Community,CN=Profile1 Release +cert.profile.outFile=profile1.pem + +// Sign profile +sign.profile.inFile=app1-profile-release.json +sign.profile.outFile=app1-profile.p7b + +// Sign app +sign.app.inFile=app1-unsigned.hap +sign.app.outFile=app1-signed.hap + + +// Default config. Do not change it +sub-ca.app.issuer=$root-ca.subject +sub-ca.app.issuerKeyAlias=$root-ca.keyAlias +sub-ca.profile.issuer=$root-ca.subject +sub-ca.profile.issuerKeyAlias=$root-ca.keyAlias + +cert.app.keyAlias=$app.keypair.keyAlias +cert.app.issuer=$sub-ca.app.subject +cert.app.issuerKeyAlias=$sub-ca.app.keyAlias +cert.app.rootCaCertFile=$root-ca.outFile +cert.app.subCaCertFile=$sub-ca.app.outFile + +cert.profile.keyAlias=$profile.keypair.keyAlias +cert.profile.issuer=$sub-ca.profile.subject +cert.profile.issuerKeyAlias=$sub-ca.profile.keyAlias +cert.profile.rootCaCertFile=$root-ca.outFile +cert.profile.subCaCertFile=$sub-ca.profile.outFile + +sign.profile.keyAlias=$profile.keypair.keyAlias +sign.profile.profileCertFile=$cert.profile.outFile + +sign.app.keyAlias=$app.keypair.keyAlias +sign.app.appCertFile=$cert.app.outFile +sign.app.profileFile=$sign.profile.outFile diff --git a/autosign/autosign.py b/autosign/autosign.py new file mode 100644 index 0000000000000000000000000000000000000000..c4e8484cadeaa5de6650c0973f3153b59bddff1c --- /dev/null +++ b/autosign/autosign.py @@ -0,0 +1,220 @@ +############################################## +# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################## + +import os +import re +import sys +from subprocess import Popen +from subprocess import PIPE + +global_config = {} + +templates = { + 'generate-keypair': { + 'required': ['keyAlias', 'keyAlg', 'keySize', 'keystoreFile'], + 'others': ['keyPwd', 'keystorePwd'] + }, + 'generate-csr': { + 'required': ['keyAlias', 'signAlg', 'subject', 'keystoreFile', 'outFile'], + 'others': ['keyPwd', 'keystorePwd'] + }, + 'generate-ca': { + 'required': ['keyAlias', 'signAlg', 'keyAlg', 'keySize', 'subject', 'keystoreFile', 'outFile'], + 'others': ['keyPwd', 'keystorePwd', 'issuer', 'issuerKeyAlias', 'issuerKeyPwd', 'validity', + 'basicConstraintsPathLen'] + }, + 'generate-app-cert': { + 'required': ['keyAlias', 'signAlg', 'keyAlg', 'keySize', 'issuer', 'issuerKeyAlias', 'subject', 'keystoreFile', + 'subCaCertFile', 'rootCaCertFile', 'outForm', 'outFile'], + 'others': ['keyPwd', 'keystorePwd', 'issuerKeyPwd', 'validity', + 'basicConstraintsPathLen'] + }, + 'generate-profile-cert': { + 'required': ['keyAlias', 'signAlg', 'keyAlg', 'keySize', 'issuer', 'issuerKeyAlias', 'subject', 'keystoreFile', + 'subCaCertFile', 'rootCaCertFile', 'outForm', 'outFile'], + 'others': ['keyPwd', 'keystorePwd', 'issuerKeyPwd', 'validity', + 'basicConstraintsPathLen'] + }, + 'sign-profile': { + 'required': ['keyAlias', 'signAlg', 'mode', 'profileCertFile', 'inFile', 'keystoreFile', 'outFile'], + 'others': ['keyPwd', 'keystorePwd'] + }, + 'sign-app': { + 'required': ['keyAlias', 'signAlg', 'mode', 'appCertFile', 'profileFile', 'inFile', 'keystoreFile', 'outFile'], + 'others': ['keyPwd', 'keystorePwd'] + }, +} + + +def print_help(): + content = "\n" \ + "Usage:python autosign.py \n" \ + " signtool.jar : Main progress jar file\n" \ + "\n" \ + "Example: \n" \ + " python autosign.py generate \n" \ + " python autosign.py sign" \ + "\n" + print(content) + + +def get_from_single_config(config_key, item_key, required=False): + param = global_config.get(config_key, {}).get(item_key, None) + if not param: + param = global_config.get('common', {}).get(item_key, None) + if not param: + if required: + print('Prepare loading: {}, config: {}'.format(config_key, global_config.get(config_key))) + print("Params {} is required.".format(item_key)) + exit(1) + return param + + +def prepare_dir(dir_name): + if not os.path.exists(dir_name): + os.mkdir(dir_name) + + +def load_engine(engine_config): + tar_dir = global_config.get('config', {}).get('targetDir') + prepare_dir(tar_dir) + + cmds = [] + for eng_k, eng_v in engine_config.items(): + template = templates.get(eng_v) + cmd = eng_v + for required_key in template.get('required'): + param = get_from_single_config(eng_k, required_key, True) + if required_key.endswith('File') and required_key != 'inFile' and os.path.basename(param) == param: + param = os.path.join(tar_dir, param) + cmd = '{} -{} "{}"'.format(cmd, required_key, param) + + for others_key in template.get('others'): + param = get_from_single_config(eng_k, others_key, False) + if param: + cmd = '{} -{} "{}"'.format(cmd, others_key, param) + cmds.append(cmd) + return cmds + + +def run_target(cmd): + command = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE, shell=True) + out = command.stdout.readlines() + with open("log.txt", mode='a+') as f: + if len(out) > 0: + f.writelines(cmd + "\r\n") + for line in out: + f.writelines(str(line.strip()) + "\r\n") + + success = True + error = command.stderr.readlines() + with open("error.txt", mode='a+') as f: + if len(error) > 0: + f.writelines(cmd + "\r\n") + + for line in error: + success = False + f.writelines(str(line.strip()) + "\r\n") + + command.wait() + return success + + +def run_with_engine(engine, jar): + cmds = load_engine(engine) + for cmd in cmds: + result = run_target('java -jar {} {}'.format(jar, cmd)) + if not result: + print("Command error on executing cmd, please check error.txt") + print(cmd) + exit(1) + print("Success!") + pass + + +def do_sign(jar): + sign_engine_config = { + 'sign.profile': 'sign-profile', + 'sign.app': 'sign-app' + } + run_with_engine(sign_engine_config, jar) + + +def do_generate(jar): + cert_engine_config = { + 'app.keypair': 'generate-keypair', + 'profile.keypair': 'generate-keypair', + 'csr': 'generate-csr', + 'root-ca': 'generate-ca', + 'sub-ca.app': 'generate-ca', + 'sub-ca.profile': 'generate-ca', + 'cert.app': 'generate-app-cert', + 'cert.profile': 'generate-profile-cert', + } + run_with_engine(cert_engine_config, jar) + + +def convert_to_map(line, temp_map): + line = line.strip('\n') + strs = line.split('=', 1) + + if len(strs) == 2: + if strs[1].startswith('$'): + temp_map[strs[0]] = temp_map[strs[1][1:]] + else: + temp_map[strs[0]] = strs[1] + + +def load_config(): + config_file = 'autosign.config' + temp_map = {} + with open(config_file, 'r') as f: + for line in f.readlines(): + if not re.match(r'\s*//[\s\S]*', line): + convert_to_map(line, temp_map) + + for mk, mv in temp_map.items(): + strs = mk.rsplit('.', 1) + if not global_config.get(strs[0]): + global_config[strs[0]] = {} + global_config[strs[0]][strs[-1]] = mv + + +def process_cmd(): + args = sys.argv + if len(args) <= 1 or '--help' == args[1] or '-h' == args[1]: + print_help() + exit(0) + + action = args[1] + if action not in ['generate', 'sign']: + print("Not support cmd") + print_help() + exit(1) + return action + + +if __name__ == '__main__': + act = process_cmd() + load_config() + jar_file = global_config.get('config', {}).get('signtool') + if not os.path.exists(jar_file): + print("Jar file '{}' not found".format(jar_file)) + exit(1) + + if act == 'generate': + do_generate(jar_file) + elif act == 'sign': + do_sign(jar_file) diff --git a/autosign/start_create.bat b/autosign/start_create.bat new file mode 100644 index 0000000000000000000000000000000000000000..d43c1fafd7c8367eed2519ec0243c7580163c6a2 --- /dev/null +++ b/autosign/start_create.bat @@ -0,0 +1,15 @@ +@rem Copyright (c) 2021-2022 Huawei Device Co., Ltd. +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. + +python autosign.py generate +pause \ No newline at end of file diff --git a/autosign/start_create.sh b/autosign/start_create.sh new file mode 100644 index 0000000000000000000000000000000000000000..abe4940c6786f6f64bfb3ea24e0c0a126497df35 --- /dev/null +++ b/autosign/start_create.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +python3 autosign.py generate \ No newline at end of file diff --git a/autosign/start_sign.bat b/autosign/start_sign.bat new file mode 100644 index 0000000000000000000000000000000000000000..b8f9bcd51c648cbba6d675660067e7e631c432cc --- /dev/null +++ b/autosign/start_sign.bat @@ -0,0 +1,15 @@ +@rem Copyright (c) 2021-2022 Huawei Device Co., Ltd. +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. + +python autosign.py sign +pause \ No newline at end of file diff --git a/autosign/start_sign.sh b/autosign/start_sign.sh new file mode 100644 index 0000000000000000000000000000000000000000..9a56b7a7d10f8ce62ca9cd2343ffb533c1425b97 --- /dev/null +++ b/autosign/start_sign.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +python3 autosign.py sign \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool/src/main/java/com/ohos/hapsigntool/HapSignTool.java b/hapsigntool/hap_sign_tool/src/main/java/com/ohos/hapsigntool/HapSignTool.java index f8a5c02c09acd9cde5f8ead4329875180a3f3d93..564cbe5b5b6ff9ba0c836c717a21b9bb5fcb817c 100644 --- a/hapsigntool/hap_sign_tool/src/main/java/com/ohos/hapsigntool/HapSignTool.java +++ b/hapsigntool/hap_sign_tool/src/main/java/com/ohos/hapsigntool/HapSignTool.java @@ -54,6 +54,14 @@ public final class HapSignTool { * Remote sign. */ private static final String REMOTE_SIGN = "remoteSign"; + /** + * Signed. + */ + private static final int SIGNED = 1; + /** + * No signed. + */ + private static final int NOT_SIGNED = 0; private HapSignTool() { } @@ -158,7 +166,7 @@ public final class HapSignTool { params.required(Options.KEY_ALIAS, Options.ISSUER, Options.ISSUER_KEY_ALIAS, Options.SUBJECT, Options.SIGN_ALG, Options.KEY_STORE_FILE); String signAlg = params.getString(Options.SIGN_ALG); - CmdUtil.judgeSignAlgType(signAlg); + CmdUtil.judgeEndSignAlgType(signAlg); String outForm = params.getString(Options.OUT_FORM); if (!StringUtils.isEmpty(outForm)) { CmdUtil.verifyType(outForm, Options.OUT_FORM_SCOPE); @@ -209,10 +217,11 @@ public final class HapSignTool { } private static boolean runCsr(Options params, ServiceApi api) { - params.required(Options.KEY_ALIAS, Options.SUBJECT, Options.SIGN_ALG, Options.KEY_STORE_FILE); + params.required(Options.KEY_ALIAS, Options.SUBJECT, Options.SIGN_ALG, Options.KEY_STORE_FILE, Options.OUT_FILE); String signAlg = params.getString(Options.SIGN_ALG); CmdUtil.judgeSignAlgType(signAlg); FileUtils.validFileType(params.getString(Options.KEY_STORE_FILE), "p12", "jks"); + FileUtils.validFileType(params.getString(Options.OUT_FILE), "csr"); return api.generateCsr(params); } @@ -249,10 +258,16 @@ public final class HapSignTool { String profileFile = params.getString(Options.PROFILE_FILE); FileUtils.validFileType(profileFile, "p7b"); - String infile = params.getString(Options.IN_FILE); - FileUtils.validFileType(infile, "hap", "bin", "zip"); + int profileSigned = params.getInt(Options.PROFILE_SIGNED, SIGNED); + if (profileSigned != SIGNED && profileSigned != NOT_SIGNED) { + CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, "profileSigned params is incorrect"); + } + String inForm = params.getString(Options.IN_FORM); + if (!StringUtils.isEmpty(inForm) && !"zip".equalsIgnoreCase(inForm) && !"bin".equalsIgnoreCase(inForm)) { + CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, "inForm params is incorrect"); + } String signAlg = params.getString(Options.SIGN_ALG); - CmdUtil.judgeSignAlgType(signAlg); + CmdUtil.judgeEndSignAlgType(signAlg); FileUtils.validFileType(params.getString(Options.KEY_STORE_FILE), "p12", "jks"); return api.signHap(params); @@ -270,7 +285,7 @@ public final class HapSignTool { } String signAlg = params.getString(Options.SIGN_ALG); - CmdUtil.judgeSignAlgType(signAlg); + CmdUtil.judgeEndSignAlgType(signAlg); String outFile = params.getString(Options.OUT_FILE); FileUtils.validFileType(outFile, "p7b"); diff --git a/hapsigntool/hap_sign_tool/src/main/java/com/ohos/hapsigntoolcmd/CmdUtil.java b/hapsigntool/hap_sign_tool/src/main/java/com/ohos/hapsigntoolcmd/CmdUtil.java index d9cc73c2cebdae8c32439b2f9ea1a31f080023b2..66ee8515d8acb0f7f34a08632c09e50cb72c188f 100644 --- a/hapsigntool/hap_sign_tool/src/main/java/com/ohos/hapsigntoolcmd/CmdUtil.java +++ b/hapsigntool/hap_sign_tool/src/main/java/com/ohos/hapsigntoolcmd/CmdUtil.java @@ -144,6 +144,19 @@ public final class CmdUtil { } } + /** + * Sign alg must in the scope. + * + * @param signAlg sign alg + */ + public static void judgeEndSignAlgType(String signAlg) { + List arrayList = Arrays.asList("SHA256withECDSA", "SHA384withECDSA"); + if (!arrayList.contains(signAlg)) { + CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, + "SignAlg params is incorrect, signature algorithms include SHA256withECDSA,SHA384withECDSA"); + } + } + /** * verifyType. * diff --git a/hapsigntool/hap_sign_tool/src/test/java/com/ohos/hapsigntoolcmd/CmdUnitTest.java b/hapsigntool/hap_sign_tool/src/test/java/com/ohos/hapsigntoolcmd/CmdUnitTest.java index 3ac4917618be646251a1b95c144a60ee200f1a16..202738b535750871e568339d061bae78cab9d136 100644 --- a/hapsigntool/hap_sign_tool/src/test/java/com/ohos/hapsigntoolcmd/CmdUnitTest.java +++ b/hapsigntool/hap_sign_tool/src/test/java/com/ohos/hapsigntoolcmd/CmdUnitTest.java @@ -183,6 +183,10 @@ public class CmdUnitTest { * Command line parameter RSA is 2048. */ public static final String CMD_RSA_2048 = "2048"; + /** + * Command line parameter ECC is 256. + */ + public static final String CMD_ECC_256 = "NIST-P-256"; /** * Command line parameter validity is 365. */ @@ -196,9 +200,9 @@ public class CmdUnitTest { */ public static final String CMD_LOCAL_SIGN = "localSign"; /** - * Command line parameter SHA256withRSA. + * Command line parameter SHA256withECDSA. */ - public static final String CMD_SHA_256_WITH_RSA = "SHA256withRSA"; + public static final String CMD_SHA_256_WITH_ECDSA = "SHA256withECDSA"; /** * Command line parameter cer file is test_app-debug-cert. */ @@ -323,8 +327,8 @@ public class CmdUnitTest { CmdUtil.Method.GENERATE_KEYPAIR, CMD_KEY_ALIAS, CMD_OH_APP1_KEY_V1, CMD_KEY_RIGHTS, CMD_RIGHTS_123456, - CMD_KEY_ALG, KeyPairTools.RSA, - CMD_KEY_SIZE, CMD_RSA_2048, + CMD_KEY_ALG, KeyPairTools.ECC_INPUT, + CMD_KEY_SIZE, CMD_ECC_256, CMD_KEY_STORE_FILE, CMD_KEY_APP_STORE_PATH, CMD_KEY_STORE_RIGHTS, CMD_RIGHTS_123456}); assertTrue(result); @@ -334,8 +338,8 @@ public class CmdUnitTest { CmdUtil.Method.GENERATE_KEYPAIR, CMD_KEY_ALIAS, CMD_OH_PROFILE_KEY_V1, CMD_KEY_RIGHTS, CMD_RIGHTS_123456, - CMD_KEY_ALG, KeyPairTools.RSA, - CMD_KEY_SIZE, CMD_RSA_2048, + CMD_KEY_ALG, KeyPairTools.ECC_INPUT, + CMD_KEY_SIZE, CMD_ECC_256, CMD_KEY_STORE_FILE, CMD_KEY_PROFILE_STORE_PATH, CMD_KEY_STORE_RIGHTS, CMD_RIGHTS_123456}); assertTrue(result); @@ -366,7 +370,7 @@ public class CmdUnitTest { CMD_KEY_ALIAS, CMD_OH_APP1_KEY_V1, CMD_KEY_RIGHTS, CMD_RIGHTS_123456, CMD_SUBJECT, CMD_APP1_RELEASE, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA, + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA, CMD_KEY_STORE_FILE, CMD_KEY_APP_STORE_PATH, CMD_KEY_STORE_RIGHTS, CMD_RIGHTS_123456, CMD_OUT_FILE, CMD_CSR_PATH}); @@ -398,7 +402,7 @@ public class CmdUnitTest { CMD_KEY_ALIAS, CMD_OH_APP1_KEY_V1, CMD_KEY_RIGHTS, CMD_RIGHTS_123456, CMD_ISSUER, CMD_APP_CA, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA, + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA, CMD_KEY_STORE_FILE, CMD_KEY_APP_STORE_PATH, CMD_KEY_STORE_RIGHTS, CMD_RIGHTS_123456, CMD_OUT_FILE, CMD_CERT_PATH, @@ -492,7 +496,7 @@ public class CmdUnitTest { CMD_OUT_FORM, CMD_CERT_CHAIN, CMD_ROOT_CA_CERT_FILE, CMD_ROOT_APP_CA_PATH, CMD_SUB_CA_CERT_FILE, CMD_SUB_APP_CA_PATH, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA}); + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA}); assertTrue(result); assertTrue(FileUtils.isFileExist(CMD_APP_DEBUG_CERT_PATH)); deleteFile(CMD_APP_RELEASE_CERT_PATH); @@ -511,7 +515,7 @@ public class CmdUnitTest { CMD_OUT_FORM, CMD_CERT_CHAIN, CMD_ROOT_CA_CERT_FILE, CMD_ROOT_APP_CA_PATH, CMD_SUB_CA_CERT_FILE, CMD_SUB_APP_CA_PATH, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA}); + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA}); assertTrue(result); assertTrue(FileUtils.isFileExist(CMD_APP_RELEASE_CERT_PATH)); } @@ -550,7 +554,7 @@ public class CmdUnitTest { CMD_OUT_FORM, CMD_CERT_CHAIN, CMD_ROOT_CA_CERT_FILE, CMD_ROOT_PROFILE_CA_PATH, CMD_SUB_CA_CERT_FILE, CMD_SUB_PROFILE_CA_PATH, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA}); + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA}); assertTrue(result); assertTrue(FileUtils.isFileExist(CMD_PROFILE_DEBUG_CERT_PATH)); deleteFile(CMD_PROFILE_RELEASE_CERT_PATH); @@ -569,7 +573,7 @@ public class CmdUnitTest { CMD_OUT_FORM, CMD_CERT_CHAIN, CMD_ROOT_CA_CERT_FILE, CMD_ROOT_PROFILE_CA_PATH, CMD_SUB_CA_CERT_FILE, CMD_SUB_PROFILE_CA_PATH, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA}); + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA}); assertTrue(result); assertTrue(FileUtils.isFileExist(CMD_PROFILE_RELEASE_CERT_PATH)); } @@ -601,7 +605,7 @@ public class CmdUnitTest { CMD_KEY_RIGHTS, CMD_RIGHTS_123456, CMD_PROFILE_CERT_FILE, CMD_PROFILE_RELEASE_CERT_PATH, CMD_IN_FILE, CMD_JSON_FILE, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA, + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA, CMD_KEY_STORE_FILE, CMD_KEY_PROFILE_STORE_PATH, CMD_KEY_STORE_RIGHTS, CMD_RIGHTS_123456, CMD_OUT_FILE, CMD_SIGN_PROFILE_PATH}); @@ -662,14 +666,14 @@ public class CmdUnitTest { CmdUtil.Method.GENERATE_CA, CMD_KEY_ALIAS, CMD_OH_ROOT_CA_KEY_V1, CMD_KEY_RIGHTS, CMD_RIGHTS_123456, - CMD_KEY_ALG, KeyPairTools.RSA, - CMD_KEY_SIZE, CMD_RSA_2048, + CMD_KEY_ALG, KeyPairTools.ECC_INPUT, + CMD_KEY_SIZE, CMD_ECC_256, CMD_KEY_STORE_FILE, CMD_KEY_APP_STORE_PATH, CMD_KEY_STORE_RIGHTS, CMD_RIGHTS_123456, CMD_OUT_FILE, CMD_ROOT_APP_CA_PATH, CMD_SUBJECT, CMD_ROOT_CA, CMD_VALIDITY, CMD_VALIDITY_365, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA, + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA, CMD_BASIC_CONSTRAINTS_PATH_LEN, CMD_BC_PATH_LEN_0}); return result; } @@ -679,14 +683,14 @@ public class CmdUnitTest { CmdUtil.Method.GENERATE_CA, CMD_KEY_ALIAS, CMD_OH_ROOT_CA_KEY_V1, CMD_KEY_RIGHTS, CMD_RIGHTS_123456, - CMD_KEY_ALG, KeyPairTools.RSA, - CMD_KEY_SIZE, CMD_RSA_2048, + CMD_KEY_ALG, KeyPairTools.ECC_INPUT, + CMD_KEY_SIZE, CMD_ECC_256, CMD_KEY_STORE_FILE, CMD_KEY_PROFILE_STORE_PATH, CMD_KEY_STORE_RIGHTS, CMD_RIGHTS_123456, CMD_OUT_FILE, CMD_ROOT_PROFILE_CA_PATH, CMD_SUBJECT, CMD_ROOT_CA, CMD_VALIDITY, CMD_VALIDITY_365, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA, + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA, CMD_BASIC_CONSTRAINTS_PATH_LEN, CMD_BC_PATH_LEN_0}); return result; } @@ -697,8 +701,8 @@ public class CmdUnitTest { CMD_KEY_ALIAS, CMD_OH_SUB_APP_CA_KEY_V1, CMD_KEY_RIGHTS, CMD_RIGHTS_123456, CMD_ISSUER, CMD_ROOT_CA, - CMD_KEY_ALG, KeyPairTools.RSA, - CMD_KEY_SIZE, CMD_RSA_2048, + CMD_KEY_ALG, KeyPairTools.ECC_INPUT, + CMD_KEY_SIZE, CMD_ECC_256, CMD_KEY_STORE_FILE, CMD_KEY_APP_STORE_PATH, CMD_KEY_STORE_RIGHTS, CMD_RIGHTS_123456, CMD_OUT_FILE, CMD_SUB_APP_CA_PATH, @@ -706,7 +710,7 @@ public class CmdUnitTest { CMD_ISSUER_KEY_RIGHTS, CMD_RIGHTS_123456, CMD_SUBJECT, CMD_APP_CA, CMD_VALIDITY, CMD_VALIDITY_365, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA, + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA, CMD_BASIC_CONSTRAINTS_PATH_LEN, CMD_BC_PATH_LEN_0}); return result; } @@ -717,8 +721,8 @@ public class CmdUnitTest { CMD_KEY_ALIAS, CMD_OH_SUB_PROFILE_CA_KEY_V1, CMD_KEY_RIGHTS, CMD_RIGHTS_123456, CMD_ISSUER, CMD_ROOT_CA, - CMD_KEY_ALG, KeyPairTools.RSA, - CMD_KEY_SIZE, CMD_RSA_2048, + CMD_KEY_ALG, KeyPairTools.ECC_INPUT, + CMD_KEY_SIZE, CMD_ECC_256, CMD_KEY_STORE_FILE, CMD_KEY_PROFILE_STORE_PATH, CMD_KEY_STORE_RIGHTS, CMD_RIGHTS_123456, CMD_OUT_FILE, CMD_SUB_PROFILE_CA_PATH, @@ -726,7 +730,7 @@ public class CmdUnitTest { CMD_ISSUER_KEY_RIGHTS, CMD_RIGHTS_123456, CMD_SUBJECT, CMD_PROFILE_CA, CMD_VALIDITY, CMD_VALIDITY_365, - CMD_SIGN_ALG, CMD_SHA_256_WITH_RSA, + CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA, CMD_BASIC_CONSTRAINTS_PATH_LEN, CMD_BC_PATH_LEN_0}); return result; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/LocalizationAdapter.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/LocalizationAdapter.java index a1556a23e56ef7991d7c09c5182ce1fa5e81e9d5..e93c23f0aff5ab55c3f07a2fc87b2675388cfffe 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/LocalizationAdapter.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/LocalizationAdapter.java @@ -210,7 +210,7 @@ public class LocalizationAdapter { * @return is out form chain */ public boolean isOutFormChain() { - String outForm = options.getString(Options.OUT_FORM, "cert"); + String outForm = options.getString(Options.OUT_FORM, "certChain"); return outForm.equals("certChain"); } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/SignToolServiceImpl.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/SignToolServiceImpl.java index 191c401e11ea5683008b6f9bcf1c092dc500c14d..f619f0ef1d91989cfb73f19082f48884f0999189 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/SignToolServiceImpl.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/SignToolServiceImpl.java @@ -57,6 +57,14 @@ public class SignToolServiceImpl implements ServiceApi { Security.addProvider(new BouncyCastleProvider()); } + /** + * App signing Capabilty Bytes. + */ + private static final byte[] APP_SIGNING_CAPABILITY = {0x30, 0x06, 0x02, 0x01, 0x01, 0x0A, 0x01, 0x00}; + /** + * Profile signing Capabilty Bytes. + */ + private static final byte[] PROFILE_SIGNING_CAPABILITY = {0x30, 0x06, 0x02, 0x01, 0x01, 0x0A, 0x01, 0x01}; /** * Logger. */ @@ -162,7 +170,22 @@ public class SignToolServiceImpl implements ServiceApi { */ @Override public boolean generateAppCert(Options options) { - return generateProfileCert(options); + LocalizationAdapter adapter = new LocalizationAdapter(options); + KeyPair keyPair = adapter.getAliasKey(false); + KeyPair issueKeyPair = adapter.getIssuerAliasKey(); + adapter.releasePwd(); + + byte[] csr = CertTools.generateCsr(keyPair, adapter.getSignAlg(), adapter.getSubject()); + X509Certificate cert = CertTools.generateEndCert(issueKeyPair, csr, adapter, APP_SIGNING_CAPABILITY); + if (adapter.isOutFormChain()) { + List certificates = new ArrayList<>(); + certificates.add(cert); + certificates.add(adapter.getSubCaCertFile()); + certificates.add(adapter.getCaCertFile()); + return outputCertChain(certificates, adapter.getOutFile()); + } else { + return outputCert(cert, adapter.getOutFile()); + } } /** @@ -179,7 +202,7 @@ public class SignToolServiceImpl implements ServiceApi { adapter.releasePwd(); byte[] csr = CertTools.generateCsr(keyPair, adapter.getSignAlg(), adapter.getSubject()); - X509Certificate cert = CertTools.generateEndCert(issueKeyPair, csr, adapter); + X509Certificate cert = CertTools.generateEndCert(issueKeyPair, csr, adapter, PROFILE_SIGNING_CAPABILITY); if (adapter.isOutFormChain()) { List certificates = new ArrayList<>(); certificates.add(cert); @@ -262,11 +285,11 @@ public class SignToolServiceImpl implements ServiceApi { } //The type of file is bin or hap - String inFile = options.getString(Options.IN_FILE); - if (inFile.endsWith(".bin")) { - return signProvider.signBin(options); - } else { + String inForm = options.getString(Options.IN_FORM, "zip"); + if ("zip".equalsIgnoreCase(inForm)) { return signProvider.sign(options); + } else { + return signProvider.signBin(options); } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/model/Options.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/model/Options.java index 42bbe70ceccaf7eef54d6da382ac5e9448c5a94f..e69a00ebe8cc67d4480e03bd16aadb4c2a64fa3f 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/model/Options.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/api/model/Options.java @@ -91,6 +91,10 @@ public class Options extends HashMap { * In file parameter name. */ public static final String IN_FILE = "inFile"; + /** + * In file parameter form. + */ + public static final String IN_FORM = "inForm"; /** * Issuer parameter name. */ @@ -162,6 +166,10 @@ public class Options extends HashMap { * Profile file parameter name. */ public static final String PROFILE_FILE = "profileFile"; + /** + * Profile file is signed or not. + */ + public static final String PROFILE_SIGNED = "profileSigned"; /** * Sign alg parameter name. */ diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/cert/CertBuilder.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/cert/CertBuilder.java index 2a67c8850296d12ed6feeb5af7b253a755b4269d..6b9a74dfb4357008bf2c705da8c9a717085a4b22 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/cert/CertBuilder.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/cert/CertBuilder.java @@ -21,6 +21,7 @@ import com.ohos.hapsigntool.error.ERROR; import com.ohos.hapsigntool.utils.CertUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.ExtendedKeyUsage; @@ -179,6 +180,20 @@ public class CertBuilder { return this; } + /** + * Add signingCapabilty for certificate builder. + * + * @param signingCapabiltyBytes signingCapabiltyBytes + * @return CertBuilder + * @throws CertIOException CertIOException + */ + public CertBuilder withSigningCapabilty(byte[] signingCapabiltyBytes) throws CertIOException { + ASN1ObjectIdentifier signingCapabiltyIdentifier = (new ASN1ObjectIdentifier("1.3.6.1.4.1.2011.2.376.1.3")) + .intern(); + x509v3CertificateBuilder.addExtension(signingCapabiltyIdentifier, false, signingCapabiltyBytes); + return this; + } + /** * build X509Certificate. * diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/cert/CertTools.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/cert/CertTools.java index eb38088e894184d14fcec9b7cecbefa77e08e734..60d46630e74bfaff26b237f9b45136a91e75b867 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/cert/CertTools.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/cert/CertTools.java @@ -161,7 +161,8 @@ public final class CertTools { * @param adapter adapter * @return X509Certificate */ - public static X509Certificate generateEndCert(KeyPair keyPair, byte[] csr, LocalizationAdapter adapter) { + public static X509Certificate generateEndCert(KeyPair keyPair, byte[] csr, LocalizationAdapter adapter, + byte[] signingCapabiltyBytes) { try { return new CertBuilder(keyPair, adapter.getIssuer(), csr, adapter.getOptions().getInt(Options.VALIDITY, THREE_YEAR_DAY)) @@ -169,6 +170,7 @@ public final class CertTools { null) .withKeyUsages(new KeyUsage(KeyUsage.digitalSignature), true) .withExtKeyUsages(new KeyPurposeId[]{KeyPurposeId.id_kp_codeSigning}, false) + .withSigningCapabilty(signingCapabiltyBytes) .build(adapter.getSignAlg()); } catch (IOException exception) { LOGGER.debug(exception.getMessage(), exception); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/SignatureBlockTypes.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/SignatureBlockTypes.java index b0d01c8266fe1be32247d6de899248804f66e9da..b46345860c31b4e941616162995e00599753caf4 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/SignatureBlockTypes.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/SignatureBlockTypes.java @@ -38,4 +38,20 @@ public class SignatureBlockTypes { * type-value of key rotation block */ public static final char KEY_ROTATION_BLOCK = 3; + + /** + * get profile block type by the flag of isSigned + * + * @param isSigned the flag whether profile is signed + * @return profile block type value + */ + public static char getProfileBlockTypes(String isSigned) { + if (isSigned != null && isSigned.equals("0")) { + return PROFILE_NOSIGNED_BLOCK; + } + if (isSigned != null && isSigned.equals("1")) { + return PROFILE_SIGNED_BLOCK; + } + return PROFILE_NOSIGNED_BLOCK; + } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index 0ba76f10c33f96e649a446a38a4bdbd2b61c82cb..657c11d9878e638531150b5b743c44a0080a81cc 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -204,6 +204,27 @@ public abstract class SignProvider { return signerConfig; } + /** + * check profile signed in bin signed + * + * @param options inputted by user. + * @throws MissingParamsException Exception occurs when the required parameters are not entered. + */ + private void checkLiteParams(Options options) throws MissingParamsException { + String[] paramFileds = {ParamConstants.PARAM_BASIC_PROFILE_SIGNED}; + Set paramSet = ParamProcessUtil.initParamField(paramFileds); + + for (String paramKey : options.keySet()) { + if (paramSet.contains(paramKey)) { + signParams.put(paramKey, options.getString(paramKey)); + } + } + + if (!signParams.containsKey(ParamConstants.PARAM_BASIC_PROFILE_SIGNED)) { + signParams.put(ParamConstants.PARAM_BASIC_PROFILE_SIGNED, "1"); + } + } + /** * sign bin file * @@ -218,6 +239,8 @@ public abstract class SignProvider { // 1. check the parameters checkParams(options); + checkLiteParams(options); + // 2. load optionalBlocks loadOptionalBlocks(); @@ -510,17 +533,23 @@ public abstract class SignProvider { private void checkProfileValid(List inputCerts) throws ProfileException { try { byte[] profile = findProfileFromOptionalBlocks(); + boolean isProfileWithoutSign = ParamConstants.ProfileSignFlag.UNSIGNED_PROFILE.getSignFlag().equals( + signParams.get(ParamConstants.PARAM_BASIC_PROFILE_SIGNED)); String content; - CMSSignedData cmsSignedData = new CMSSignedData(profile); - boolean verifyResult = VerifyUtils.verifyCmsSignedData(cmsSignedData); - if (!verifyResult) { - throw new ProfileException("Verify profile pkcs7 failed! Profile is invalid."); - } - Object contentObj = cmsSignedData.getSignedContent().getContent(); - if (!(contentObj instanceof byte[])) { - throw new ProfileException("Check profile failed, signed profile content is not byte array!"); + if (!isProfileWithoutSign) { + CMSSignedData cmsSignedData = new CMSSignedData(profile); + boolean verifyResult = VerifyUtils.verifyCmsSignedData(cmsSignedData); + if (!verifyResult) { + throw new ProfileException("Verify profile pkcs7 failed! Profile is invalid."); + } + Object contentObj = cmsSignedData.getSignedContent().getContent(); + if (!(contentObj instanceof byte[])) { + throw new ProfileException("Check profile failed, signed profile content is not byte array!"); + } + content = new String((byte[]) contentObj, StandardCharsets.UTF_8); + } else { + content = new String(profile, StandardCharsets.UTF_8); } - content = new String((byte[]) contentObj, StandardCharsets.UTF_8); JsonElement parser = JsonParser.parseString(content); JsonObject profileJson = parser.getAsJsonObject(); checkProfileInfo(profileJson, inputCerts); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/sign/SignBin.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/sign/SignBin.java index d81be304aedccf58c20ac2572d512182a0dc752c..cc63783493f3f32e915aeebdee1b80e34ab78e33 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/sign/SignBin.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/sign/SignBin.java @@ -56,7 +56,8 @@ public class SignBin { String inputFile = signParams.get(ParamConstants.PARAM_BASIC_INPUT_FILE); String outputFile = signParams.get(ParamConstants.PARAM_BASIC_OUTPUT_FILE); String profileFile = signParams.get(ParamConstants.PARAM_BASIC_PROFILE); - if (!writeBlockDataToFile(inputFile, outputFile, profileFile)) { + String profileSigned = signParams.get(ParamConstants.PARAM_BASIC_PROFILE_SIGNED); + if (!writeBlockDataToFile(inputFile, outputFile, profileFile, profileSigned)) { LOGGER.error("The block head data made failed."); ParamProcessUtil.delDir(new File(outputFile)); return false; @@ -83,12 +84,13 @@ public class SignBin { } private static boolean writeBlockDataToFile( - String inputFile, String outputFile, String profileFile) { + String inputFile, String outputFile, String profileFile, String profileSigned) { try { long binFileLen = FileUtils.getFileLen(inputFile); long profileDataLen = FileUtils.getFileLen(profileFile); if (!checkBinAndProfileLengthIsValid(binFileLen, profileDataLen)) { - LOGGER.error("file length is invalid, binFileLen: " + binFileLen + " profileDataLen: " + profileDataLen); + LOGGER.error("file length is invalid, binFileLen: " + binFileLen + + " profileDataLen: " + profileDataLen); throw new IOException(); } @@ -97,9 +99,9 @@ public class SignBin { LOGGER.error("The profile block head offset is overflow interger range, offset: " + offset); throw new IOException(); } - char isSigned = SignatureBlockTypes.PROFILE_SIGNED_BLOCK; + char isSigned = SignatureBlockTypes.getProfileBlockTypes(profileSigned); byte[] proBlockByte = - HwBlockHead.getBlockHead(isSigned, SignatureBlockTags.DEFAULT, (short) profileDataLen, (int) offset); + HwBlockHead.getBlockHead(isSigned, SignatureBlockTags.DEFAULT, (short) profileDataLen, (int) offset); offset += profileDataLen; if (isLongOverflowInteger(offset)) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/verify/VerifyUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/verify/VerifyUtils.java index 939efab86d5318835eabe6d6499d062641564dbf..818eef00ca51ffa2937ec8606b2c06eb2d9875b6 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/verify/VerifyUtils.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/verify/VerifyUtils.java @@ -48,6 +48,7 @@ public class VerifyUtils { * @return true, if verify success * @throws CMSException if error occurs */ + @SuppressWarnings("unchecked") public static boolean verifyCmsSignedData(CMSSignedData cmsSignedData) throws CMSException { Store certs = cmsSignedData.getCertificates(); boolean verifyResult = cmsSignedData.verifySignatures(sid -> { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/profile/VerifyHelper.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/profile/VerifyHelper.java index f67e2886a1f8fe4a398eeb6b303f250f69d51473..d9bde1bf8904996e6567d0190c650dc54b2c4dd5 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/profile/VerifyHelper.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/profile/VerifyHelper.java @@ -79,6 +79,7 @@ public class VerifyHelper implements IProvisionVerifier { } } + @SuppressWarnings("unchecked") CMSSignedData verifyPkcs(byte[] p7b) { CMSSignedData cmsSignedData = null; try { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/CertUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/CertUtils.java index 23ffd73291de01147f770ad3e6b19626a29502ca..267c6f53794a528e02403391c2a6603c6aa72d24 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/CertUtils.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/CertUtils.java @@ -147,6 +147,7 @@ public final class CertUtils { return ids.toArray(new KeyPurposeId[]{}); } + @SuppressWarnings("unchecked") public static X500Name buildDN(String nameString) { ValidateUtils.throwIfNotMatches(!StringUtils.isEmpty(nameString), ERROR.COMMAND_ERROR, ""); @@ -255,6 +256,7 @@ public final class CertUtils { * @return Certs * @throws CertificateException Convert failed */ + @SuppressWarnings("unchecked") public static List generateCertificates(byte[] cert) throws CertificateException { CertificateFactory factory = CertificateFactory.getInstance("X.509"); List certificates = diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/CertificateUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/CertificateUtils.java index 2143fd39e6b8b132cc53ba52d329ba2e590321ec..77797e54f7fc8224eac2ca9e232b134c8eb766ea 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/CertificateUtils.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/CertificateUtils.java @@ -61,6 +61,7 @@ public class CertificateUtils { * @throws CertificateException data in file is not certificate * @throws VerifyCertificateChainException certificates in file are not certificate chain */ + @SuppressWarnings("unchecked") public static List getCertListFromFile(String certsFile) throws IOException, CertificateException, VerifyCertificateChainException { try (FileInputStream fileInputStream = FileUtils.openInputStream(new File(certsFile))) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/ParamConstants.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/ParamConstants.java index 5f0e87eaa189e019d7b2c1fd6a502c9cc718e764..3f0db8b9d36d5856a27eedef5ae1b25eb3758f24 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/ParamConstants.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/ParamConstants.java @@ -166,6 +166,11 @@ public class ParamConstants { */ public static final String PARAM_BASIC_SIGANTURE_ALG = "signAlg"; + /** + * Flag indicates whether profile is signed + */ + public static final String PARAM_BASIC_PROFILE_SIGNED = "profileSigned"; + /** * Url of signature server */ diff --git a/hapsigntool/hap_sign_tool_lib/src/test/java/com/ohos/hapsigntool/CertTest.java b/hapsigntool/hap_sign_tool_lib/src/test/java/com/ohos/hapsigntool/CertTest.java index df6db55d82171293c3c9125f3330381a39933285..a37ae857eaa30c5b2d36d18f7f4f07e85e4f6bf9 100644 --- a/hapsigntool/hap_sign_tool_lib/src/test/java/com/ohos/hapsigntool/CertTest.java +++ b/hapsigntool/hap_sign_tool_lib/src/test/java/com/ohos/hapsigntool/CertTest.java @@ -69,6 +69,10 @@ public class CertTest { * Params CN=App1 Release. */ public static final String APP1_RELEASE = "C=CN,O=OpenHarmony,OU=OpenHarmony Community,CN=App1 Release"; + /** + * App signing Capabilty Bytes. + */ + private static final byte[] APP_SIGNING_CAPABILITY = {0x30, 0x06, 0x02, 0x01, 0x01, 0x0A, 0x01, 0x00}; static { Security.addProvider(new BouncyCastleProvider()); @@ -170,7 +174,8 @@ public class CertTest { options.put(Options.ISSUER, APP_CA); options.put(Options.SIGN_ALG, SHA_384_WITH_RSA); options.put(Options.VALIDITY, VALIDITY_365); - X509Certificate appCert = CertTools.generateEndCert(keyPair, csr, new LocalizationAdapter(options)); + X509Certificate appCert = CertTools.generateEndCert(keyPair, csr, new LocalizationAdapter(options), + APP_SIGNING_CAPABILITY); try { appCert.verify(keyPair.getPublic()); } catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException @@ -189,7 +194,7 @@ public class CertTest { try { options.put(Options.ISSUER, null); options.put(Options.SIGN_ALG, ""); - appCert = CertTools.generateEndCert(keyPair, csr, new LocalizationAdapter(options)); + appCert = CertTools.generateEndCert(keyPair, csr, new LocalizationAdapter(options), APP_SIGNING_CAPABILITY); assertNull(appCert); } catch (Exception exception) { logger.info(exception, () -> exception.getMessage());