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