RSA加解密开始构建工具类就是举步维艰,官方文档虽然很全,但是还是有很多小瑕疵,在自己经过几天的时间,彻底解决了中文乱码的问题、分段加密的问题。
首先看官方示例代码(以RSA非对称加解密(多次调用doFinal实现分段)为例:):
import cryptoFramework from "@ohos.security.cryptoFramework"
function stringToUint8Array(str) {
var arr = [];
for (var i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
var tmpArray = new Uint8Array(arr);
return tmpArray;
}
// 字节流转成可理解的字符串
function uint8ArrayToString(array) {
let arrayString = '';
for (let i = 0; i < array.length; i++) {
arrayString += String.fromCharCode(array[i]);
}
return arrayString;
}
function encryptLongMessagePromise() {
let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
let globalCipherOutput;
let globalDecodeOutput;
var globalKeyPair;
let plainTextSplitLen = 64; // RSA每次加解密允许的原文长度大小与密钥位数和填充模式等有关,详细规格内容见overview文档
let cipherTextSplitLen = 128; // RSA密钥每次加密生成的密文数据长度计算方式:密钥位数/8
let keyGenName = "RSA1024";
let cipherAlgName = "RSA1024|PKCS1";
let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // 创建非对称密钥生成器对象
let cipher = cryptoFramework.createCipher(cipherAlgName); // 创建加密Cipher对象
let decoder = cryptoFramework.createCipher(cipherAlgName); // 创建解密Decoder对象
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("testRsaMultiDoFinal");
}, 10);
}).then(() => {
return asyKeyGenerator.generateKeyPair(); // 生成rsa密钥
}).then(keyPair => {
globalKeyPair = keyPair; // 保存到密钥对全局变量
return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
}).then(async () => {
globalCipherOutput = [];
// 将原文按64字符进行拆分,循环调用doFinal进行加密,使用1024bit密钥时,每次加密生成128B长度的密文
for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) {
let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen);
let tempBlob = { data : stringToUint8Array(tempStr) };
let tempCipherOutput = await cipher.doFinal(tempBlob);
globalCipherOutput = globalCipherOutput.concat(Array.from(tempCipherOutput.data));
}
console.info(`globalCipherOutput len is ${globalCipherOutput.length}, data is: ${globalCipherOutput.toString()}`);
return;
}).then(() =>{
return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null);
}).then(async() => {
globalDecodeOutput = [];
// 将密文按128B进行拆分解密,得到原文后进行拼接
for (let i = 0; i < (globalCipherOutput.length / cipherTextSplitLen); i++) {
let tempBlobData = globalCipherOutput.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen);
let message = new Uint8Array(tempBlobData);
let tempBlob = { data : message };
let tempDecodeOutput = await decoder.doFinal(tempBlob);
globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data);
}
if (globalDecodeOutput === globalPlainText) {
console.info(`encode and decode success`);
} else {
console.info(`encode and decode error`);
}
return;
}).catch(error => {
console.error(`catch error, ${error.code}, ${error.message}`);
})
}
let plainTextSplitLen = 64; // RSA每次加解密允许的原文长度大小与密钥位数和填充模式等有关,详细规格内容见overview文档
注意点:在解密中,这句代码就是产生中文乱码的关键。
鸿蒙OS开发 | 更多内容↓点击 | HarmonyOS与OpenHarmony技术 |
---|---|---|
鸿蒙技术文档 | 开发知识更新库gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md 在这。 | 或+mau123789学习,是v喔 |
globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data);
好,加上我的代码
加密:
/**
* 测试RSA加密
*/
export function textRsaEncryption(value: string) {
let keyGenName = "RSA1024";
let cipherAlgName = "RSA1024|PKCS1";
//64 RSA每次加解密允许的原文长度大小与密钥位数和填充模式等有关,详细规格内容见overview文档
let plainTextSplitLen = 117;
let globalKeyPair; //密钥对
let globalEncryptionOutput; //加密输出
let arrTest = StringUtils.string2Uint8Array1(value);
//创建非对称密钥生成器对象
let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName);
// 创建加密Cipher对象
let cipherEncryption = cryptoFramework.createCipher(cipherAlgName);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("textRsaEncryption");
}, 10);
})
.then(() => {
let base64 = Base64.getInstance()
let pubKeyBlob = { data: new Uint8Array(base64.decode(publicKey)) }
let priKeyBlob = { data: new Uint8Array(base64.decode(privateKey)) }
return asyKeyGenerator.convertKey(pubKeyBlob, priKeyBlob);
})
.then(keyPair => {
globalKeyPair = keyPair; // 保存到密钥对全局变量
return cipherEncryption.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
}).then(async () => {
globalEncryptionOutput = [];
// 将原文按64字符进行拆分,循环调用doFinal进行加密,使用1024bit密钥时,每次加密生成128B长度的密文
for (let i = 0; i < (arrTest.length / plainTextSplitLen); i++) {
let tempArr = arrTest.slice(i * plainTextSplitLen, (i + 1) * plainTextSplitLen);
let tempBlob = { data: tempArr };
let tempCipherOutput = await cipherEncryption.doFinal(tempBlob);
globalEncryptionOutput = globalEncryptionOutput.concat(Array.from(tempCipherOutput.data));
}
let base64 = Base64.getInstance()
let enStr = base64.encode(globalEncryptionOutput)
LogUtils.i("加密总长度:" + globalEncryptionOutput.length + "\n生成加密串:\n" + enStr)
return enStr
})
.catch(error => {
LogUtils.i(`加密异常, ${error.code}, ${error.message}`);
})
}复制
解密:
/**
* 测试RSA解密
*/
export function textRsaDecryption(value: string) {
let keyGenName = "RSA1024";
let cipherAlgName = "RSA1024|PKCS1";
// RSA密钥每次加密生成的密文数据长度计算方式:密钥位数/8
let cipherTextSplitLen = 128;
let globalKeyPair; //密钥对
//创建非对称密钥生成器对象
let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName);
// 创建解密Decoder对象
let cipherDecryption = cryptoFramework.createCipher(cipherAlgName);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("textRsaEncryption");
}, 10);
})
.then(() => {
let base64 = Base64.getInstance()
let pubKeyBlob = { data: new Uint8Array(base64.decode(publicKey)) }
let priKeyBlob = { data: new Uint8Array(base64.decode(privateKey)) }
return asyKeyGenerator.convertKey(pubKeyBlob, priKeyBlob);
})
.then(keyPair => {
globalKeyPair = keyPair; // 保存到密钥对全局变量
return cipherDecryption.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null);
}).then(async () => {
let base64 = Base64.getInstance()
let globalCipherOutput1 = new Uint8Array(base64.decode(value))
let len = globalCipherOutput1.length
//解密输出
let globalDecryptionOutput = new Uint8Array(len);
let globalOffset = 0
// 将密文按128B进行拆分解密,得到原文后进行拼接
for (let i = 0; i < (len / cipherTextSplitLen); i++) {
let tempBlobData = globalCipherOutput1.subarray(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen);
let message = new Uint8Array(tempBlobData);
let tempBlob = { data: message };
let tempDecodeOutput = await cipherDecryption.doFinal(tempBlob);
//存入数组 解决边累加边转中文时 字节错乱出现乱码
globalDecryptionOutput.set(tempDecodeOutput.data, globalOffset)
//偏移量
globalOffset += tempDecodeOutput.data.byteLength
}
let result = StringUtils.uint8Array2String(globalDecryptionOutput)
LogUtils.i("解密串:cipherAlgName[" + cipherAlgName + "]\n" + result);
})
.catch(error => {
LogUtils.i(`解密异常,cipherAlgName[${cipherAlgName}] ${error.code}, ${error.message}`);
})
}复制
运行代码:
Text("RSA加解密联测")
.TextNormalStyle()
.fontSize(16)
.fontWeight(FontWeight.Normal)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.margin({ left: 5 })
.layoutWeight(1)
.onClick(() => {
let globalPlainText = ""
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "一二三四五六七八九十"
globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
globalPlainText += "SDK向DevEco Studio提供全量API,DevEco Studio识别开发者项目中选择的设备形态,找到该设备的支持能力集,筛选支持能力集包含的API并提供API联想"
//
textRsaEncryption(globalPlainText)
.then(enStr => {
if (enStr) textRsaDecryption(enStr)
})
})
}
.width('100%')
.height(50)
.margin({ top: 10 })
.padding(5)复制
运行结果:
终于大功告成!!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。