RSA加解密開始構(gòu)建工具類就是舉步維艱,官方文檔雖然很全,但是還是有很多小瑕疵,在自己經(jīng)過幾天的時間,徹底解決了中文亂碼的問題、分段加密的問題。
首先看官方示例代碼(以RSA非對稱加解密(多次調(diào)用doFinal實現(xiàn)分段)為例:):
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;
}
// 字節(jié)流轉(zhuǎn)成可理解的字符串
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每次加解密允許的原文長度大小與密鑰位數(shù)和填充模式等有關(guān),詳細(xì)規(guī)格內(nèi)容見overview文檔
let cipherTextSplitLen = 128; // RSA密鑰每次加密生成的密文數(shù)據(jù)長度計算方式:密鑰位數(shù)/8
let keyGenName = "RSA1024";
let cipherAlgName = "RSA1024|PKCS1";
let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // 創(chuàng)建非對稱密鑰生成器對象
let cipher = cryptoFramework.createCipher(cipherAlgName); // 創(chuàng)建加密Cipher對象
let decoder = cryptoFramework.createCipher(cipherAlgName); // 創(chuàng)建解密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字符進(jìn)行拆分,循環(huán)調(diào)用doFinal進(jìn)行加密,使用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進(jìn)行拆分解密,得到原文后進(jìn)行拼接
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每次加解密允許的原文長度大小與密鑰位數(shù)和填充模式等有關(guān),詳細(xì)規(guī)格內(nèi)容見overview文檔
注意點:在解密中,這句代碼就是產(chǎn)生中文亂碼的關(guān)鍵。
鴻蒙OS開發(fā) | 更多內(nèi)容↓點擊 | HarmonyOS與OpenHarmony技術(shù) |
---|---|---|
鴻蒙技術(shù)文檔 | 開發(fā)知識更新庫gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md 在這。 | 或+mau123789學(xué)習(xí),是v喔 |
globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data);
好,加上我的代碼
加密:
/**
* 測試RSA加密
*/
export function textRsaEncryption(value: string) {
let keyGenName = "RSA1024";
let cipherAlgName = "RSA1024|PKCS1";
//64 RSA每次加解密允許的原文長度大小與密鑰位數(shù)和填充模式等有關(guān),詳細(xì)規(guī)格內(nèi)容見overview文檔
let plainTextSplitLen = 117;
let globalKeyPair; //密鑰對
let globalEncryptionOutput; //加密輸出
let arrTest = StringUtils.string2Uint8Array1(value);
//創(chuàng)建非對稱密鑰生成器對象
let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName);
// 創(chuàng)建加密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字符進(jìn)行拆分,循環(huán)調(diào)用doFinal進(jìn)行加密,使用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}`);
})
}復(fù)制
解密:
/**
* 測試RSA解密
*/
export function textRsaDecryption(value: string) {
let keyGenName = "RSA1024";
let cipherAlgName = "RSA1024|PKCS1";
// RSA密鑰每次加密生成的密文數(shù)據(jù)長度計算方式:密鑰位數(shù)/8
let cipherTextSplitLen = 128;
let globalKeyPair; //密鑰對
//創(chuàng)建非對稱密鑰生成器對象
let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName);
// 創(chuàng)建解密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進(jìn)行拆分解密,得到原文后進(jìn)行拼接
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);
//存入數(shù)組 解決邊累加邊轉(zhuǎn)中文時 字節(jié)錯亂出現(xiàn)亂碼
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}`);
})
}復(fù)制
運行代碼:
Text("RSA加解密聯(lián)測")
.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識別開發(fā)者項目中選擇的設(shè)備形態(tài),找到該設(shè)備的支持能力集,篩選支持能力集包含的API并提供API聯(lián)想"
//
textRsaEncryption(globalPlainText)
.then(enStr = > {
if (enStr) textRsaDecryption(enStr)
})
})
}
.width('100%')
.height(50)
.margin({ top: 10 })
.padding(5)復(fù)制
運行結(jié)果:
終于大功告成!!
審核編輯 黃宇
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。
舉報投訴
-
API
+關(guān)注
關(guān)注
2文章
1510瀏覽量
62394 -
RSA
+關(guān)注
關(guān)注
0文章
59瀏覽量
18950 -
OpenHarmony
+關(guān)注
關(guān)注
25文章
3744瀏覽量
16577 -
鴻蒙OS
+關(guān)注
關(guān)注
0文章
190瀏覽量
4537
發(fā)布評論請先 登錄
相關(guān)推薦
鴻蒙OS開發(fā)實戰(zhàn):【ArkTS 實現(xiàn)MQTT協(xié)議(2)】
1. 協(xié)議傳輸通道僅為TCPSocket
2. 基于HarmonyOS SDK API 9開發(fā)
3. 開發(fā)語言:ArkTS,TypeScript
labviewAES加解密小程序
本帖最后由 eehome 于 2013-1-5 10:10 編輯
使用AES算法對128bit加密和解密版本:LabVIEW 8.6 8.6.1作者:zerld功能:使用AES算法對128bit加密和解密為便于閱讀,算法還留有優(yōu)化空間。本
發(fā)表于 02-22 14:12
硬件加解密的分類
文章目錄1、硬件加解密的分類2、ARM-CE / ARM-NEON3、Soc crypto engion4、cryptoisland5、cryptocell1、硬件加解密的分類在armv8的芯片
發(fā)表于 07-22 07:55
硬件加解密主要優(yōu)點及引擎種類
運算引擎,將一串明碼資料經(jīng)過加密或編碼(Cryptography)后變成一堆不具意義的亂碼,大幅降低數(shù)據(jù)傳輸?shù)娘L(fēng)險,但資料加密或編碼化是復(fù)雜的運算過程,極耗CPU資源,大量加解密資料需求會造成CPU效能
發(fā)表于 08-28 07:29
STM32加解密技術(shù)
沒有加解密技術(shù)是萬萬不能的? 通訊安全? 平臺安全? *例外:STM32 RDP保護(hù)知識產(chǎn)權(quán)? 加解密技術(shù)不是萬能的? 只是工具? 無法代替其它STM32安全技術(shù)
發(fā)表于 09-08 08:18
鴻蒙 OS 應(yīng)用開發(fā)初體驗
的 IDE、鴻蒙生態(tài)的開發(fā)語言 ArkTS,通過模擬器運行起來了鴻蒙 OS 版 HelloWorld。對于已經(jīng)有移動
發(fā)表于 11-02 19:38
RSA加解密系統(tǒng)及其單芯片實現(xiàn)
RSA加解密系統(tǒng)及其單芯片實現(xiàn)隨著計算機科技的進(jìn)步,帶給人類極大的便利性,但伴隨而來的卻是安全性之問題。最簡單便利的安全措施是利用使用者賬號及密碼加以控管,但密
發(fā)表于 11-20 16:25
?27次下載
鴻蒙開發(fā)之ArkTS基礎(chǔ)知識
一、ArkTS簡介 ArkTS是HarmonyOS優(yōu)選的主力應(yīng)用開發(fā)語言。它在TypeScript(簡稱TS)的基礎(chǔ)上,匹配了鴻蒙的ArkUI框架,擴展了聲明式UI、狀態(tài)管理
鴻蒙OS開發(fā)問題:(ArkTS) 【解決中文亂碼 string2Uint8Array、uint8Array2String】
在進(jìn)行base64編碼中,遇到中文如果不進(jìn)行處理一定會出現(xiàn)亂碼
評論