• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![](figure/安全子系统.png)
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