• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Signing and Signature Verification with an SM2 Key Pair (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 [SM2](crypto-sign-sig-verify-overview.md#sm2).
11
12## Adding the Dynamic Library in the CMake Script
13```txt
14target_link_libraries(entry PUBLIC libohcrypto.so)
15```
16
17## Signing Data
181. Call [OH_CryptoSign_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptosign_create) with the string parameter **'SM2_256|SM3'** to create a **Sign** instance. The key type is **SM2_256**, and MD algorithm is **SM3**.
19
202. Call [OH_CryptoSign_Init](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptosign_init) to initialize the **Sign** instance using [OH_CryptoPrivKey](../../reference/apis-crypto-architecture-kit/capi-cryptoasymkeyapi-oh-cryptoprivkey.md).
21
223. 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.
23
244. Call [OH_CryptoSign_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptosign_final) to obtain the signed data.
25
265. Call [OH_CryptoSign_Destroy](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptosign_destroy) to free the memory.
27
28```c++
29#include "CryptoArchitectureKit/crypto_common.h"
30#include "CryptoArchitectureKit/crypto_asym_key.h"
31#include "CryptoArchitectureKit/crypto_signature.h"
32
33static OH_Crypto_ErrCode doSm2Test() {
34   OH_CryptoAsymKeyGenerator *keyCtx = nullptr;
35   OH_CryptoKeyPair *keyPair = nullptr;
36   OH_CryptoSign *sign = nullptr;
37
38   uint8_t plainText[] = {
39      0x96, 0x46, 0x2e, 0xde, 0x3f, 0x47, 0xbf, 0xd6, 0x87, 0x48, 0x36, 0x1d, 0x75, 0x35, 0xbd, 0xbc,
40      0x6b, 0x06, 0xe8, 0xb3, 0x68, 0x91, 0x53, 0xce, 0x76, 0x5d, 0x24, 0xda, 0xdc, 0xc4, 0x9f, 0x94,
41   };
42   Crypto_DataBlob msgBlob = {
43      .data = reinterpret_cast<uint8_t *>(plainText),
44      .len = sizeof(plainText)};
45
46   OH_Crypto_ErrCode ret = OH_CryptoAsymKeyGenerator_Create((const char *)"SM2_256", &keyCtx);
47   if (ret != CRYPTO_SUCCESS) {
48      return ret;
49   }
50   ret = OH_CryptoAsymKeyGenerator_Generate(keyCtx, &keyPair);
51   if (ret != CRYPTO_SUCCESS) {
52      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
53      return ret;
54   }
55
56   OH_CryptoPrivKey *privKey = OH_CryptoKeyPair_GetPrivKey(keyPair);
57   ret = OH_CryptoSign_Create((const char *)"SM2_256|SM3", &sign);
58   if (ret != CRYPTO_SUCCESS) {
59      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
60      OH_CryptoKeyPair_Destroy(keyPair);
61      return ret;
62   }
63   ret = OH_CryptoSign_Init(sign, privKey);
64   if (ret != CRYPTO_SUCCESS) {
65      OH_CryptoSign_Destroy(sign);
66      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
67      OH_CryptoKeyPair_Destroy(keyPair);
68      return ret;
69   }
70
71   ret = OH_CryptoSign_Update(sign, &msgBlob);
72   if (ret != CRYPTO_SUCCESS) {
73      OH_CryptoSign_Destroy(sign);
74      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
75      OH_CryptoKeyPair_Destroy(keyPair);
76      return ret;
77   }
78
79   Crypto_DataBlob signBlob = {.data = nullptr, .len = 0};
80   ret = OH_CryptoSign_Final(sign, nullptr, &signBlob);
81   if (ret != CRYPTO_SUCCESS) {
82      OH_CryptoSign_Destroy(sign);
83      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
84      OH_CryptoKeyPair_Destroy(keyPair);
85      return ret;
86   }
87   OH_CryptoSign_Destroy(sign);
88   OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
89   OH_CryptoKeyPair_Destroy(keyPair);
90   OH_Crypto_FreeDataBlob(&signBlob);
91   return CRYPTO_SUCCESS;
92}
93```
94
95## Verifying the Signature
96
971. Call [OH_CryptoVerify_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptoverify_create) with the string parameter **'SM2_256|SM3'** to create a **Verify** instance. The key type is **SM2_256**, and MD algorithm is **SM3**.
98
992. 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**).
100
1013. 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. 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. If a small amount of data is to be verified, you can call **OH_CryptoVerify_Final** immediately after **OH_CryptoVerify_Init()**.
102
1034. Call [OH_CryptoVerify_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-signature-h.md#oh_cryptoverify_final) to verify the signature.
104
105```c++
106#include "CryptoArchitectureKit/crypto_common.h"
107#include "CryptoArchitectureKit/crypto_signature.h"
108#include "CryptoArchitectureKit/crypto_asym_key.h"
109
110static bool doTestSm2Signature()
111{
112   OH_CryptoAsymKeyGenerator *keyCtx = nullptr;
113   OH_CryptoKeyPair *keyPair = nullptr;
114   OH_CryptoVerify *verify = nullptr;
115
116   uint8_t plainText[] = {
117      0x96, 0x46, 0x2e, 0xde, 0x3f, 0x47, 0xbf, 0xd6, 0x87, 0x48, 0x36, 0x1d, 0x75, 0x35, 0xbd, 0xbc,
118      0x6b, 0x06, 0xe8, 0xb3, 0x68, 0x91, 0x53, 0xce, 0x76, 0x5d, 0x24, 0xda, 0xdc, 0xc4, 0x9f, 0x94,
119   }; // Data to be verified, for reference only.
120   Crypto_DataBlob msgBlob = {
121      .data = reinterpret_cast<uint8_t *>(plainText),
122      .len = sizeof(plainText)
123   };
124
125   uint8_t pubKeyText[] = {
126      0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
127      0x81, 0x1c, 0xcf, 0x55, 0x01, 0x82, 0x2d, 0x03, 0x42, 0x00, 0x04, 0x80, 0x5b, 0x78, 0x04, 0xd7,
128      0xcf, 0xc3, 0x99, 0x63, 0xae, 0x88, 0xcd, 0xfc, 0xd6, 0x18, 0xf4, 0x08, 0xe8, 0xe3, 0x68, 0x47,
129      0x4f, 0x44, 0x0e, 0xb2, 0xba, 0x3a, 0xb3, 0x10, 0xf1, 0xc9, 0xd0, 0x84, 0xe2, 0xa4, 0x47, 0xbe,
130      0x72, 0xae, 0xf8, 0x6a, 0xeb, 0x6e, 0x10, 0xab, 0x52, 0x6b, 0x6a, 0x58, 0xc6, 0xb5, 0x78, 0xaa,
131      0x70, 0xe5, 0x58, 0x20, 0x4e, 0x34, 0x42, 0x77, 0x08, 0x27, 0x11,
132   }; // Public key in DER format, for reference only.
133
134   Crypto_DataBlob keyBlob = {
135      .data = reinterpret_cast<uint8_t *>(pubKeyText),
136      .len = sizeof(pubKeyText)
137   };
138
139   uint8_t signText[] = {
140      0x30, 0x45, 0x02, 0x21, 0x00, 0xf4, 0xe7, 0x9d, 0x35, 0x33, 0xa6, 0x86, 0x2e, 0x2a, 0x97, 0x72,
141      0xc9, 0x46, 0x79, 0x65, 0xca, 0x4a, 0x71, 0x34, 0xca, 0xf7, 0x58, 0xb3, 0x26, 0xa5, 0xdb, 0xfa,
142      0x8b, 0xbe, 0xbf, 0x5f, 0x90, 0x02, 0x20, 0x53, 0xb4, 0x23, 0xb1, 0xe2, 0x8f, 0x2f, 0xe9, 0xc8,
143      0x22, 0xef, 0xab, 0x9b, 0x13, 0x08, 0x75, 0x8e, 0xb1, 0x9c, 0x59, 0xe5, 0xd6, 0x64, 0x35, 0xf5,
144      0xd1, 0xde, 0xfa, 0xfe, 0x80, 0x37, 0x1a,
145   }; // Signature data, for reference only.
146
147   Crypto_DataBlob signBlob = {
148      .data = reinterpret_cast<uint8_t *>(signText),
149      .len = sizeof(signText)
150   };
151
152   // keypair
153   OH_Crypto_ErrCode ret = CRYPTO_SUCCESS;
154   ret = OH_CryptoAsymKeyGenerator_Create((const char *)"SM2_256", &keyCtx); // Create an asymmetric key generator.
155   if (ret != CRYPTO_SUCCESS) {
156      return false;
157   }
158   ret = OH_CryptoAsymKeyGenerator_Convert(keyCtx, CRYPTO_DER, &keyBlob, nullptr, &keyPair); // Convert the public key in DER format to OH_CryptoKeyPair.
159   if (ret != CRYPTO_SUCCESS) {
160      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
161      return false;
162   }
163   OH_CryptoPubKey *pubKey = OH_CryptoKeyPair_GetPubKey(keyPair);
164   // verify
165   ret = OH_CryptoVerify_Create((const char *)"SM2_256|SM3", &verify); // Create a Verify instance.
166   if (ret != CRYPTO_SUCCESS) {
167      OH_CryptoVerify_Destroy(verify);
168      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
169      return false;
170   }
171   ret = OH_CryptoVerify_Init(verify, pubKey); // Use the public key to initialize the Verify instance.
172   if (ret != CRYPTO_SUCCESS) {
173      OH_CryptoVerify_Destroy(verify);
174      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
175      return false;
176   }
177   bool res = OH_CryptoVerify_Final(verify, &msgBlob, &signBlob); // Verify the signature of the data.
178   if (res != true) {
179      OH_CryptoVerify_Destroy(verify);
180      OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
181      return false;
182   }
183
184   OH_CryptoVerify_Destroy(verify);
185   OH_CryptoAsymKeyGenerator_Destroy(keyCtx);
186   OH_CryptoKeyPair_Destroy(keyPair);
187   return res;
188}
189  ```
190