首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

鸿蒙开发:加密算法封装

  • 24-12-16 12:05
  • 3415
  • 5876
juejin.cn

前言

加密算法是开发中常见的业务,为了安全起见,客户端与服务端传输数据,往往是通过加密之后进行通信,这样做的目的,可以保证数据的机密性,防止敏感数据泄露,而鸿蒙系统中,关于加密算法就比较容易实现,毕竟ArkTs是基于TypeScript实现的,所以有些算法之间基本是通用的。

加密方式有很多,比如对称加密,非对称加密,还有常见的消息摘要算法MD5,SHA等等,本文主要概述常见的几种算法,并简单封装后使用。

消息摘要算法

消息摘要算法,也就是哈希算法或单向散列算法,通过任意长度的消息,运算生成固定长度摘要的算法,鸿蒙中主要是通过cryptoFramework.createMd方法来实现各个算法。

目前支持的算法与规格如下:

摘要算法支持种类API版本
HASHSHA19+
HASHSHA2249+
HASHSHA2569+
HASHSHA3849+
HASHSHA5129+
HASHMD59+
HASHSM310+

举一个很简单的SHA256算法,其他规格,只需要更改种类即可。

TypeScript
复制代码
let md = cryptoFramework.createMd("SHA256") await md.update({ data: new Uint8Array(buffer.from("加密的数据", 'utf-8').buffer) }) let mdResult = await md.digest() console.info('===加密后结果:' + mdResult.data) let sha256Result = this.uint8ArrayToString(mdResult.data) console.info('===转字符串后结果:' + sha256Result) let mdLen = md.getMdLength() console.info("===加密后长度: " + mdLen)

再比如,MD5:

TypeScript
复制代码
let md = cryptoFramework.createMd("MD5") await md.update({ data: new Uint8Array(buffer.from("加密的数据", 'utf-8').buffer) }) let mdResult = await md.digest() console.info('===加密后结果:' + mdResult.data) let sha256Result = this.uint8ArrayToString(mdResult.data) console.info('===转字符串后结果:' + sha256Result) let mdLen = md.getMdLength() console.info("===加密后长度: " + mdLen)

从以上的代码中可以看出,基本上系统提供的Api已经足够的简洁。

Base64

其实要论严格来说,base64并不是加密算法,只是对应的编码格式,用于在文本协议中表示二进制数据,通过使用Base64编码,可以将二进制数据转换为可打印的ACSII字符,即Base64编码是从二进制到字符的过程,从而保证数据在传输过程中不受损失。

在鸿蒙当中也提供了Base64的编码与解密,使用起来也是非常的简单。

TypeScript
复制代码
// Base64 编码 public base64Encode(str: string): string { let blob: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(str, 'utf-8').buffer) } let base64Helper = new util.Base64Helper() return base64Helper.encodeToStringSync(blob.data) } // Base64 解密 public base64Decode(input: string): string { let base64Helper = new util.Base64Helper() let uint8Array = base64Helper.decodeSync(input) return buffer.from(uint8Array).toString("utf-8") }

AES对称加密

对称加密有一个显著的特点,那就是加密方和解密方使用的是同一个密钥,这种方式加解密的速度比较快,适合数据比较长时使用,但是密钥传输的过程不安全,且容易被破解,密钥管理也比较麻烦,常见的对称加密有,AES,DES,一般最常用的就是AES。

对称加密AES提供了7种加密模式,分别是ECB、CBC、OFB、CFB、CTR、GCM和CCM,不同的加密模式适用的加解密参数不同。

分组模式密钥长度(bit)填充模式API版本
ECB[128/192/256][NoPadding/PKCS5/PKCS7]9+
CBC[128/192/256][NoPadding/PKCS5/PKCS7]9+
CTR[128/192/256][NoPadding/PKCS5/PKCS7]9+
OFB[128/192/256][NoPadding/PKCS5/PKCS7]9+
CFB[128/192/256][NoPadding/PKCS5/PKCS7]9+
GCM[128/192/256][NoPadding/PKCS5/PKCS7]9+
CCM[128/192/256][NoPadding/PKCS5/PKCS7]9+

简单举例几个模式实际代码执行,无论哪种方式,都是需要秘钥和加解密内容,一般我们进行AES开发,首先要确定秘钥,然后确定加密内容和解密内容。

ECB模式,加解密

TypeScript
复制代码
// 加密消息 async encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) { let cipher = cryptoFramework.createCipher('AES128|ECB|PKCS7'); await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, null); let cipherData = await cipher.doFinal(plainText); return cipherData; } // 解密消息 async decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) { let decoder = cryptoFramework.createCipher('AES128|ECB|PKCS7'); await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, null); let decryptData = await decoder.doFinal(cipherText); re

GCM模式,加解密

TypeScript
复制代码
genGcmParamsSpec() { let ivBlob = this.generateRandom(12); let arr = [1, 2, 3, 4, 5, 6, 7, 8]; // 8 bytes let dataAad = new Uint8Array(arr); let aadBlob: cryptoFramework.DataBlob = { data: dataAad }; arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes let dataTag = new Uint8Array(arr); let tagBlob: cryptoFramework.DataBlob = { data: dataTag }; // GCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中 let gcmParamsSpec: cryptoFramework.GcmParamsSpec = { iv: ivBlob, aad: aadBlob, authTag: tagBlob, algName: "GcmParamsSpec" }; return gcmParamsSpec; } gcmParams = this.genGcmParamsSpec(); // 加密消息 async encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) { let cipher = cryptoFramework.createCipher('AES128|GCM|PKCS7'); await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, this.gcmParams); let encryptUpdate = await cipher.update(plainText); // gcm模式加密doFinal时传入空,获得tag数据,并更新至gcmParams对象中。 this.gcmParams.authTag = await cipher.doFinal(null); return encryptUpdate; } // 解密消息 async decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) { let decoder = cryptoFramework.createCipher('AES128|GCM|PKCS7'); await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, this.gcmParams); let decryptUpdate = await decoder.update(cipherText); // gcm模式解密doFinal时传入空,验证init时传入的tag数据,如果验证失败会抛出异常。 let decryptData = await decoder.doFinal(null); if (decryptData == null) { console.info('GCM decrypt success, decryptData is null'); } return decryptUpdate; }

CCM模式,加解密

TypeScript
复制代码
genCcmParamsSpec() { let rand: cryptoFramework.Random = cryptoFramework.createRandom(); let ivBlob: cryptoFramework.DataBlob = rand.generateRandomSync(7); let aadBlob: cryptoFramework.DataBlob = rand.generateRandomSync(8); let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes let dataTag = new Uint8Array(arr); let tagBlob: cryptoFramework.DataBlob = { data: dataTag }; // CCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中 let ccmParamsSpec: cryptoFramework.CcmParamsSpec = { iv: ivBlob, aad: aadBlob, authTag: tagBlob, algName: "CcmParamsSpec" }; return ccmParamsSpec; } ccmParams = this.genCcmParamsSpec(); // 加密消息 async encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) { let cipher = cryptoFramework.createCipher('AES128|CCM'); await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, this.ccmParams); let encryptUpdate = await cipher.update(plainText); // ccm模式加密doFinal时传入空,获得tag数据,并更新至ccmParams对象中。 this.ccmParams.authTag = await cipher.doFinal(null); return encryptUpdate; } // 解密消息 async decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) { let decoder = cryptoFramework.createCipher('AES128|CCM'); await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, this.ccmParams); let decryptUpdate = await decoder.doFinal(cipherText); return decryptUpdate; }

秘钥,在实际的开发中,我们可以根据提供的字符串或者其他特定字符生成我们的秘钥,一般为Base64编码之后的字符串形式秘钥,在加解密的时候,再进行解码即可。

RSA非对称加密

非对称加密和对称加密不同之处就在于,它有两个秘钥,一个公钥,一个私钥,公钥用于加密,私钥用于解密,相对于对称加密而言,安全系数上上了一层台阶,但是也有中间人攻击的风险,常见的非对称加密有,RSA,DSA,ECC等,一般最常用的就是RSA。

RSA也提供了多种加密方式,比如PKCS1模式,PKCS1_OAEP模式,以及NoPadding。

PKCS1模式

TypeScript
复制代码
// 加密消息 async encryptMessagePromise(publicKey: cryptoFramework.PubKey, plainText: cryptoFramework.DataBlob) { let cipher = cryptoFramework.createCipher('RSA1024|PKCS1'); await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, publicKey, null); let encryptData = await cipher.doFinal(plainText); return encryptData; } // 解密消息 async decryptMessagePromise(privateKey: cryptoFramework.PriKey, cipherText: cryptoFramework.DataBlob) { let decoder = cryptoFramework.createCipher('RSA1024|PKCS1'); await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, privateKey, null); let decryptData = await decoder.doFinal(cipherText); return decryptData; }

其它模式,不再举例了,大家可以去官网查看。

封装使用

大家可以使用以上的方式进行数据的加解密,当然了,也可以自行封装,或者使用他人封装好的,针对以上,我也简单封装了一下,有需要的朋友可以拿来使用。

简单功能列表

快速使用

方式一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。

建议:在使用的模块路径下进行执行命令。

text
复制代码
ohpm install @abner/security

方式二:在工程的oh-package.json5中设置三方包依赖,配置示例如下:

text
复制代码
"dependencies": { "@abner/security": "^1.0.0"}

代码使用

1、MD5

同步

TypeScript
复制代码
let encryptContent = md5EncryptSync("加密的数据") console.log("===加密后:" + encryptContent)

异步

TypeScript
复制代码
md5Encrypt("加密的数据").then((content) => { console.log("===加密后:" + content) })

2、BASE64

编码同步

TypeScript
复制代码
let encryptContent = base64EncodeSync("我是测试数据") this.mBase64EncodeString = encryptContent console.log("===编码后:" + encryptContent)

编码异步

TypeScript
复制代码
base64Encode("我是测试数据").then((encryptContent) => { this.mBase64EncodeString = encryptContent console.log("===编码后:" + encryptContent) })

解码同步

TypeScript
复制代码
base64Decode(this.mBase64EncodeString).then((decode) => { console.log("===解码后:" + decode) })

3、SHA

sha默认是SHA256,可以根据需要进行修改,在第二个参数传入即可。

同步

TypeScript
复制代码
let encryptContent = shaEncryptSync("1") console.log("===加密后:" + encryptContent)

异步

TypeScript
复制代码
shaEncrypt("1").then((content) => { console.log("===加密后:" + content) })

修改algName

TypeScript
复制代码
let encryptContent = shaEncryptSync("1","SHA256") console.log("===加密后:" + encryptContent)

4、SM3

同步

TypeScript
复制代码
let encryptContent = sM3EncryptSync("加密的数据") console.log("===加密后:" + encryptContent)

异步

TypeScript
复制代码
sM3Encrypt("加密的数据").then((content) => { console.log("===加密后:" + content) })

5、AES

随机生成SymKey密钥【异步】

TypeScript
复制代码
aesGenerateSymKey().then((symKey) => { this.mSymKey = symKey console.log("===密钥:" + symKey) })

随机生成SymKey密钥【同步】

TypeScript
复制代码
let symKey = aesGenerateSymKeySync() this.mSymKey = symKey console.log("===密钥:" + symKey)

字符串生成密钥【异步】

TypeScript
复制代码
aesGenerateSymKey("1234").then((symKey) => { this.mSymKey = symKey console.log("===密钥:" + symKey) })

字符串生成密钥【同步】

TypeScript
复制代码
let symKeyString = aesGenerateSymKeySync("1234") this.mSymKey = symKeyString console.log("===密钥:" + symKeyString)

加密数据【异步】【ECB模式】

TypeScript
复制代码
aesEncryptString("123", this.mSymKey).then((result) => { this.encryptString = result console.log("===加密后数据:" + result) })

解密数据【异步】【ECB模式】

TypeScript
复制代码
aesDecryptString(this.encryptString, this.mSymKey).then((result) => { console.log("===解密后数据:" + result) })

加密数据【同步】【ECB模式】

TypeScript
复制代码
let result = aesEncryptStringSync("123", this.mSymKey) this.encryptString = result console.log("===加密后数据:" + result)

解密数据【同步】【ECB模式】

TypeScript
复制代码
let decryptString = aesDecryptStringSync(this.encryptString!, this.mSymKey!) console.log("===加密后数据:" + decryptString)

6、RSA

随机生成KeyPair密钥对 【异步】

TypeScript
复制代码
rsaGenerateAsyKey().then((keyPair) => { let pubKey = keyPair.pubKey //公钥 let priKey = keyPair.priKey //私钥 this.priKey = priKey this.pubKey = pubKey })

随机生成KeyPair密钥对【同步】

TypeScript
复制代码
let keyPair = rsaGenerateAsyKeySync() let pubKey1 = keyPair.pubKey //公钥 let priKey1 = keyPair.priKey //私钥 this.priKey = priKey1 this.pubKey = pubKey1

随机生成字符串密钥对 【异步】

TypeScript
复制代码
rsaGenerateAsyKeyPem().then((keyPairPem) => { let pubKey = keyPairPem.pubKey //公钥 let priKey = keyPairPem.priKey //私钥 console.log("===公钥:" + pubKey) console.log("===私钥:" + priKey) })

随机生成字符串密钥对【同步】

TypeScript
复制代码
let keyPairPem = generateAsyKeyPemSync() let pubKeyPem = keyPairPem.pubKey //公钥 let priKeyPem = keyPairPem.priKey //私钥 console.log("===公钥:" + pubKeyPem) console.log("===私钥:" + priKeyPem)

随机生成密钥对二进制【异步】

TypeScript
复制代码
rsaGenerateAsyKeyDataBlob().then((dataBlobArray) => { let pubKey: cryptoFramework.DataBlob = dataBlobArray[0] let priKey: cryptoFramework.DataBlob = dataBlobArray[1] console.log("===公钥二进制:" + JSON.stringify(pubKey)) console.log("===私钥二进制:" + JSON.stringify(priKey)) })

随机生成密钥对二进制【同步】

TypeScript
复制代码
let dataBlobArray = rsaGenerateAsyKeyDataBlobSync() let pubKey: cryptoFramework.DataBlob = dataBlobArray[0] let priKey: cryptoFramework.DataBlob = dataBlobArray[1] console.log("===公钥二进制:" + JSON.stringify(pubKey)) console.log("===私钥二进制:" + JSON.stringify(priKey))

指定二进制数据生成KeyPair密钥对【异步】

TypeScript
复制代码
rsaGenKeyPairByData(this.pkData, this.skData).then((keyPair) => { let pubKey = keyPair.pubKey //公钥 let priKey = keyPair.priKey //私钥 this.priKey = priKey this.pubKey = pubKey })

指定二进制数据生成KeyPair密钥对【同步】

TypeScript
复制代码
let keyPairByDataSync = rsaGenKeyPairByDataSync(this.pkData, this.skData) let pubKeyPairByData = keyPairByDataSync.pubKey //公钥 let priKeyPairByData = keyPairByDataSync.priKey //私钥 this.priKey = priKeyPairByData this.pubKey = pubKeyPairByData

二进制数据生成字符串密钥对【异步】

TypeScript
复制代码
rsaGenKeyPairByDataPem(this.pkData, this.skData).then((keyPairPem) => { let pubKeyPem = keyPairPem.pubKey //公钥 let priKeyPem = keyPairPem.priKey //私钥 console.log("===公钥:" + pubKeyPem) console.log("===私钥:" + priKeyPem) })

二进制数据生成字符串密钥对【同步】

TypeScript
复制代码
let keyPairByDataPemSync = rsaGenKeyPairByDataPemSync(this.pkData, this.skData) let pubKeyPairByDataPem = keyPairByDataPemSync.pubKey //公钥 let priKeyPairByDataPem = keyPairByDataPemSync.priKey //私钥 console.log("===公钥:" + pubKeyPairByDataPem) console.log("===私钥:" + priKeyPairByDataPem)

字符串数据生成KeyPair密钥对【异步】

TypeScript
复制代码
rsaGenKeyPairString(this.appRsaPublicKey, this.appRsaPrivateKey).then((keyPair) => { let pubKey = keyPair.pubKey let priKey = keyPair.priKey this.priKey = priKey this.pubKey = pubKey })

字符串数据生成KeyPair密钥对【同步】

TypeScript
复制代码
let keyPair2 = rsaGenKeyPairStringSync(this.publicPkcs1Str1024, this.priKeyPkcs1Str1024) let pubKey3 = keyPair2.pubKey let priKey3 = keyPair2.priKey this.priKey = priKey3 this.pubKey = pubKey3

字符串数据生成字符串密钥对【异步】

TypeScript
复制代码
rsaGenKeyPairStringPem(this.appRsaPublicKey, this.appRsaPrivateKey).then((keyPair) => { let pubKeyPem = keyPair.pubKey //公钥 let priKeyPem = keyPair.priKey //私钥 console.log("===公钥:" + pubKeyPem) console.log("===私钥:" + priKeyPem) })

字符串数据生成字符串密钥对【同步】

TypeScript
复制代码
let keyPairStringPemSync = rsaGenKeyPairStringPemSync(this.publicPkcs1Str1024, this.priKeyPkcs1Str1024) let pubKeyPairStringPemSync = keyPairStringPemSync.pubKey //公钥 let priKeyPairStringPemSync = keyPairStringPemSync.priKey //私钥 console.log("===公钥:" + pubKeyPairStringPemSync) console.log("===私钥:" + priKeyPairStringPemSync)

字符串密钥方式加密【异步】

TypeScript
复制代码
let message = "我是一段要加密的数据" console.log("===加密前数据:" + message) rsaEncryptString(message, this.publicKey).then((data) => { this.encryptString = data console.log("===加密后数据:" + data) }).catch((e: BusinessError) => { console.log("===加密错误:" + JSON.stringify(e.message)) })

字符串密钥方式解密【异步】

TypeScript
复制代码
//必须有私钥,还有要解密的数据 rsaDecryptString(this.encryptString, this.privateKey).then((data) => { console.log("===解密后数据:" + data) })

字符串密钥方式加密【同步】

TypeScript
复制代码
let message1 = "我是一段要加密的数据" console.log("===加密前数据:" + message1) this.encryptString = rsaEncryptStringSync(message1, this.publicKey) console.log("===加密后数据:" + this.encryptString)

字符串密钥方式解密【同步】

TypeScript
复制代码
//必须有私钥,还有要解密的数据 let data = rsaDecryptStringSync(this.encryptString, this.privateKey) console.log("===解密后数据:" + data)

加密 KeyPair密钥方式【异步】 需要cryptoFramework.PubKey

TypeScript
复制代码
if (this.pubKey != undefined) { let message = "我是一段要加密的数据" console.log("===加密前数据:" + message) rsaEncryptDataBlob(message, this.pubKey!).then((data) => { this.encryptDataBlob = data console.log("===加密后数据:" + JSON.stringify(data)) }).catch((e: BusinessError) => { console.log("===加密错误:" + JSON.stringify(e.message)) }) }

解密 KeyPair密钥方式【异步】

TypeScript
复制代码
if (this.priKey != undefined && this.encryptDataBlob != undefined) { //必须有私钥,还有要解密的数据 rsaDecryptDataBlob(this.encryptDataBlob, this.priKey).then((data) => { console.log("===解密后数据:" + data) }) }

加密 KeyPair密钥方式【同步】

TypeScript
复制代码
if (this.pubKey != undefined) { let message1 = "我是一段要加密的数据" console.log("===加密前数据:" + message1) this.encryptDataBlob = rsaEncryptDataBlobSync(message1, this.pubKey!) console.log("===加密后数据:" + JSON.stringify(this.encryptDataBlob)) }

解密 KeyPair密钥方式【同步】

TypeScript
复制代码
if (this.priKey != undefined && this.encryptDataBlob != undefined) { //必须有私钥,还有要解密的数据 let data = rsaDecryptDataBlobSync(this.encryptDataBlob, this.priKey) console.log("===解密后数据:" + data) }

私钥签名 同步

TypeScript
复制代码
let sign = rsaEncryptPriKeyContentSync("123", this.privateKey) console.log("=======签名:" + sign)

公钥验签 同步

TypeScript
复制代码
//this.signData为签名内容 let signResult = rsaDecryptPubKeyContentSync("123",this.signData, this.publicKey) console.log("=======验签:" + signResult)

私钥签名 异步

TypeScript
复制代码
rsaEncryptPriKeyContent("123", this.privateKey).then((sign) => { console.log("=======签名:" + sign) })

公钥验签 异步

TypeScript
复制代码
//this.signData为签名内容 rsaDecryptPubKeyContent("123",this.signData, this.publicKey).then((signResult) => { console.log("=======验签:" + signResult) })
注:本文转载自juejin.cn的程序员一鸣的文章"https://juejin.cn/post/7447918750059544586"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

140
Android
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top