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