1# 使用RSA密钥对签名验签(PSS模式)(ArkTS) 2 3<!--Kit: Crypto Architecture Kit--> 4<!--Subsystem: Security--> 5<!--Owner: @zxz--3--> 6<!--Designer: @lanming--> 7<!--Tester: @PAFT--> 8<!--Adviser: @zengyawen--> 9 10对应的算法规格请查看[签名验签算法规格:RSA](crypto-sign-sig-verify-overview.md#rsa)。 11 12**签名** 13 141. 调用[cryptoFramework.createAsyKeyGeneratorBySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateasykeygeneratorbyspec10)、[AsyKeyGeneratorBySpec.generateKeyPair](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatekeypair10),指定密钥参数,生成RSA非对称密钥对(KeyPair)。 15 如何生成RSA非对称密钥,开发者可参考下文示例,并结合[非对称密钥生成和转换规格:RSA](crypto-asym-key-generation-conversion-spec.md#rsa)和[指定密钥参数生成非对称密钥对](crypto-generate-asym-key-pair-from-key-spec.md)理解,参考文档与当前示例可能存在入参差异,请在阅读时注意区分。 16 172. 调用[cryptoFramework.createSign](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatesign),指定字符串参数'RSA|PSS|SHA256|MGF1_SHA256',创建非对称密钥类型为不带长度的RSA、填充模式为PSS、摘要算法为SHA256、掩码算法为MGF1_SHA256的Sign实例,用于完成签名操作。 18 193. 调用[Sign.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-3),使用私钥(PriKey)初始化Sign实例。 20 214. 调用[Sign.setSignSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#setsignspec10),设置签名参数。此处设置盐值的长度(SignSpecItem.PSS_SALT_LEN_NUM)为32字节。在验签时将校验此数据。 22 235. 调用[Sign.getSignSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getsignspec10),获取其他签名参数。 24 256. 调用[Sign.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-3),传入待签名的数据。当前单次update长度没有限制,开发者可以根据数据量判断如何调用update。 26 277. 调用[Sign.sign](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#sign-1),生成数据签名。 28 29**验签** 30 311. 调用[cryptoFramework.createVerify](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateverify),指定字符串参数'RSA2048|PSS|SHA256|MGF1_SHA256',创建非对称密钥类型为RSA2048、填充模式为PSS、摘要算法为SHA256、掩码算法为MGF1_SHA256的Verify实例,用于完成验签操作。 32 332. 调用[Verify.setVerifySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#setverifyspec10),设置签名参数。需要与签名时设置的保持一致。 34 353. 调用[Verify.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-5),使用公钥(PubKey)初始化Verify实例。 36 374. 调用[Verify.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-5),传入待验证的数据。当前单次update长度没有限制,开发者可以根据数据量判断如何调用update。 38 395. 调用[Verify.verify](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#verify-1),对数据进行验签。 40 41- 异步方法示例: 42 43 ```ts 44 import { cryptoFramework } from '@kit.CryptoArchitectureKit'; 45 import { buffer } from '@kit.ArkTS'; 46 // 根据密钥参数属性构造RSA非对称密钥对密钥参数。 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 // 生成RSA2048密钥对参数。 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 // 完整的明文被拆分为input1和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 // 获得RSA密钥对密钥参数对象。 77 let rsaKeyPairSpec = genRsa2048KeyPairSpec(); 78 // 构造RSA密钥对生成器。 79 let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec); 80 // sign和verify均支持RSA密钥带长度/不带长度的写法。 81 let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256"); 82 let verifier = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256"); 83 let keyPair = await rsaGeneratorSpec.generateKeyPair(); 84 await signer.init(keyPair.priKey); 85 // 在签名初始化后,对PSS参数进行set和get操作。 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 // 在验签初始化前,对PSS参数进行set和get操作。 101 verifier.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN); 102 saltLen = verifier.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM); 103 console.info("SaltLen == " + saltLen); 104 tf = verifier.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM); 105 console.info("trailer field == " + tf); 106 md = verifier.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR); 107 console.info("md == " + md); 108 mgf = verifier.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR); 109 console.info("mgf == " + mgf); 110 mgf1Md = verifier.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR); 111 await verifier.init(keyPair.pubKey); 112 await verifier.update(input1); 113 let verifyResult = await verifier.verify(input2, signMessageBlob); 114 if (verifyResult === true) { 115 console.info('verify success'); 116 } else { 117 console.error('verify failed'); 118 } 119 } 120 ``` 121 122- 同步方法示例: 123 124 ```ts 125 import { cryptoFramework } from '@kit.CryptoArchitectureKit'; 126 import { buffer } from '@kit.ArkTS'; 127 // 根据密钥参数属性构造RSA非对称密钥对密钥参数。 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 // 生成RSA2048密钥对参数。 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 // 完整的明文被拆分为input1和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 // 获得RSA密钥对密钥参数对象。 158 let rsaKeyPairSpec = genRsa2048KeyPairSpec(); 159 // 构造RSA密钥对生成器。 160 let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec); 161 // sign和verify均支持RSA密钥带长度/不带长度的写法。 162 let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256"); 163 let verifier = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256"); 164 let keyPair = rsaGeneratorSpec.generateKeyPairSync(); 165 signer.initSync(keyPair.priKey); 166 // 在签名初始化后,对PSS参数进行set和get操作。 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 // 在验签初始化前,对PSS参数进行set和get操作。 182 verifier.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN); 183 saltLen = verifier.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM); 184 console.info("SaltLen == " + saltLen); 185 tf = verifier.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM); 186 console.info("trailer field == " + tf); 187 md = verifier.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR); 188 console.info("md == " + md); 189 mgf = verifier.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR); 190 console.info("mgf == " + mgf); 191 mgf1Md = verifier.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR); 192 verifier.initSync(keyPair.pubKey); 193 verifier.updateSync(input1); 194 let verifyResult = verifier.verifySync(input2, signMessageBlob); 195 if (verifyResult === true) { 196 console.info('verify success'); 197 } else { 198 console.error('verify failed'); 199 } 200 } 201 ```