赞
踩
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)
终于大功告成!!
而网上有关鸿蒙的开发资料非常的少,假如你想学好鸿蒙的应用开发与系统底层开发。你可以参考这份资料,少走很多弯路,节省没必要的麻烦。由两位前阿里高级研发工程师联合打造的《鸿蒙NEXT星河版OpenHarmony开发文档》里面内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)技术知识点
如果你是一名Android、Java、前端等等开发人员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。下面是鸿蒙开发的学习路线图。
高清完整版请点击→《鸿蒙NEXT星河版开发学习文档》
针对鸿蒙成长路线打造的鸿蒙学习文档。话不多说,我们直接看详细资料鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,帮助大家在技术的道路上更进一步。
《鸿蒙 (OpenHarmony)开发学习视频》
《鸿蒙生态应用开发V2.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
获取这份鸿蒙星河版学习资料,请点击→《鸿蒙NEXT星河版开发学习文档》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
ArkTS语言
安装DevEco Studio
运用你的第一个ArkTS应用
ArkUI声明式UI开发
.……
《鸿蒙开发进阶》
Stage模型入门
网络管理
数据管理
电话服务
分布式应用开发
通知与窗口管理
多媒体技术
安全技能
任务管理
WebGL
国际化开发
应用测试
DFX面向未来设计
鸿蒙系统移植和裁剪定制
……
《鸿蒙开发实战》
ArkTS实践
UIAbility应用
网络案例
……
获取这份鸿蒙星河版学习资料,请点击→《鸿蒙NEXT星河版开发学习文档》
鸿蒙—作为国家主力推送的国产操作系统。部分的高校已经取消了安卓课程,从而开设鸿蒙课程;企业纷纷跟进启动了鸿蒙研发。
并且鸿蒙是完全具备无与伦比的机遇和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,未来将会支持 50 万款的应用。那么这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。