最近在接手一个金融理财类鸿蒙应用的底层安全重构时,遭遇了上架审核的滑铁卢。安全扫描报告直接指出:本地数据库与偏好设置中的敏感字段(如银行卡号、身份证哈希)使用了软加密,且密钥硬编码在代码中,存在极大的反编译泄露风险。这就逼迫我们必须放弃传统的 cryptoFramework 纯软件加解密,全面拥抱系统级的 HUKS(通用密钥库系统)以及国密算法。

告别硬编码,让密钥永不落盘

以前为了图方便,很多开发者会直接生成一个固定的 AES 密钥字符串作为常量。这次重构的第一步,就是把所有密钥的生成和存储全部移交给 HUKS。HUKS 的底层依托于设备的 TEE(可信执行环境),生成的密钥材料是无法导出的。应用层只能拿着一个“别名(Alias)”去请求系统代替你进行加解密运算。

typescript

import huks from '@ohos.security.huks';

const KEY_ALIAS = 'finance_master_key';

async function generateSecureKey() {
  const properties: huks.HuksParam[] = [
    { tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_AES },
    { tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 },
    { tag: huks.HuksTag.HUKS_TAG_PURPOSE, value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT },
    // 警示:如果是金融级场景,建议将模式设为 GCM,它自带完整性校验,防篡改
    { tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, value: huks.HuksCipherMode.HUKS_MODE_GCM },
    { tag: huks.HuksTag.HUKS_TAG_PADDING, value: huks.HuksKeyPadding.HUKS_PADDING_NONE }
  ];

  await huks.generateKeyItem(KEY_ALIAS, { properties });
}

注意 GCM 模式下的 IV 陷阱

密钥生成完毕,开始重构加解密逻辑时,很快遇到了第一个阻碍。HUKS 的 GCM 模式要求每次加密必须传入一个随机的 IV(初始化向量)。如果你不传,或者传了固定值,系统会直接报错。

typescript

import cryptoFramework from '@ohos.security.cryptoFramework';

async function encryptData(plainText: string): Promise<string> {
  // 必须每次生成 12 字节的随机 IV
  const ivBlob = await cryptoFramework.createRandom().generateRandomSync(12);
  
  const encryptOptions: huks.HuksOptions = {
    properties: [
      // ... 前面的基础属性
      { tag: huks.HuksTag.HUKS_TAG_PURPOSE, value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT },
      { tag: huks.HuksTag.HUKS_TAG_IV, value: ivBlob.data }
    ],
    inData: new TextEncoder().encode(plainText).buffer
  };

  const handle = await huks.initSession(KEY_ALIAS, encryptOptions);
  const result = await huks.finishSession(handle.handle, encryptOptions);
  
  // 核心警示:HUKS 不会帮你保存 IV。你必须把 IV 和密文拼接在一起存入数据库。
  // 否则解密时无法还原。
  const combined = new Uint8Array(ivBlob.data.length + result.outData.byteLength);
  combined.set(ivBlob.data, 0);
  combined.set(new Uint8Array(result.outData), ivBlob.data.length);
  
  return arrayBufferToBase64(combined.buffer);
}

跨设备与系统备份的降级策略

重构完成后,我们在测试换机克隆功能时发现了致命问题。因为 HUKS 的密钥是强绑定在当前设备上的,当用户将数据迁移到新手机时,旧的加密数据全部变成了乱码,应用直接崩溃。

这是一个极其深刻的安全边界问题。对于金融类数据,必须通过 BackupExtensionAbility 将本地数据库排除在系统备份之外。在应用启动时,进行设备指纹校验,如果发现是全新的设备,直接清空本地缓存,强制用户重新登录拉取云端脱敏后的数据,确保安全与体验的平衡。

引入国密 SM4 算法。查阅 HUKS 文档,将上述的 HUKS_ALG_AES 替换为 HUKS_ALG_SM4。使用同样的模式进行加密,把生成的密文存入关系型数据库,尝试写一段代码,模拟一次拔掉网线后的冷启动解密,验证数据的完整性。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐