1# Signing and Signature Verification with an RSA Key Pair (PSS Mode) (ArkTS)
2
3
4For details about the algorithm specifications, see [RSA](crypto-sign-sig-verify-overview.md#rsa).
5
6
7**Signing**
8
9
101. Use [cryptoFramework.createAsyKeyGeneratorBySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateasykeygeneratorbyspec10) and [AsyKeyGeneratorBySpec.generateKeyPair](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatekeypair-3) to generate an RSA asymmetric key pair (**KeyPair**) based on the specified key parameters.
11
12   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.
13
142. Use [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**.
15
163. Use [Sign.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-3) to initialize the **Sign** instance with the private key (**PriKey**).
17
184. Use [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.
19
205. Use [Sign.getSignSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getsignspec10) to obtain other parameters for signing.
21
226. Use [Sign.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-3) to pass in the data to be signed.
23
24   Currently, the amount of data to be passed in by a single **Sign.update()** is not limited. You can determine how to pass in data based on the data volume.
25
267. Use [Sign.sign](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#sign-1) to generate a signature.
27
28
29**Signature Verification**
30
31
321. Use [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**.
33
342. Use [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.
35
363. Use [Verify.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-5) to initialize the **Verify** instance using the public key (**PubKey**).
37
384. Use [Verify.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-5) to pass in the data to be verified.
39
40   Currently, the amount of data to be passed in by a single **Verify.update()** is not limited. You can determine how to pass in data based on the data volume.
41
425. Use [Verify.verify](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#verify-1) to verify the data signature.
43
44- Example (using asynchronous APIs):
45
46  ```ts
47  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
48  import { buffer } from '@kit.ArkTS';
49  // Construct the RSA key pair parameter based on the key pair specifications.
50  function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) {
51    let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
52      n: nIn,
53      algName: "RSA",
54      specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
55    };
56    let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = {
57      params: rsaCommSpec,
58      sk: dIn,
59      pk: eIn,
60      algName: "RSA",
61      specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC
62    };
63    return rsaKeyPairSpec;
64  }
65  // Generate the RSA2048 key pair parameter.
66  function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec {
67    let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
68    let eIn = BigInt("0x010001");
69    let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1");
70    return genRsaKeyPairSpec(nIn, eIn, dIn);
71  }
72
73  async function verifyMessagePSS() {
74    // The plaintext is split into input1 and input2.
75    let plan1 = "This is Sign test plan1";
76    let plan2 = "This is Sign test plan2";
77    let input1: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(plan1, 'utf-8').buffer) };
78    let input2: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(plan2, 'utf-8').buffer) };
79    // Generate the RSA key pair parameter (Rsa2048KeyPairSpec) object.
80    let rsaKeyPairSpec = genRsa2048KeyPairSpec();
81    // Create an RSA key pair generator.
82    let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
83    // Both sign() and verify() support the RSA key with or without the length.
84    let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256");
85    let verifyer = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256");
86    let keyPair = await rsaGeneratorSpec.generateKeyPair();
87    await signer.init(keyPair.priKey);
88    // After the Sign instance is initialized, set and obtain the PSS parameters.
89    let setN = 32;
90    signer.setSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
91    let saltLen = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
92    console.info("SaltLen == " + saltLen);
93    let tf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
94    console.info("trailer field == " + tf);
95    let md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
96    console.info("md == " + md);
97    let mgf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
98    console.info("mgf == " + mgf);
99    let mgf1Md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
100    console.info("mgf1Md == " + mgf1Md);
101    await signer.update(input1);
102    let signMessageBlob = await signer.sign(input2);
103    // Before the Verify instance is initialized, set and get PSS parameters.
104    verifyer.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
105    saltLen = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
106    console.info("SaltLen == " + saltLen);
107    tf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
108    console.info("trailer field == " + tf);
109    md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
110    console.info("md == " + md);
111    mgf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
112    console.info("mgf == " + mgf);
113    mgf1Md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
114    await verifyer.init(keyPair.pubKey);
115    await verifyer.update(input1);
116    let verifyResult = await verifyer.verify(input2, signMessageBlob);
117    if (verifyResult == true) {
118      console.info('verify success');
119    } else {
120      console.error('verify failed');
121    }
122  }
123  ```
124
125
126- Example (using synchronous APIs):
127
128  ```ts
129  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
130  import { buffer } from '@kit.ArkTS';
131  // Construct the RSA key pair parameter based on the key pair specifications.
132  function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) {
133    let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
134      n: nIn,
135      algName: "RSA",
136      specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
137    };
138    let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = {
139      params: rsaCommSpec,
140      sk: dIn,
141      pk: eIn,
142      algName: "RSA",
143      specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC
144    };
145    return rsaKeyPairSpec;
146  }
147  // Generate the RSA2048 key pair parameter.
148  function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec {
149    let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
150    let eIn = BigInt("0x010001");
151    let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1");
152    return genRsaKeyPairSpec(nIn, eIn, dIn);
153  }
154
155  function verifyMessagePSS() {
156    // The plaintext is split into input1 and input2.
157    let plan1 = "This is Sign test plan1";
158    let plan2 = "This is Sign test plan2";
159    let input1: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(plan1, 'utf-8').buffer) };
160    let input2: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(plan2, 'utf-8').buffer) };
161    // Generate the RSA key pair parameter (Rsa2048KeyPairSpec) object.
162    let rsaKeyPairSpec = genRsa2048KeyPairSpec();
163    // Create an RSA key pair generator.
164    let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
165    // Both sign() and verify() support the RSA key with or without the length.
166    let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256");
167    let verifyer = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256");
168    let keyPair = rsaGeneratorSpec.generateKeyPairSync();
169    signer.initSync(keyPair.priKey);
170    // After the Sign instance is initialized, set and obtain the PSS parameters.
171    let setN = 32;
172    signer.setSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
173    let saltLen = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
174    console.info("SaltLen == " + saltLen);
175    let tf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
176    console.info("trailer field == " + tf);
177    let md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
178    console.info("md == " + md);
179    let mgf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
180    console.info("mgf == " + mgf);
181    let mgf1Md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
182    console.info("mgf1Md == " + mgf1Md);
183    signer.updateSync(input1);
184    let signMessageBlob = signer.signSync(input2);
185    // Before the Verify instance is initialized, set and get PSS parameters.
186    verifyer.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
187    saltLen = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
188    console.info("SaltLen == " + saltLen);
189    tf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
190    console.info("trailer field == " + tf);
191    md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
192    console.info("md == " + md);
193    mgf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
194    console.info("mgf == " + mgf);
195    mgf1Md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
196    verifyer.initSync(keyPair.pubKey);
197    verifyer.updateSync(input1);
198    let verifyResult = verifyer.verifySync(input2, signMessageBlob);
199    if (verifyResult == true) {
200      console.info('verify success');
201    } else {
202      console.error('verify failed');
203    }
204  }
205  ```
206