1# 使用3DES对称密钥加解密(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对应的算法规格请查看[对称密钥加解密算法规格:3DES](crypto-sym-encrypt-decrypt-spec.md#3des)。 11 12## 开发步骤 13 14**加密** 15 161. 调用[cryptoFramework.createSymKeyGenerator](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatesymkeygenerator)和[SymKeyGenerator.convertKey](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#convertkey-1),生成密钥算法为3DES、密钥长度为192位的对称密钥(SymKey)。 17 18 如何生成3DES对称密钥,开发者可参考下文示例,并结合[对称密钥生成和转换规格:3DES](crypto-sym-key-generation-conversion-spec.md#3des)和[指定二进制数据转换对称密钥](crypto-convert-binary-data-to-sym-key.md)理解,参考文档与当前示例可能存在入参差异,请在阅读时注意区分。 19 202. 调用[cryptoFramework.createCipher](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatecipher),指定字符串参数'3DES192|ECB|PKCS7',创建对称密钥类型为3DES192、分组模式为ECB、填充模式为PKCS7的Cipher实例,用于完成加密操作。 21 223. 调用[Cipher.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-1),设置模式为加密(CryptoMode.ENCRYPT_MODE),指定加密密钥(SymKey),初始化加密Cipher实例。 23 24 ECB模式无加密参数,传入null。 25 264. 调用[Cipher.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-1),更新数据(明文)。 27 28 - 当数据量较小时,可以在init完成后直接调用doFinal。 29 - 当数据量较大时,可以多次调用update,即分段加解密。 30 - 用户可以自行决定数据量大小。例如,数据量大于20字节时使用update。 31 325. 调用[Cipher.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-1),获取加密后的数据。 33 34 - 已使用update,data传入null。 35 - doFinal输出结果可能为null,在访问具体数据前,需要先判断结果是否为null,避免产生异常。 36 37**解密** 38 391. 调用[cryptoFramework.createCipher](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatecipher),指定字符串参数'3DES192|ECB|PKCS7',创建对称密钥类型为3DES192、分组模式为ECB、填充模式为PKCS7的Cipher实例,用于完成解密操作。 40 412. 调用[Cipher.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-1),设置模式为解密(CryptoMode.DECRYPT_MODE),并指定解密密钥(SymKey)初始化解密Cipher实例。ECB模式无加密参数,调用时直接传入null。 42 433. 调用[Cipher.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-1),更新数据(密文)。 44 454. 调用[Cipher.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-1),获取解密后的数据。 46 47## 开发示例 48 49当前示例以ECB分组模式为例,不需要设置加解密参数IV。 50 51如果使用CBC、CTR、OFB、CFB分组模式,需设置加解密参数IV,请参考[设置加解密参数IV](#设置加解密参数iv),并确保在生成和初始化Cipher实例时正确设置相关参数。 52 53- 异步方法示例: 54 55 ```ts 56 import { cryptoFramework } from '@kit.CryptoArchitectureKit'; 57 import { buffer } from '@kit.ArkTS'; 58 59 // 加密消息。 60 async function encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) { 61 // 如果使用CBC、CTR、OFB或CFB分组模式,需将此处修改为对应模式,并添加IV作为加解密参数。 62 let cipher = cryptoFramework.createCipher('3DES192|ECB|PKCS7'); 63 await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, null); 64 let encryptData = await cipher.doFinal(plainText); 65 return encryptData; 66 } 67 // 解密消息。 68 async function decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) { 69 // 如果使用CBC、CTR、OFB或CFB分组模式,需将此处修改为对应模式,并添加加解密参数IV。 70 let decoder = cryptoFramework.createCipher('3DES192|ECB|PKCS7'); 71 await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, null); 72 let decryptData = await decoder.doFinal(cipherText); 73 return decryptData; 74 } 75 async function genSymKeyByData(symKeyData: Uint8Array) { 76 let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData }; 77 let symGenerator = cryptoFramework.createSymKeyGenerator('3DES192'); 78 let symKey = await symGenerator.convertKey(symKeyBlob); 79 console.info('convertKey success'); 80 return symKey; 81 } 82 async function main() { 83 let keyData = new Uint8Array([238, 249, 61, 55, 128, 220, 183, 224, 139, 253, 248, 239, 239, 41, 71, 25, 235, 206, 230, 162, 249, 27, 234, 114]); 84 let symKey = await genSymKeyByData(keyData); 85 let message = "This is a test"; 86 let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) }; 87 let encryptText = await encryptMessagePromise(symKey, plainText); 88 let decryptText = await decryptMessagePromise(symKey, encryptText); 89 if (plainText.data.toString() === decryptText.data.toString()) { 90 console.info('decrypt ok'); 91 console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8')); 92 } else { 93 console.error('decrypt failed'); 94 } 95 } 96 ``` 97 98- 同步方法示例: 99 100 ```ts 101 import { cryptoFramework } from '@kit.CryptoArchitectureKit'; 102 import { buffer } from '@kit.ArkTS'; 103 104 // 加密消息。 105 function encryptMessage(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) { 106 // 如果使用CBC、CTR、OFB或CFB分组模式,需将此处修改为对应模式,并添加加解密参数IV。 107 let cipher = cryptoFramework.createCipher('3DES192|ECB|PKCS7'); 108 cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, null); 109 let encryptData = cipher.doFinalSync(plainText); 110 return encryptData; 111 } 112 // 解密消息。 113 function decryptMessage(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) { 114 // 对于CBC、CTR、OFB、CFB分组模式,需要将此处修改为对应模式,并添加加解密参数IV。 115 let decoder = cryptoFramework.createCipher('3DES192|ECB|PKCS7'); 116 decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, null); 117 let decryptData = decoder.doFinalSync(cipherText); 118 return decryptData; 119 } 120 function genSymKeyByData(symKeyData: Uint8Array) { 121 let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData }; 122 let symGenerator = cryptoFramework.createSymKeyGenerator('3DES192'); 123 let symKey = symGenerator.convertKeySync(symKeyBlob); 124 console.info('convertKeySync success'); 125 return symKey; 126 } 127 function main() { 128 let keyData = new Uint8Array([238, 249, 61, 55, 128, 220, 183, 224, 139, 253, 248, 239, 239, 41, 71, 25, 235, 206, 230, 162, 249, 27, 234, 114]); 129 let symKey = genSymKeyByData(keyData); 130 let message = "This is a test"; 131 let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) }; 132 let encryptText = encryptMessage(symKey, plainText); 133 let decryptText = decryptMessage(symKey, encryptText); 134 if (plainText.data.toString() === decryptText.data.toString()) { 135 console.info('decrypt ok'); 136 console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8')); 137 } else { 138 console.error('decrypt failed'); 139 } 140 } 141 ``` 142 143### 设置加解密参数IV 144 145下述示例为CBC分组模式,需要设置加解密参数IV。 146 147如果分组模式为CBC、CTR、OFB、CFB,需要参考如下设置加解密参数IV。ECB不需要设置加解密参数IV。 148 149 ```ts 150 function genIvParamsSpec() { 151 let ivBlob = generateRandom(8); //3DES的 CBC、CFB、OFB、CTR的iv长度为8字节。 152 let ivParamsSpec: cryptoFramework.IvParamsSpec = { 153 algName: "IvParamsSpec", 154 iv: ivBlob 155 }; 156 return ivParamsSpec; 157 } 158 let iv = genIvParamsSpec(); 159 let cipher = cryptoFramework.createCipher('3DES192|CBC|PKCS7'); 160 cipher.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, iv); 161 // 本段代码只展示CBC、CTR、OFB、CFB分段模式的不同,其他流程请参考开发示例。 162 ``` 163