鸿蒙开发:10-加密

612 阅读4分钟

加密

鸿蒙中常用的加密解密的工具

  1. @ohos.security.cryptoFramework (加解密算法库框架)
  2. @ohos/crypto-js
  3. @pura/harmony-utils

文档

使用AES对称密钥(ECB模式)加解密(ArkTS)-加解密开发指导-加解密

如何使用AES算法加密-加解密算法

对称密钥加解密算法规格-加解密算法规格

非对称密钥加解密算法规格-加解密算法规格

前置

  1. 加密分为对称加密非对称加密
  2. 一般来说你要加密,大体的用什么加密你是知道的(比如AES、DES、RSA、MD5.....),但是还应该了解具体的加密规则:加密算法分组模式密钥长度填充模式

对称密钥加解密算法规格-加解密算法规格

非对称密钥加解密算法规格-加解密算法规格

  1. 以AES加密为例,密钥长度128,常用分组模式为ECB,使用PKCS7填充模式,加密规则的字符串参数则为AES128|ECB|PKCS7(后面加密要用到)

加密步骤

  1. 处理加密key:我们的原始密钥key一般为一定长度的字符串,在使用前需要将其转换为符合要求的Key。
    • 将原始key转换为二进制字节数组类型
    • 根据密钥长度判断是否满足长度,不足的按规则补齐,过长需要裁切(也可以使用工具中的convertKey)
    • 将转换后的key包装成需要的格式(如DataBolb)
  2. 创建加密生成器实例,如下(有些工具内置了加密实例,可以直接按加密方法调用对应加密方法)
    let cipherAlgName = 'AES128|ECB|PKCS7';
    let cipher = cryptoFramework.createCipher(cipherAlgName);
    
  3. 调用初始化方法
    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, null);
    
  4. 调用加密方法
    let cipherData = await cipher.doFinal(plainText);
    
  5. (可能需要)将密文转换为其他格式(如Base64)来方便发送

示例

1、示例1

如何使用AES算法加密-加解密算法

import { cryptoFramework } from '@kit.CryptoArchitectureKit'; 
import { buffer, util } from '@kit.ArkTS'; 
 
@Entry 
@Component 
struct AESEncryptionDecryption { 
  build() { 
    Row() { 
      Button('加解密') 
        .onClick(async () => { 
          // 导入密钥 
          let key = await getKey(); 
          // 加密 
          let globalResult = await aesEncrypt('测试', key); 
          // 解密 
          aesDecrypt(globalResult, key); 
        }) 
        .width('100%') 
        .height(50) 
    } 
    .height('100%') 
  } 
} 
 
export const base = new util.Base64Helper(); 
 
// 字节流转成可理解的字符串 
export function uint8ArrayToString(array: Uint8Array) { 
  // 将UTF-8编码转换成Unicode编码 
  let out: string = ''; 
  let index: number = 0; 
  let len: number = array.length; 
  while (index < len) { 
    let character = array[index++]; 
    switch (character >> 4) { 
      case 0: 
      case 1: 
      case 2: 
      case 3: 
      case 4: 
      case 5: 
      case 6: 
      case 7: 
        out += String.fromCharCode(character); 
        break; 
      case 12: 
      case 13: 
        out += String.fromCharCode(((character & 0x1F) << 6) | (array[index++] & 0x3F)); 
        break; 
      case 14: 
        out += String.fromCharCode(((character & 0x0F) << 12) | ((array[index++] & 0x3F) << 6) | 
          ((array[index++] & 0x3F) << 0)); 
        break; 
      default: 
        break; 
    } 
  } 
  return out; 
} 
 
// 字符串转成字节流 
function stringToUint8Array(str: string) { 
  return new Uint8Array(buffer.from(str, 'utf-8').buffer); 
} 
 
// 获取密钥 
async function getKey() { 
  let symAlgName = 'AES128'; 
  let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 
  let dataUint8Array = stringToUint8Array('Whh82GtW/EVjBkD8'); 
  let keyBlob: cryptoFramework.DataBlob = { data: dataUint8Array }; 
  let promiseSymKey = await symKeyGenerator.convertKey(keyBlob); 
  let key = base.encodeToStringSync(promiseSymKey.getEncoded().data); // 将密钥转换为base64存储 
  return key; 
} 
 
// 加密 
async function aesEncrypt(text: string, puKey: string): Promise<string> { 
  let globalResult = ''; 
  try { 
    let cipherAlgName = 'AES128|ECB|PKCS7'; 
    let globalCipher = cryptoFramework.createCipher(cipherAlgName); 
    let symAlgName = 'AES128'; 
    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 
    let dataUint8Array = base.decodeSync(puKey); 
    let keyBlob: cryptoFramework.DataBlob = { data: dataUint8Array }; 
    let promiseSymKey = await symKeyGenerator.convertKey(keyBlob); 
    await globalCipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, promiseSymKey, null); 
    let result = await globalCipher.doFinal({ data: stringToUint8Array(text) }); 
    globalResult = base.encodeToStringSync(result.data); 
    console.info('加密后的明文:' + globalResult); 
  } catch (err) { 
    console.info(err.message); 
  } 
  return globalResult; 
} 
 
// 解密 
async function aesDecrypt(text: string, key: string) { 
  let globalResult = ''; 
  try { 
    let cipherAlgName = 'AES128|ECB|PKCS7'; 
    let globalCipher = cryptoFramework.createCipher(cipherAlgName); 
    let symAlgName = 'AES128'; 
    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 
    let dataUint8Array = base.decodeSync(key); 
    let keyBlob: cryptoFramework.DataBlob = { data: dataUint8Array }; 
    let promiseSymKey = await symKeyGenerator.convertKey(keyBlob); 
    await globalCipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, promiseSymKey, null); 
    let plainText: cryptoFramework.DataBlob = { data: base.decodeSync(text) }; 
    let result = await globalCipher.doFinal(plainText); 
    globalResult = uint8ArrayToString(result.data); 
    console.info('解密后的明文:' + globalResult); 
  } catch (err) { 
    console.info(err.message); 
  } 
}
2、示例2
import { util } from '@kit.ArkTS';
import { CryptoJS } from '@ohos/crypto-js';
import { CryptoHelper, CryptoUtil, DES, Base64Util, StrUtil } from '@pura/harmony-utils';
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG = 'Base64DES';

export class Base64DES {
  static socketEncrypt(encryptString: string, keyStr?: string) {
    try {
      keyStr = 'abcdefg123456789';
      // let key: Uint8Array = Base64DES.createDESKey(StrUtil.strToUint8Array(keyStr));
      const key = CryptoJS.enc.Utf8.parse(keyStr.slice(0, 8));
      const result = CryptoJS.DES.encrypt(CryptoJS.enc.Utf8.parse(encryptString), key, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
      });
      return result.toString();

    } catch (err) {
      let error: BusinessError = err as BusinessError;
      console.log(TAG, JSON.stringify(error));
      return ''
    }

  }

  //字符串转Uint8Array
  static getBytes(str: string): Uint8Array {
    //TextEncoder默认使用"utf-8"编码
    const textEncoder: util.TextEncoder = new util.TextEncoder();
    return textEncoder.encodeInto(str);
  }

  static createDESKey(key: Uint8Array): Uint8Array {
    // DES 密钥必须是 8 字节长
    if (key.length < 8) {
      // 如果密钥过短,进行填充
      key = CryptoHelper.getUint8ArrayPaddingZero(key, 8);
    } else if (key.length > 8) {
      // 如果密钥过长,进行截断
      key = key.slice(0, 8);
    }
    return key;
  }
}