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)复制
运行结果:
终于大功告成!!
审核编辑 黄宇
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
API
+关注
关注
2文章
1499浏览量
61961 -
RSA
+关注
关注
0文章
59浏览量
18885 -
OpenHarmony
+关注
关注
25文章
3713浏览量
16254 -
鸿蒙OS
+关注
关注
0文章
188浏览量
4382
发布评论请先 登录
相关推荐
鸿蒙OS开发实战:【ArkTS 实现MQTT协议(2)】
1. 协议传输通道仅为TCPSocket
2. 基于HarmonyOS SDK API 9开发
3. 开发语言:ArkTS,TypeScript
labviewAES加解密小程序
本帖最后由 eehome 于 2013-1-5 10:10 编辑
使用AES算法对128bit加密和解密版本:LabVIEW 8.6 8.6.1作者:zerld功能:使用AES算法对128bit加密和解密为便于阅读,算法还留有优化空间。本
发表于 02-22 14:12
硬件加解密的分类
文章目录1、硬件加解密的分类2、ARM-CE / ARM-NEON3、Soc crypto engion4、cryptoisland5、cryptocell1、硬件加解密的分类在armv8的芯片
发表于 07-22 07:55
硬件加解密主要优点及引擎种类
运算引擎,将一串明码资料经过加密或编码(Cryptography)后变成一堆不具意义的乱码,大幅降低数据传输的风险,但资料加密或编码化是复杂的运算过程,极耗CPU资源,大量加解密资料需求会造成CPU效能
发表于 08-28 07:29
STM32加解密技术
没有加解密技术是万万不能的• 通讯安全• 平台安全• *例外:STM32 RDP保护知识产权• 加解密技术不是万能的• 只是工具• 无法代替其它STM32安全技术
发表于 09-08 08:18
RSA加解密系统及其单芯片实现
RSA加解密系统及其单芯片实现随着计算机科技的进步,带给人类极大的便利性,但伴随而来的却是安全性之问题。最简单便利的安全措施是利用使用者账号及密码加以控管,但密
发表于 11-20 16:25
•27次下载
鸿蒙开发之ArkTS基础知识
一、ArkTS简介 ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript(简称TS)的基础上,匹配了鸿蒙的ArkUI框架,扩展了声明式UI、状态管理
评论