• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Signing and Signature Verification with an RSA Key Pair (PKCS1 Mode) (C/C++)
2
3<!--Kit: Crypto Architecture Kit-->
4<!--Subsystem: Security-->
5<!--Owner: @zxz--3-->
6<!--Designer: @lanming-->
7<!--Tester: @PAFT-->
8<!--Adviser: @zengyawen-->
9
10For details about the algorithm specifications, see [RSA](crypto-sign-sig-verify-overview.md#rsa).
11
12## Adding the Dynamic Library in the CMake Script
13```txt
14target_link_libraries(entry PUBLIC libohcrypto.so)
15```
16## Signing Data
171. Call [OH_CryptoSign_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptosign_create) and specify the string parameter **'RSA1024|PKCS1|SHA256'** to create a **Sign** instance for signing.
18
192. Call [OH_CryptoSign_Init](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptosign_init) to initialize the **Sign** instance by using the private key (**OH_CryptoPrivKey**).
20
213. Call [OH_CryptoSign_Update](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptosign_update) to pass in the data to be signed. Currently, the amount of data to be passed in by a single **update** is not limited. You can determine how to pass in data based on the data volume. If the data size is small, you can simply call **OH_CryptoSign_Final** to pass in the full data.
22
234. Call [OH_CryptoSign_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptosign_final) to obtain the signed data.
24
255. Call [OH_CryptoSign_Destroy](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptosign_destroy) to free the memory.
26
27```c++
28#include "CryptoArchitectureKit/crypto_common.h"
29#include "CryptoArchitectureKit/crypto_signature.h"
30#include "CryptoArchitectureKit/crypto_asym_key.h"
31
32static OH_Crypto_ErrCode doTestRsaSignature() {
33   OH_CryptoAsymKeyGenerator *keyCtx = nullptr;
34   OH_CryptoKeyPair *keyPair = nullptr;
35   OH_CryptoSign *sign = nullptr;
36   Crypto_DataBlob signData = {.data = nullptr, .len = 0};
37
38   uint8_t plainText[] = {
39      0x43, 0x31, 0x7d, 0xb5, 0x85, 0x2e, 0xd4, 0xef, 0x08, 0x7a, 0x17, 0x96, 0xbc, 0x7c, 0x8f, 0x80,
40      0x8c, 0xa7, 0x63, 0x7f, 0x26, 0x89, 0x8f, 0xf0, 0xfa, 0xa7, 0x51, 0xbd, 0x9c, 0x69, 0x17, 0xf3,
41      0xd1, 0xb5, 0xc7, 0x12, 0xbf, 0xcf, 0x91, 0x25, 0x82, 0x23, 0x6b, 0xd6, 0x64, 0x52, 0x77, 0x93,
42      0x01, 0x9d, 0x70, 0xa3, 0xf4, 0x92, 0x16, 0xec, 0x3f, 0xa7, 0x3c, 0x83, 0x8d, 0x40, 0x41, 0xfc,
43   }; // Data to be verified, for reference only.
44   Crypto_DataBlob msgBlob = {
45      .data = reinterpret_cast<uint8_t *>(plainText),
46      .len = sizeof(plainText)
47   };
48
49   OH_Crypto_ErrCode ret = OH_CryptoAsymKeyGenerator_Create((const char *)"RSA2048", &keyCtx);
50   if (ret != CRYPTO_SUCCESS) {
51      return ret;
52   }
53   ret = OH_CryptoAsymKeyGenerator_Generate(keyCtx, &keyPair);
54   if (ret != CRYPTO_SUCCESS) {
55      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
56      return ret;
57   }
58
59   OH_CryptoPrivKey *privKey = OH_CryptoKeyPair_GetPrivKey(keyPair);
60   ret = OH_CryptoSign_Create((const char *)"RSA1024|PKCS1|SHA256", &sign);
61   if (ret != CRYPTO_SUCCESS) {
62      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
63      OH_CryptoKeyPair_Destroy(keyPair);
64      return ret;
65   }
66
67   ret = OH_CryptoSign_Init(sign, privKey);
68   if (ret != CRYPTO_SUCCESS) {
69      OH_CryptoSign_Destroy(sign);
70      OH_CryptoKeyPair_Destroy(keyPair);
71      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
72      return ret;
73   }
74   ret = OH_CryptoSign_Update(sign, &msgBlob);
75   if (ret != CRYPTO_SUCCESS) {
76      OH_CryptoSign_Destroy(sign);
77      OH_CryptoKeyPair_Destroy(keyPair);
78      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
79      return ret;
80   }
81   ret = OH_CryptoSign_Final(sign, nullptr, &signData);
82   if (ret != CRYPTO_SUCCESS) {
83      OH_CryptoSign_Destroy(sign);
84      OH_CryptoKeyPair_Destroy(keyPair);
85      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
86      return ret;
87   }
88
89   OH_CryptoSign_Destroy(sign);
90   OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
91   OH_CryptoKeyPair_Destroy(keyPair);
92   return CRYPTO_SUCCESS;
93}
94```
95
96## Verifying the Signature
97
981. Call [OH_CryptoVerify_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptoverify_create) with the string parameter **'RSA1024|PKCS1|SHA256'** to create a **Verify** instance. The string parameter must be the same as that used to create the **Sign** instance.
99
1002. Call [OH_CryptoVerify_Init](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptoverify_init) to initialize the **Verify** instance by using the public key (**OH_CryptoPubKey**).
101
1023. Call [OH_CryptoVerify_Update](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptoverify_update) to pass in the data to be verified.
103   Currently, the amount of data to be passed in by a single **OH_CryptoVerify_Update** is not limited. You can determine how to pass in data based on the data volume.
104
105   - If a small amount of data is to be verified, you can directly call [OH_CryptoVerify_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptoverify_final) after **OH_CryptoVerify_Init()**.
106   - If a large amount of data is to be verified, call **OH_CryptoVerify_Update()** multiple times to [pass in data by segment](crypto-rsa-sign-sig-verify-pkcs1-by-segment-ndk.md).
107
1084. Call [OH_CryptoVerify_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptoverify_final) to verify the signature.
109
110```c++
111#include "CryptoArchitectureKit/crypto_common.h"
112#include "CryptoArchitectureKit/crypto_asym_key.h"
113#include "CryptoArchitectureKit/crypto_signature.h"
114
115static bool doTestRsaSignature()
116{
117   OH_CryptoAsymKeyGenerator *keyCtx = nullptr;
118   OH_CryptoKeyPair *keyPair = nullptr;
119   OH_CryptoVerify *verify = nullptr;
120
121   uint8_t plainText[] = {
122      0x43, 0x31, 0x7d, 0xb5, 0x85, 0x2e, 0xd4, 0xef, 0x08, 0x7a, 0x17, 0x96, 0xbc, 0x7c, 0x8f, 0x80,
123      0x8c, 0xa7, 0x63, 0x7f, 0x26, 0x89, 0x8f, 0xf0, 0xfa, 0xa7, 0x51, 0xbd, 0x9c, 0x69, 0x17, 0xf3,
124      0xd1, 0xb5, 0xc7, 0x12, 0xbf, 0xcf, 0x91, 0x25, 0x82, 0x23, 0x6b, 0xd6, 0x64, 0x52, 0x77, 0x93,
125      0x01, 0x9d, 0x70, 0xa3, 0xf4, 0x92, 0x16, 0xec, 0x3f, 0xa7, 0x3c, 0x83, 0x8d, 0x40, 0x41, 0xfc,
126   }; // Data to be verified, for reference only.
127   Crypto_DataBlob msgBlob = {
128      .data = reinterpret_cast<uint8_t *>(plainText),
129      .len = sizeof(plainText)
130   };
131
132   uint8_t pubKeyText[] = {
133      0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x52, 0x53, 0x41, 0x20, 0x50,
134      0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d,
135      0x49, 0x47, 0x4a, 0x41, 0x6f, 0x47, 0x42, 0x41, 0x4d, 0x78, 0x63, 0x44, 0x4d, 0x6f, 0x61, 0x59,
136      0x52, 0x58, 0x6f, 0x78, 0x65, 0x69, 0x33, 0x49, 0x6d, 0x33, 0x33, 0x78, 0x4a, 0x76, 0x61, 0x73,
137      0x63, 0x43, 0x62, 0x77, 0x31, 0x6f, 0x73, 0x63, 0x32, 0x56, 0x56, 0x69, 0x47, 0x6a, 0x56, 0x47,
138      0x47, 0x4a, 0x37, 0x6c, 0x75, 0x4e, 0x41, 0x58, 0x6b, 0x6a, 0x73, 0x56, 0x46, 0x64, 0x35, 0x0a,
139      0x58, 0x37, 0x4c, 0x4d, 0x6c, 0x46, 0x34, 0x63, 0x35, 0x5a, 0x75, 0x59, 0x2f, 0x61, 0x69, 0x57,
140      0x77, 0x70, 0x54, 0x69, 0x63, 0x62, 0x67, 0x49, 0x33, 0x43, 0x66, 0x50, 0x6f, 0x32, 0x6a, 0x6c,
141      0x52, 0x74, 0x67, 0x41, 0x46, 0x6b, 0x44, 0x71, 0x7a, 0x4b, 0x53, 0x46, 0x62, 0x46, 0x47, 0x51,
142      0x6b, 0x43, 0x6e, 0x64, 0x63, 0x2b, 0x54, 0x59, 0x6b, 0x5a, 0x42, 0x32, 0x70, 0x45, 0x6f, 0x72,
143      0x0a, 0x7a, 0x73, 0x61, 0x56, 0x58, 0x77, 0x5a, 0x47, 0x45, 0x34, 0x41, 0x43, 0x70, 0x59, 0x35,
144      0x79, 0x65, 0x66, 0x49, 0x44, 0x6c, 0x45, 0x57, 0x49, 0x51, 0x4f, 0x6a, 0x59, 0x4b, 0x2f, 0x6c,
145      0x58, 0x71, 0x7a, 0x48, 0x47, 0x69, 0x4f, 0x69, 0x32, 0x75, 0x4a, 0x45, 0x75, 0x44, 0x43, 0x50,
146      0x6a, 0x51, 0x64, 0x6a, 0x54, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, 0x45, 0x3d, 0x0a, 0x2d, 0x2d,
147      0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x52, 0x53, 0x41, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49,
148      0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a,
149   }; // Public key in DER format, for reference only.
150
151   Crypto_DataBlob keyBlob = {
152      .data = reinterpret_cast<uint8_t *>(pubKeyText),
153      .len = sizeof(pubKeyText)
154   };
155
156   uint8_t signText[] = {
157      0x68, 0x2f, 0x3b, 0xe6, 0xa6, 0x5c, 0xb8, 0x60, 0xd4, 0xe1, 0x64, 0xa7, 0xd8, 0x0c, 0x9c, 0x89,
158      0x39, 0xb4, 0xf0, 0xb7, 0xad, 0xb5, 0x8a, 0x71, 0x04, 0xf1, 0xa5, 0x63, 0xdd, 0x32, 0x6a, 0x44,
159      0xeb, 0xff, 0xb7, 0xe6, 0x85, 0xe5, 0xa5, 0x55, 0x5d, 0x5b, 0x28, 0x53, 0x63, 0xe4, 0xb3, 0xb9,
160      0xa8, 0x70, 0xc8, 0x8f, 0xcd, 0x21, 0x8d, 0xe6, 0x1f, 0xe5, 0x78, 0x34, 0xd3, 0x45, 0x0c, 0x9c,
161      0x7a, 0x22, 0x1b, 0x63, 0x55, 0xca, 0x14, 0xa5, 0x0c, 0x7a, 0x40, 0x8e, 0xa1, 0x14, 0x78, 0xa1,
162      0xf1, 0x36, 0x78, 0xbd, 0xba, 0x37, 0x3b, 0x5b, 0xb0, 0x8e, 0xb3, 0x4a, 0x9b, 0x1b, 0x0c, 0xfa,
163      0xfa, 0xc7, 0x9f, 0xb1, 0x35, 0x48, 0x82, 0x73, 0xf8, 0x6b, 0xd4, 0x76, 0x33, 0x5c, 0xed, 0x9c,
164      0xd8, 0x4b, 0xc9, 0x92, 0xa0, 0x3f, 0x6e, 0xba, 0x78, 0x2e, 0x80, 0x78, 0x1e, 0x74, 0xa0, 0x47,
165   }; // Signature data, for reference only.
166
167   Crypto_DataBlob signBlob = {
168      .data = reinterpret_cast<uint8_t *>(signText),
169      .len = sizeof(signText)
170   };
171
172   // keypair
173   OH_Crypto_ErrCode ret = CRYPTO_SUCCESS;
174   ret = OH_CryptoAsymKeyGenerator_Create((const char *)"RSA2048", &keyCtx); // Create an asymmetric key generator.
175   if (ret != CRYPTO_SUCCESS) {
176      return false;
177   }
178   ret = OH_CryptoAsymKeyGenerator_Convert(keyCtx, CRYPTO_PEM, &keyBlob, nullptr, &keyPair); // Convert the public key in PEM format to OH_CryptoKeyPair.
179   if (ret != CRYPTO_SUCCESS) {
180      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
181      return false;
182   }
183   OH_CryptoPubKey *pubKey = OH_CryptoKeyPair_GetPubKey(keyPair); // Obtain the public key.
184   // verify
185   ret = OH_CryptoVerify_Create((const char *)"RSA1024|PKCS1|SHA256", &verify); // Create a Verify instance.
186   if (ret != CRYPTO_SUCCESS) {
187      OH_CryptoVerify_Destroy(verify);
188      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
189      return false;
190   }
191   ret = OH_CryptoVerify_Init(verify, pubKey); // Use the public key to initialize the Verify instance.
192   if (ret != CRYPTO_SUCCESS) {
193      OH_CryptoVerify_Destroy(verify);
194      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
195      return false;
196   }
197   bool res = OH_CryptoVerify_Final(verify, &msgBlob, &signBlob); // Verify the signature of the data.
198   if (res != true) {
199      OH_CryptoVerify_Destroy(verify);
200      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
201      return false;
202   }
203
204   OH_CryptoVerify_Destroy(verify);
205   OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
206   OH_CryptoKeyPair_Destroy(keyPair);
207   return res;
208}
209```
210