• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Signing and Signature Verification with an RSA Key Pair (PSS Mode) (ArkTS)
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**Signing**
13
141. Call [cryptoFramework.createAsyKeyGeneratorBySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateasykeygeneratorbyspec10) and [AsyKeyGeneratorBySpec.generateKeyPair](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatekeypair10) to generate an RSA asymmetric key pair (**KeyPair**) based on the specified key parameters.
15   In addition to the example in this topic, [RSA](crypto-asym-key-generation-conversion-spec.md#rsa) and [Generating an Asymmetric Key Pair Based on Key Parameters](crypto-generate-asym-key-pair-from-key-spec.md) may help you better understand how to generate an RSA asymmetric key pair. Note that the input parameters in the reference documents may be different from those in the example below.
16
172. Call [cryptoFramework.createSign](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatesign) with the string parameter **'RSA|PSS|SHA256|MGF1_SHA256'** to create a **Sign** instance. As indicated by the string parameter, the key type is RSA without length, the padding mode is **PSS**, the MD algorithm is **SHA256**, and the mask algorithm is **MGF1_SHA256**.
18
193. Call [Sign.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-3) to initialize the **Sign** instance with the private key (**PriKey**).
20
214. Call [Sign.setSignSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#setsignspec10) to set parameters for signing. In this example, the salt length (**SignSpecItem.PSS_SALT_LEN_NUM**) is set to 32 bytes. The data will be verified in signature verification.
22
235. Call [Sign.getSignSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getsignspec10) to obtain other parameters for signing.
24
256. Call [Sign.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-3) 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 size.
26
277. Call [Sign.sign](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#sign-1) to generate a signature.
28
29**Signature Verification**
30
311. Call [cryptoFramework.createVerify](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateverify) with the string parameter **'RSA2048|PSS|SHA256|MGF1_SHA256'** to create a **Verify** instance. As indicated by the string parameter, the asymmetric key type is **RSA2048**, the padding mode is **PSS**, the MD algorithm is **SHA256**, and mask algorithm is **MGF1_SHA256**.
32
332. Call [Verify.setVerifySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#setverifyspec10) to set the parameters for signature verification. The parameter value must be the same as that set for signing.
34
353. Call [Verify.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-5) to initialize the **Verify** instance using the public key (**PubKey**).
36
374. Call [Verify.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-5) to pass in the data to be verified. 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 size.
38
395. Call [Verify.verify](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#verify-1) to verify the data signature.
40
41- Example (using asynchronous APIs):
42
43  ```ts
44  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
45  import { buffer } from '@kit.ArkTS';
46  // Construct the RSA key pair parameter based on the key pair specifications.
47  function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) {
48    let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
49      n: nIn,
50      algName: "RSA",
51      specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
52    };
53    let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = {
54      params: rsaCommSpec,
55      sk: dIn,
56      pk: eIn,
57      algName: "RSA",
58      specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC
59    };
60    return rsaKeyPairSpec;
61  }
62  // Generate the RSA2048 key pair parameter.
63  function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec {
64    let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
65    let eIn = BigInt("0x010001");
66    let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1");
67    return genRsaKeyPairSpec(nIn, eIn, dIn);
68  }
69
70  async function verifyMessagePSS() {
71    // The plaintext is split into input1 and input2.
72    let plan1 = "This is Sign test plan1";
73    let plan2 = "This is Sign test plan2";
74    let input1: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(plan1, 'utf-8').buffer) };
75    let input2: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(plan2, 'utf-8').buffer) };
76    // Generate the RSA key pair parameter (Rsa2048KeyPairSpec) object.
77    let rsaKeyPairSpec = genRsa2048KeyPairSpec();
78    // Create an RSA key pair generator.
79    let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
80    // Both sign() and verify() support the RSA key with or without the length.
81    let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256");
82    let verifyer = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256");
83    let keyPair = await rsaGeneratorSpec.generateKeyPair();
84    await signer.init(keyPair.priKey);
85    // After the Sign instance is initialized, set and obtain the PSS parameters.
86    let setN = 32;
87    signer.setSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
88    let saltLen = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
89    console.info("SaltLen == " + saltLen);
90    let tf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
91    console.info("trailer field == " + tf);
92    let md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
93    console.info("md == " + md);
94    let mgf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
95    console.info("mgf == " + mgf);
96    let mgf1Md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
97    console.info("mgf1Md == " + mgf1Md);
98    await signer.update(input1);
99    let signMessageBlob = await signer.sign(input2);
100    // Before the Verify instance is initialized, set and get PSS parameters.
101    verifyer.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
102    saltLen = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
103    console.info("SaltLen == " + saltLen);
104    tf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
105    console.info("trailer field == " + tf);
106    md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
107    console.info("md == " + md);
108    mgf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
109    console.info("mgf == " + mgf);
110    mgf1Md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
111    await verifyer.init(keyPair.pubKey);
112    await verifyer.update(input1);
113    let verifyResult = await verifyer.verify(input2, signMessageBlob);
114    if (verifyResult === true) {
115      console.info('verify success');
116    } else {
117      console.error('verify failed');
118    }
119  }
120  ```
121
122- Example (using synchronous APIs):
123
124  ```ts
125  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
126  import { buffer } from '@kit.ArkTS';
127  // Construct the RSA key pair parameter based on the key pair specifications.
128  function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) {
129    let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
130      n: nIn,
131      algName: "RSA",
132      specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
133    };
134    let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = {
135      params: rsaCommSpec,
136      sk: dIn,
137      pk: eIn,
138      algName: "RSA",
139      specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC
140    };
141    return rsaKeyPairSpec;
142  }
143  // Generate the RSA2048 key pair parameter.
144  function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec {
145    let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
146    let eIn = BigInt("0x010001");
147    let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1");
148    return genRsaKeyPairSpec(nIn, eIn, dIn);
149  }
150
151  function verifyMessagePSS() {
152    // The plaintext is split into input1 and input2.
153    let plan1 = "This is Sign test plan1";
154    let plan2 = "This is Sign test plan2";
155    let input1: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(plan1, 'utf-8').buffer) };
156    let input2: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(plan2, 'utf-8').buffer) };
157    // Generate the RSA key pair parameter (Rsa2048KeyPairSpec) object.
158    let rsaKeyPairSpec = genRsa2048KeyPairSpec();
159    // Create an RSA key pair generator.
160    let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
161    // Both sign() and verify() support the RSA key with or without the length.
162    let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256");
163    let verifyer = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256");
164    let keyPair = rsaGeneratorSpec.generateKeyPairSync();
165    signer.initSync(keyPair.priKey);
166    // After the Sign instance is initialized, set and obtain the PSS parameters.
167    let setN = 32;
168    signer.setSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
169    let saltLen = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
170    console.info("SaltLen == " + saltLen);
171    let tf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
172    console.info("trailer field == " + tf);
173    let md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
174    console.info("md == " + md);
175    let mgf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
176    console.info("mgf == " + mgf);
177    let mgf1Md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
178    console.info("mgf1Md == " + mgf1Md);
179    signer.updateSync(input1);
180    let signMessageBlob = signer.signSync(input2);
181    // Before the Verify instance is initialized, set and get PSS parameters.
182    verifyer.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
183    saltLen = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
184    console.info("SaltLen == " + saltLen);
185    tf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
186    console.info("trailer field == " + tf);
187    md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
188    console.info("md == " + md);
189    mgf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
190    console.info("mgf == " + mgf);
191    mgf1Md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
192    verifyer.initSync(keyPair.pubKey);
193    verifyer.updateSync(input1);
194    let verifyResult = verifyer.verifySync(input2, signMessageBlob);
195    if (verifyResult === true) {
196      console.info('verify success');
197    } else {
198      console.error('verify failed');
199    }
200  }
201  ```
202