1# Development Guidelines on Application Signature Verification<a name="EN-US_TOPIC_0000001058671627"></a> 2 3- [When to Use](#section18502174174019) 4- [Signature Verification Process](#section554632717226) 5- [Available APIs](#section1633115419401) 6- [Development Procedure \(Scenario 1\)](#section4207112818418) 7 - [Signature Verification](#section11470123816297) 8 - [OpenHarmony Self-signed Application Generation](#section167151429133312) 9 - [Development Examples](#section174318361353) 10 11- [Development Procedure \(Scenario 2\)](#section81272563427) 12 - [Signature Verification](#section07028210442) 13 - [Development Examples](#section1930711345445) 14 15- [Debugging and Verification](#section427316292411) 16 17## When to Use<a name="section18502174174019"></a> 18 19You can call the APIs provided by the signature verification component to check integrity of a debugging, released, or OpenHarmony self-signed application. You can also call APIs of the signature verification component to obtain some information in the profile, for example, **appid**. In addition, you can call APIs to check whether the UDID of a debugging application matches that of the device to ensure that the application is installed on the right device. 20 21## Signature Verification Process<a name="section554632717226"></a> 22 23An unsigned HAP is in **.zip** format and consists of a file block, central directory, and end of central directory \(EOCD\). 24 25After the HAP is signed, a signature block is added between the file block and the central directory. The signature block consists of a file signature block, profile signature block, and signature header. The following figure shows the structure of a signed HAP. 26 27**Figure 1** Structure of a signed HAP<a name="fig699855043"></a> 28 29 30 31 32The signature verification process consists of three steps: HAP signature verification, signature verification for the profile signature block, and profile content verification. 33 34**HAP signature verification** 35 36Use the preset root certificate of the device and the certificate chain to prove that the leaf certificate is trusted. Then use the digest obtained by decrypting the public key of the leaf certificate to prove that the HAP is not tampered with. 37 38The process is as follows: 39 401. Use the preset root certificate of the device to verify the certificate chain in the file signature block and prove that the leaf certificate is trusted. 412. Use the public key in the leaf certificate to verify the file signature block and prove that this block is not tampered with. 423. Calculate and merge the digests of the file block, central directory, and EOCD. Merge the calculation result with the digest of the profile signature block in the signature block. Then compare the merge result with the digest of the file signature block. If they are the same, the HAP signature verification is successful. 43 44**Signature verification for the profile signature block** 45 46First of all, check who issued the signature of the profile signature block. If the signature was issued by the application market, the signature is trusted and does not need to be verified. Otherwise, the signature needs to be verified. Next, verify the certificate chain and then use the leaf certificate to verify the signature of the profile signature block to prove that it is not tampered with. 47 48**Profile content verification** 49 50Obtain the profile and check the validity of its content. If the HAP is a debugging application, check whether the UDID of the current device is contained in the UDID list in the profile. If yes, the verification is successful. Then compare the certificate in the profile with the leaf certificate used for HAP verification \(this is not required for a released or OpenHarmony self-signed application\). If they are the same, the entire signature verification process is complete. 51 52## Available APIs<a name="section1633115419401"></a> 53 54The following table lists the innerkits APIs provided by the signature verification component. These APIs are available only for system applications. 55 56**Table 1** APIs provided by the signature verification component 57 58<a name="table1731550155318"></a> 59<table><thead align="left"><tr id="row4419501537"><th class="cellrowborder" valign="top" width="57.38999999999999%" id="mcps1.2.3.1.1"><p id="p54150165315"><a name="p54150165315"></a><a name="p54150165315"></a>Function</p> 60</th> 61<th class="cellrowborder" valign="top" width="42.61%" id="mcps1.2.3.1.2"><p id="p941150145313"><a name="p941150145313"></a><a name="p941150145313"></a>Description</p> 62</th> 63</tr> 64</thead> 65<tbody><tr id="row34145016535"><td class="cellrowborder" valign="top" width="57.38999999999999%" headers="mcps1.2.3.1.1 "><p id="p122711391160"><a name="p122711391160"></a><a name="p122711391160"></a>int APPVERI_AppVerify(const char *filePath, VerifyResult *verifyRst)</p> 66</td> 67<td class="cellrowborder" valign="top" width="42.61%" headers="mcps1.2.3.1.2 "><p id="p13562171015712"><a name="p13562171015712"></a><a name="p13562171015712"></a>Verifies a signature by specifying the file path and returns the data obtained from the profile to the caller through <strong id="b7884251078"><a name="b7884251078"></a><a name="b7884251078"></a>verifyRst</strong>. This is the main entry function.</p> 68</td> 69</tr> 70<tr id="row1746172917474"><td class="cellrowborder" valign="top" width="57.38999999999999%" headers="mcps1.2.3.1.1 "><p id="p2131144717619"><a name="p2131144717619"></a><a name="p2131144717619"></a>int APPVERI_SetDebugMode(bool mode)</p> 71</td> 72<td class="cellrowborder" valign="top" width="42.61%" headers="mcps1.2.3.1.2 "><p id="p1577114614282"><a name="p1577114614282"></a><a name="p1577114614282"></a>Sets the debugging mode. If <strong id="b357165110811"><a name="b357165110811"></a><a name="b357165110811"></a>mode</strong> is set to <strong id="b425811565813"><a name="b425811565813"></a><a name="b425811565813"></a>true</strong>, certificate chain verification based on the debugging root key is enabled; if <strong id="b1846271515134"><a name="b1846271515134"></a><a name="b1846271515134"></a>mode</strong> is set to <strong id="b1646271551319"><a name="b1646271551319"></a><a name="b1646271551319"></a>false</strong>, it is disabled.</p> 73<p id="p2431455765"><a name="p2431455765"></a><a name="p2431455765"></a>Note: Currently, no certificate based on the existing debugging root key is available. You can replace the debugging root key and perform related verification as required.</p> 74</td> 75</tr> 76<tr id="row10992232154714"><td class="cellrowborder" valign="top" width="57.38999999999999%" headers="mcps1.2.3.1.1 "><p id="p685215538611"><a name="p685215538611"></a><a name="p685215538611"></a>void APPVERI_FreeVerifyRst(VerifyResult *verifyRst)</p> 77</td> 78<td class="cellrowborder" valign="top" width="42.61%" headers="mcps1.2.3.1.2 "><p id="p126575774517"><a name="p126575774517"></a><a name="p126575774517"></a>Releases memory in <strong id="b12392192921512"><a name="b12392192921512"></a><a name="b12392192921512"></a>verifyRst</strong>.</p> 79</td> 80</tr> 81</tbody> 82</table> 83 84## Development Procedure \(Scenario 1\)<a name="section4207112818418"></a> 85 86### Signature Verification<a name="section11470123816297"></a> 87 88To verify applications released in the application market, debugging applications signed with debugging certificates of the application market, and OpenHarmony self-signed applications, perform the following steps: 89 901. Construct the VerifyResult structure. 91 92 ``` 93 VerifyResult verifyResult = {0}; 94 ``` 95 962. Call the APPVERI\_AppVerify function by specifying the file path and VerifyResult to verify the application signature. 97 98 ``` 99 int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); 100 ``` 101 1023. Check the returned result. If the verification is successful, obtain and process the data in VerifyResult. 103 104 ``` 105 signatureInfo.appId = verifyResult.profile.appid; 106 signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; 107 ``` 108 1094. Call the APPVERI\_FreeVerifyRst function to release memory in VerifyResult. 110 111 ``` 112 APPVERI_FreeVerifyRst(&verifyResult); 113 ``` 114 115 116### OpenHarmony Self-signed Application Generation<a name="section167151429133312"></a> 117 118The procedure is as follows: 119 1201. Prepare required materials. 121 122 Prepare the signature tool, system application HAP, system application profile \(\*.p7b\), signing certificate \(\*.cer\), and signing public/private key pair \(\*.jks\). 123 1242. Place all the materials in the same directory and start the shell. 1253. Run the following command in the shell to sign the application: 126 127 ``` 128 java -jar hapsigntoolv2.jar sign -mode localjks -privatekey "OpenHarmony Software Signature" -inputFile camera.hap -outputFile signed_camera.hap -signAlg SHA256withECDSA -keystore OpenHarmony.jks -keystorepasswd 123456 -keyaliaspasswd 123456 -profile camera_release.p7b -certpath OpenHarmony.cer -profileSigned 1 129 ``` 130 131 Key fields: 132 133 **-jar**: signature tool, which is **[hapsigntool](https://repo.huaweicloud.com/harmonyos/develop_tools/hapsigntoolv2.jar)** 134 135 **-mode**: local signature flag, which is fixed at **localjks** 136 137 **-privatekey**: alias of the public/private key pair, which is **OpenHarmony Software Signature** 138 139 **-inputFile**: application to be signed, which is generated through compilation 140 141 **-outputFile**: signed application 142 143 **-signAlg**: signing algorithm, which is fixed at **SHA256withECDSA** 144 145 **-keystore**: public/private key pair, which is [OpenHarmony.jks](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.jks) in the **OpenHarmonyCer** directory of the **security\_services\_app\_verify** repository. The default password is **123456**. You can use a tool \(such as keytool\) to change the password. 146 147 **-keystorepasswd**: password of the public/private key pair, which is **123456** by default 148 149 **-keyaliaspasswd**: password of the public/private key pair alias, which is **123456** by default 150 151 **-profile**: application profile, which is stored in the code directory 152 153 **-certpath**: signing certificate, which is [OpenHarmony.cer](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.cer) in the **OpenHarmonyCer** directory of the **security\_services\_app\_verify** repository. 154 155 **-profileSigned**: whether the signature block contains the profile. The value is fixed at **1**, indicating that the signature block contains the profile. 156 157 158### Development Examples<a name="section174318361353"></a> 159 160The following example describes how the application management framework component verifies the signature of an application during its installation. 161 162``` 163uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) 164{ 165 bool mode = ManagerService::GetInstance().IsDebugMode(); 166 HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); 167 // Construct the VerifyResult structure. 168 VerifyResult verifyResult = {0}; 169 // Verify the signature by specifying the file path. 170 int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); 171 uint8_t errorCode = SwitchErrorCode(ret); 172 if (errorCode != ERR_OK) { 173 return errorCode; 174 } 175 // Obtain appid from the VerifyResult structure. 176 signatureInfo.appId = verifyResult.profile.appid; 177 // Obtain the application name written in the profile from the VerifyResult structure. 178 signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; 179 int32_t restricNum = verifyResult.profile.permission.restricNum; 180 for (int32_t i = 0; i < restricNum; i++) { 181 signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); 182 } 183 // Release memory in VerifyResult. 184 APPVERI_FreeVerifyRst(&verifyResult); 185 return ERR_OK; 186} 187``` 188 189## Development Procedure \(Scenario 2\)<a name="section81272563427"></a> 190 191### Signature Verification<a name="section07028210442"></a> 192 193To verify applications signed with certificates that are based on debugging root keys, perform the following steps: 194 1951. Call the APPVERI\_SetDebugMode\(true\) function to enable the debugging mode. 196 197 ``` 198 ManagerService::SetDebugMode(true); 199 ... 200 uint8_t ManagerService::SetDebugMode(bool enable) 201 { 202 int32_t ret = APPVERI_SetDebugMode(enable); 203 if (ret < 0) { 204 HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); 205 return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; 206 } 207 isDebugMode_ = enable; 208 HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); 209 return ERR_OK; 210 } 211 ``` 212 2132. Construct the **VerifyResult** structure, verify the application signature, and release memory in **VerifyResult**. 2143. Call the APPVERI\_SetDebugMode\(false\) function to disable the debugging mode. 215 216 ``` 217 ManagerService::SetDebugMode(false); 218 ``` 219 220 221### Development Examples<a name="section1930711345445"></a> 222 223The following is the example code \(supplemented based on the example code for scenario 1\): 224 225``` 226uint8_t ManagerService::SetDebugMode(bool enable) 227{ 228 int32_t ret = APPVERI_SetDebugMode(enable); 229 if (ret < 0) { 230 HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); 231 return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; 232 } 233 isDebugMode_ = enable; 234 HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); 235 return ERR_OK; 236} 237uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) 238{ 239 // Enable debugging mode. 240 ManagerService::SetDebugMode(true); 241 bool mode = ManagerService::GetInstance().IsDebugMode(); 242 HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); 243 // Construct the VerifyResult structure. 244 VerifyResult verifyResult = {0}; 245 // Verify the signature by specifying the file path. 246 int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); 247 uint8_t errorCode = SwitchErrorCode(ret); 248 if (errorCode != ERR_OK) { 249 return errorCode; 250 } 251 // Obtain appid from the VerifyResult structure. 252 signatureInfo.appId = verifyResult.profile.appid; 253 // Obtain the application name written in the profile from the VerifyResult structure. 254 signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; 255 int32_t restricNum = verifyResult.profile.permission.restricNum; 256 for (int32_t i = 0; i < restricNum; i++) { 257 signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); 258 } 259 // Release memory in VerifyResult. 260 APPVERI_FreeVerifyRst(&verifyResult); 261 // Disable debugging mode. 262 ManagerService::SetDebugMode(false); 263 return ERR_OK; 264} 265``` 266 267## Debugging and Verification<a name="section427316292411"></a> 268 2691. Choose an application that can be properly installed on OpenHarmony. 2702. Develop the application based on the development guidelines. 2713. Use a self-developed program to verify the signature of the developed application. If the verification is successful and **appid** can be obtained, the development is successful. 272 273