使用RSA非对称密钥（PKCS1\_OAEP模式）加解密(ArkTS)
===================================

对应的算法规格请查看[非对称密钥加解密算法规格：RSA](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/crypto-asym-encrypt-decrypt-spec#rsa)。

**加密**

1.  调用[cryptoFramework.createAsyKeyGeneratorBySpec](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#cryptoframeworkcreateasykeygeneratorbyspec10)、[AsyKeyGeneratorBySpec.generateKeyPair](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#generatekeypair10)，指定密钥参数，生成RSA非对称密钥对（KeyPair）。
    
    如何生成RSA非对称密钥对，开发者可参考下文示例，并结合[非对称密钥生成和转换规格：RSA](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/crypto-asym-key-generation-conversion-spec#rsa)和[指定密钥参数生成非对称密钥对](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/crypto-generate-asym-key-pair-from-key-spec)理解，参考文档与当前示例可能存在入参差异，请在阅读时注意区分。
    
2.  调用[cryptoFramework.createCipher](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#cryptoframeworkcreatecipher)，指定字符串参数'RSA2048|PKCS1\_OAEP|SHA256|MGF1\_SHA1'，创建非对称密钥类型为RSA2048、填充模式为PKCS1\_OAEP、摘要算法为SHA256、掩码摘要为MGF1\_SHA1的RSA密钥的Cipher实例，用于完成加解密操作。
    
3.  调用[Cipher.init](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#init-1)，设置模式为加密（cryptoFramework.CryptoMode.ENCRYPT\_MODE），指定加密密钥（KeyPair.PubKey），初始化加密Cipher实例。
    
    非对称密钥无加密参数，直接传入null。
    
4.  在调用Cipher.doFinal前，调用[Cipher.setCipherSpec](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#setcipherspec10)设置PKCS1\_OAEP填充参数pSource。调用[Cipher.getCipherSpec](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#getcipherspec10)可获得OAEP相关参数。
    
5.  调用[Cipher.doFinal](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#dofinal-1)，传入明文，获取加密后的数据。
    

**解密**

1.  由于RSA算法的Cipher实例不支持重复init操作，需要调用[cryptoFramework.createCipher](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#cryptoframeworkcreatecipher)，重新生成Cipher实例。
    
2.  调用[Cipher.init](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#init-1)，设置模式为解密（cryptoFramework.CryptoMode.DECRYPT\_MODE），指定解密密钥（KeyPair.PriKey）初始化解密Cipher实例。PKCS1\_OAEP模式无额外加密参数，直接传入null。
    
3.  在调用Cipher.doFinal前，调用[Cipher.setCipherSpec](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#setcipherspec10)设置PKCS1\_OAEP填充参数pSource，此处需要和加密时设置的保持一致。调用[Cipher.getCipherSpec](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#getcipherspec10)可获得OAEP相关参数。
    
4.  调用[Cipher.doFinal](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-cryptoframework#dofinal-1)，传入密文，获取解密后的数据。
    

*   异步方法示例：
    
    import { cryptoFramework } from '@kit.CryptoArchitectureKit';
    import { buffer } from '@kit.ArkTS';
    
    // 根据密钥参数属性构造RSA非对称密钥对密钥参数
    function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) {
      let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
        n: nIn,
        algName: 'RSA',
        specType: cryptoFramework.AsyKeySpecType.COMMON\_PARAMS\_SPEC
      };
      let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = {
        params: rsaCommSpec,
        sk: dIn,
        pk: eIn,
        algName: 'RSA',
        specType: cryptoFramework.AsyKeySpecType.KEY\_PAIR\_SPEC
      };
      return rsaKeyPairSpec;
    }
    
    // 生成RSA2048密钥对参数
    function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec {
      let nIn =
        BigInt(' ');
      let eIn = BigInt('0x010001');
      let dIn =
        BigInt(' ');
      return genRsaKeyPairSpec(nIn, eIn, dIn);
    }
    
    async function rsaUseSpecDecryptOAEPPromise() {
      let plan = 'This is a test';
      // 获得RSA密钥对密钥参数对象
      let rsaKeyPairSpec = genRsa2048KeyPairSpec();
      // 根据RSA密钥对参数生成RSA密钥对
      let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
      let cipher = cryptoFramework.createCipher('RSA2048|PKCS1\_OAEP|SHA256|MGF1\_SHA1');
      let decoder = cryptoFramework.createCipher('RSA2048|PKCS1\_OAEP|SHA256|MGF1\_SHA1');
      // RSA加解密PKCS1-OAEP模式填充字节流P
      let pSource = new Uint8Array(\[1, 2, 3, 4\]);
      let input: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(plan, 'utf-8').buffer) };
      // 生成密钥对
      let keyPair = await rsaGeneratorSpec.generateKeyPair();
      // 进行加密操作初始化
      await cipher.init(cryptoFramework.CryptoMode.ENCRYPT\_MODE, keyPair.pubKey, null);
      // get和set操作可以放在Cipher对象init之后，此处对cipher进行set和get操作
      cipher.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_PSRC\_UINT8ARR, pSource);
      let retP = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_PSRC\_UINT8ARR);
      // 比较get出来的P字节流与set进去的P字节流是否一致
      if (retP.toString() != pSource.toString()) {
        console.error('error init pSource ' + retP);
      } else {
        console.info('pSource changed == ' + retP);
      }
      // 进行OAEP其他参数的get操作
      let md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MD\_NAME\_STR);
      console.info('md == ' + md);
      let mgf = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF\_NAME\_STR);
      console.info('mgf == ' + mgf);
      let mgf1Md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_MD\_STR);
      console.info('mgf1Md == ' + mgf1Md);
      let cipherDataBlob = await cipher.doFinal(input);
      // get和set操作可以放在Cipher对象init之前，且与init之后等价，此处对decoder进行set和get操作
      decoder.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_PSRC\_UINT8ARR, pSource);
      retP = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_PSRC\_UINT8ARR);
      // 比较get出来的P字节流与set进去的P字节流是否一致
      if (retP.toString() != pSource.toString()) {
        console.error('error init pSource ' + retP);
      } else {
        console.info('pSource changed == ' + retP);
      }
      // 进行OAEP其他参数的get操作
      md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MD\_NAME\_STR);
      console.info('md == ' + md);
      mgf = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF\_NAME\_STR);
      console.info('mgf == ' + mgf);
      mgf1Md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_MD\_STR);
      console.info('mgf1Md == ' + mgf1Md);
      // 初始化解密操作
      await decoder.init(cryptoFramework.CryptoMode.DECRYPT\_MODE, keyPair.priKey, null);
      let decodeData = await decoder.doFinal(cipherDataBlob);
      // 解密成功
      if (decodeData.data.toString() === input.data.toString()) {
        console.info('oaep decrypt result: success.');
      } else {
        console.error('oaep decrypt result: fail.');
      }
    }
    
*   同步方法示例：
    
    import { cryptoFramework } from '@kit.CryptoArchitectureKit';
    import { buffer } from '@kit.ArkTS';
    // 根据密钥参数属性构造RSA非对称密钥对密钥参数
    function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) {
      let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
        n: nIn,
        algName: 'RSA',
        specType: cryptoFramework.AsyKeySpecType.COMMON\_PARAMS\_SPEC
      };
      let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = {
        params: rsaCommSpec,
        sk: dIn,
        pk: eIn,
        algName: 'RSA',
        specType: cryptoFramework.AsyKeySpecType.KEY\_PAIR\_SPEC
      };
      return rsaKeyPairSpec;
    }
    // 生成RSA2048密钥对参数
    function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec {
      let nIn = BigInt(' ');
      let eIn = BigInt('0x010001');
      let dIn = BigInt(' ');
      return genRsaKeyPairSpec(nIn, eIn, dIn);
    }
    function main() {
      let plan = 'This is a test';
      // 获得RSA密钥对密钥参数对象
      let rsaKeyPairSpec = genRsa2048KeyPairSpec();
      // 根据RSA密钥对参数生成RSA密钥对
      let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
      let cipher = cryptoFramework.createCipher('RSA2048|PKCS1\_OAEP|SHA256|MGF1\_SHA1');
      let decoder = cryptoFramework.createCipher('RSA2048|PKCS1\_OAEP|SHA256|MGF1\_SHA1');
      // RSA加解密PKCS1-OAEP模式填充字节流P
      let pSource = new Uint8Array(\[1, 2, 3, 4\]);
      let input: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(plan, 'utf-8').buffer) };
      // 生成密钥对
      let keyPair = rsaGeneratorSpec.generateKeyPairSync();
      // 进行加密操作初始化
      cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT\_MODE, keyPair.pubKey, null);
      // get和set操作可以放在Cipher对象init之后，此处对cipher进行set和get操作
      cipher.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_PSRC\_UINT8ARR, pSource);
      let retP = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_PSRC\_UINT8ARR);
      // 比较get出来的P字节流与set进去的P字节流是否一致
      if (retP.toString() != pSource.toString()) {
        console.error('error init pSource ' + retP);
      } else {
        console.info('pSource changed == ' + retP);
      }
      // 进行OAEP其他参数的get操作
      let md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MD\_NAME\_STR);
      console.info('md == ' + md);
      let mgf = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF\_NAME\_STR);
      console.info('mgf == ' + mgf);
      let mgf1Md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_MD\_STR);
      console.info('mgf1Md == ' + mgf1Md);
      let cipherDataBlob = cipher.doFinalSync(input);
      // get和set操作可以放在Cipher对象init之前，且与init之后等价，此处对decoder进行set和get操作
      decoder.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_PSRC\_UINT8ARR, pSource);
      retP = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_PSRC\_UINT8ARR);
      // 比较get出来的P字节流与set进去的P字节流是否一致
      if (retP.toString() != pSource.toString()) {
        console.error('error init pSource ' + retP);
      } else {
        console.info('pSource changed == ' + retP);
      }
      // 进行OAEP其他参数的get操作
      md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MD\_NAME\_STR);
      console.info('md == ' + md);
      mgf = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF\_NAME\_STR);
      console.info('mgf == ' + mgf);
      mgf1Md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP\_MGF1\_MD\_STR);
      console.info('mgf1Md == ' + mgf1Md);
      // 初始化解密操作
      decoder.initSync(cryptoFramework.CryptoMode.DECRYPT\_MODE, keyPair.priKey, null);
      let decodeData = decoder.doFinalSync(cipherDataBlob);
      // 解密成功
      if (decodeData.data.toString() === input.data.toString()) {
        console.info('oaep decrypt result: success.');
      } else {
        console.error('oaep decrypt result: fail.');
      }
    }