HarmonyOS Developer 通用密钥库开发指导

丶龙八夷
发布于 2023-3-31 15:25
浏览
0收藏

密钥访问控制

HUKS提供了全面完善的密钥访问控制能力,确保存储在HUKS中的密钥被合法正确的访问。

首先,业务只能访问属于自己的密钥,即只能访问通过HUKS生成或导入的密钥。

其次,支持密钥的用户身份认证访问控制,对于高安敏感的业务密钥,需要在使用密钥的时候,再次要求用户即时的验证锁屏密码或生物特征,验证通过后,才能使用业务密钥。

除此之外,HUKS还支持严格限制密钥的使用用途,如支持只允许AES密钥进行加密解密,只允许RSA密钥进行签名验签。

用户身份认证访问控制

生成或导入密钥时,可以指定密钥必须经过用户身份认证后才能使用。您可以指定用于解锁设备锁屏的凭据(指纹、人脸)的子集进行身份认证。在生成/导入密钥后,即使应用进程被攻击也不会导致未经用户授权的密钥访问,一般用于高敏感且高级别安全保护的场景,比如免密登录、免密支付、自动填充密码保护场景。

除用户身份认证外,应用还须将密钥的授权访问类型(即失效条件)设置为以下两种类型之一:

  • 清除锁屏密码后密钥永久无效。设置此模式的前提是当前用户已经设置了锁屏密码,在生成/导入密钥后,一旦清除了锁屏密码,此类密钥将永久失效。注意,修改密码不会导致失效情况发生。此模式适合那些需要锁屏密码授权访问或用户强相关的数据保护的场景。
  • 用户新录入生物特征后永久无效。此模式需要当前用户至少录入了一个生物特征(如指纹)才能生效,在生成/导入密钥后,一旦录入新的生物特征,这些密钥将永久失效。注意,仅删除生物特征不会导致失效情况发生。如果您不希望新录入的生物特征后,用户还可以授权访问原有数据(密钥保护的数据),那么可以使用此模式,如免密登录,免密支付等场景。

此外,为了保证密钥使用时用户认证结果的有效性(不可重放),HUKS支持挑战值校验:在身份认证前,需要从HUKS获取挑战值(调用​​huks.initSession()​​​返回的​​HuksSessionHandle​​​中)传给用户身份认证方法(​​userIAM_userAuth.getAuthInstance​​),然后在密钥操作时校验认证令牌的挑战值。

开发流程

设置了二次用户身份认证的密钥,需要先初始化密钥会话并获取挑战值,然后将HUKS生成的挑战值传至用户身份认证方法进行用户身份认证,认证通过后获取一个认证令牌,将认证令牌传至HUKS进行密钥操作。

HarmonyOS Developer 通用密钥库开发指导-鸿蒙开发者社区

接口说明

  1. 生成或导入密钥时,在密钥属性集中需指定三个参数:用户认证类型​​HuksUserAuthType​​​、授权访问类型​​HuksAuthAccessType​​​、挑战值类型​​HuksChallengeType​​​。
    表3用户认证类型:两种类型的子集

名称

说明

HUKS_USER_AUTH_TYPE_FINGERPRINT

0x0001

用户认证类型为指纹,允许和人脸同时设置

HUKS_USER_AUTH_TYPE_FACE

0x0002

用户认证类型为人脸 ,允许和指纹同时设置


表4 安全访问类型:二选一

名称

说明

HUKS_AUTH_ACCESS_INVALID_CLEAR_PASSWORD

1

清除锁屏密码后密钥无法访问。

HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL

2

新录入生物特征后密钥无法访问,用户认证类型须包含生物认证类型。

表5 挑战值类型:三选一

名称

说明

HUKS_CHALLENGE_TYPE_NORMAL

0

普通类型,每次密钥的使用需要独立的一次用户认证

HUKS_CHALLENGE_TYPE_CUSTOM

1

自定义类型,支持和多个密钥共享一次用户认证

HUKS_CHALLENGE_TYPE_NONE

2

无挑战值类型,用户认证时不需要挑战值

注意

当指定挑战值类型为HUKS_CHALLENGE_TYPE_NONE 时,不需要传递挑战值,但是存在新的限制:在用户身份认证后,一段时间内允许访问该密钥,超时后不能访问,需要重新认证才能访问。因此应用需要额外指定超时时间HUKS_TAG_AUTH_TIMEOUT属性(最大60秒)。

  1. 使用密钥时,先初始化密钥会话,然后根据密钥生成/导入阶段指定的挑战值类型属性是否需要获取挑战值,或组装新的挑战值。
  2. 表6使用密钥的接口介绍

接口名

描述

initSession(keyAlias: string, options: HuksOptions, callback: AsyncCallback<HuksSessionHandle>) : void

初始化密钥会话,获取挑战值

updateSession(handle: number, options: HuksOptions, token: Uint8Array, callback: AsyncCallback<HuksReturnResult>) : void

分段操作数据,传递认证令牌

finishSession(handle: number, options: HuksOptions, token: Uint8Array, callback: AsyncCallback<HuksReturnResult>) : void

结束密钥会话,传递认证令牌

开发步骤

  1. 生成密钥并指定指纹访问控制和相关属性

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

/*
 * 确定密钥别名和封装密钥属性参数集
 */
let keyAlias = 'dh_key_fingerprint_access';
let properties = new Array();
properties[0] = {
  tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
  value: huks.HuksKeyAlg.HUKS_ALG_SM4,
}
properties[1] = {
  tag: huks.HuksTag.HUKS_TAG_PURPOSE,
  value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
}
properties[2] = {
  tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
  value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
}
properties[3] = {
  tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
  value: huks.HuksCipherMode.HUKS_MODE_CBC,
}
properties[4] = {
  tag: huks.HuksTag.HUKS_TAG_PADDING,
  value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
}
// 指定密钥身份认证的类型:指纹
properties[5] = {
  tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE,
  value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT
}
// 指定密钥安全授权的类型(失效类型):新录入生物特征(指纹)后无效
properties[6] = {
  tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE,
  value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL
}
// 指定挑战值的类型:默认类型
properties[7] = {
  tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE,
  value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL
}
let huksOptions = {
  properties: properties,
  inData: new Uint8Array(new Array())
}

/*
 * 生成密钥
 */
function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
  return new Promise((resolve, reject) => {
    try {
      huks.generateKeyItem(keyAlias, huksOptions, function (error, data) {
        if (error) {
          reject(error);
        } else {
          resolve(data);
        }
      });
    } catch (error) {
      throwObject.isThrow = true;
      throw(error);
    }
  });
}

async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
  console.info(`enter callback generateKeyItem`);
  let throwObject = {isThrow: false};
  try {
    await generateKeyItem(keyAlias, huksOptions, throwObject)
      .then((data) => {
        console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
      })
      .catch(error => {
        if (throwObject.isThrow) {
          throw(error);
        } else {
          console.error(`callback: generateKeyItem failed, code: ${error.code}, msg: ${error.message}`);
        }
      });
  } catch (error) {
    console.error(`callback: generateKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
  }
}

async function TestGenKeyForFingerprintAccessControl() {
  await publicGenKeyFunc(keyAlias, huksOptions);
}
  1. 初始化密钥会话获取挑战值并发起指纹认证获取认证令牌

import huks from '@ohos.security.huks';
import userIAM_userAuth from '@ohos.userIAM.userAuth';

/*
 * 确定密钥别名和封装密钥属性参数集
 */
let srcKeyAlias = 'sm4_key_fingerprint_access';
let handle;
let challenge;
let fingerAuthToken;
let authType = userIAM_userAuth.UserAuthType.FINGERPRINT;
let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1;

/* 集成生成密钥参数集 & 加密参数集 */
let properties = new Array();
properties[0] = {
  tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
  value: huks.HuksKeyAlg.HUKS_ALG_SM4,
}
properties[1] = {
  tag: huks.HuksTag.HUKS_TAG_PURPOSE,
  value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
}
properties[2] = {
  tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
  value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
}
properties[3] = {
  tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
  value: huks.HuksCipherMode.HUKS_MODE_CBC,
}
properties[4] = {
  tag: huks.HuksTag.HUKS_TAG_PADDING,
  value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
}
let huksOptions = {
  properties: properties,
  inData: new Uint8Array(new Array())
}

function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksSessionHandle> {
  return new Promise((resolve, reject) => {
    try {
      huks.initSession(keyAlias, huksOptions, function (error, data) {
        if (error) {
          reject(error);
        } else {
          resolve(data);
        }
      });
    } catch (error) {
      throwObject.isThrow = true;
      throw(error);
    }
  });
}

async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
  console.info(`enter callback doInit`);
  let throwObject = {isThrow: false};
  try {
    await initSession(keyAlias, huksOptions, throwObject)
      .then ((data) => {
        console.info(`callback: doInit success, data = ${JSON.stringify(data)}`);
        handle = data.handle;
        challenge = data.challenge;
      })
      .catch((error) => {
        if (throwObject.isThrow) {
          throw(error);
        } else {
          console.error(`callback: doInit failed, code: ${error.code}, msg: ${error.message}`);
        }
      });
  } catch (error) {
    console.error(`callback: doInit input arg invalid, code: ${error.code}, msg: ${error.message}`);
  }
}

function userIAMAuthFinger(huksChallenge:Uint8Array) {
  // 获取认证对象
  let auth;
  try {
    auth = userIAM_userAuth.getAuthInstance(huksChallenge, authType, authTrustLevel);
    console.log("get auth instance success");
  } catch (error) {
    console.log("get auth instance failed" + error);
  }

  // 订阅认证结果
  try {
    auth.on("result", {
      callback: (result: userIAM_userAuth.AuthResultInfo) => {
        /* 认证成功获取认证令牌 */
        fingerAuthToken = result.token;
      }
    });
    console.log("subscribe authentication event success");
  } catch (error) {
    console.log("subscribe authentication event failed " + error);
  }

  // 开始认证
  try {
    auth.start();
    console.info("authV9 start auth success");
  } catch (error) {
    console.info("authV9 start auth failed, error = " + error);
  }
}

async function testInitAndAuthFinger() {
  /* 初始化密钥会话获取挑战值 */
  await publicInitFunc(srcKeyAlias, huksOptions);
  /* 调用userIAM进行身份认证 */
  userIAMAuthFinger(challenge);
}
  1. 传入认证令牌进行数据操作

/*
 * 以下以SM4 128密钥的Callback操作使用为例
 */
import huks from '@ohos.security.huks';

/*
 * 确定密钥别名和封装密钥属性参数集
 */
let srcKeyAlias = 'sm4_key_fingerprint_access';
let IV = '1234567890123456';
let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string';
let handle;
let fingerAuthToken;
let updateResult = new Array();
let finishOutData;

/* 集成生成密钥参数集 & 加密参数集 */
let propertiesEncrypt = new Array();
propertiesEncrypt[0] = {
  tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
  value: huks.HuksKeyAlg.HUKS_ALG_SM4,
}
propertiesEncrypt[1] = {
  tag: huks.HuksTag.HUKS_TAG_PURPOSE,
  value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT,
}
propertiesEncrypt[2] = {
  tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
  value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
}
propertiesEncrypt[3] = {
  tag: huks.HuksTag.HUKS_TAG_PADDING,
  value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
}
propertiesEncrypt[4] = {
  tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
  value: huks.HuksCipherMode.HUKS_MODE_CBC,
}
propertiesEncrypt[5] = {
  tag: huks.HuksTag.HUKS_TAG_IV,
  value: StringToUint8Array(IV),
}
let encryptOptions = {
  properties: propertiesEncrypt,
  inData: new Uint8Array(new Array())
}

function StringToUint8Array(str) {
  let arr = [];
  for (let i = 0, j = str.length; i < j; ++i) {
    arr.push(str.charCodeAt(i));
  }
  return new Uint8Array(arr);
}

function updateSession(handle:number, huksOptions:huks.HuksOptions, token:Uint8Array, throwObject) : Promise<huks.HuksReturnResult> {
  return new Promise((resolve, reject) => {
    try {
      huks.updateSession(handle, huksOptions, token, function (error, data) {
        if (error) {
          reject(error);
        } else {
          resolve(data);
        }
      });
    } catch (error) {
      throwObject.isThrow = true;
      throw(error);
    }
  });
}

async function publicUpdateFunc(handle:number, token:Uint8Array, huksOptions:huks.HuksOptions) {
  console.info(`enter callback doUpdate`);
  let throwObject = {isThrow: false};
  try {
    await updateSession(handle, huksOptions, token, throwObject)
      .then ((data) => {
        console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`);
      })
      .catch(error => {
        if (throwObject.isThrow) {
          throw(error);
        } else {
          console.error(`callback: doUpdate failed, code: ${error.code}, msg: ${error.message}`);
        }
      });
  } catch (error) {
    console.error(`callback: doUpdate input arg invalid, code: ${error.code}, msg: ${error.message}`);
  }
}

function finishSession(handle:number, huksOptions:huks.HuksOptions, token:Uint8Array, throwObject) : Promise<huks.HuksReturnResult> {
  return new Promise((resolve, reject) => {
    try {
      huks.finishSession(handle, huksOptions, token, function (error, data) {
        if (error) {
          reject(error);
        } else {
          resolve(data);
        }
      });
    } catch (error) {
      throwObject.isThrow = true;
      throw(error);
    }
  });
}

async function publicFinishFunc(handle:number, token:Uint8Array, huksOptions:huks.HuksOptions) {
  console.info(`enter callback doFinish`);
  let throwObject = {isThrow: false};
  try {
    await finishSession(handle, huksOptions, token, throwObject)
      .then ((data) => {
        finishOutData = data.outData;
        console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`);
      })
      .catch(error => {
        if (throwObject.isThrow) {
          throw(error);
        } else {
          console.error(`callback: doFinish failed, code: ${error.code}, msg: ${error.message}`);
        }
      });
  } catch (error) {
    console.error(`callback: doFinish input arg invalid, code: ${error.code}, msg: ${error.message}`);
  }
}

async function testSm4Cipher() {
  encryptOptions.inData = StringToUint8Array(cipherInData);
  /* 传入认证令牌 */
  await publicUpdateFunc(handle, fingerAuthToken, encryptOptions);
  encryptUpdateResult = updateResult;

  encryptOptions.inData = new Uint8Array(new Array());
  /* 传入认证令牌 */
  await publicFinishFunc(handle, fingerAuthToken, encryptOptions);
  if (finishOutData === cipherInData) {
    console.info('test finish encrypt err ');
  } else {
    console.info('test finish encrypt success');
  }
}

常见问题

  1. Cannot find name 'huks'.
    不能找到huks,使用了接口函数但没导入security.huks.d.ts,添加import huks from '@ohos.security.huks';即可。
  2. Property 'finishSession' does not exist on type 'typeof huks'. Did you mean 'finish'?
    不能在huks库中找到finishSession,finishSession是API9版本的,请更新SDK版本或替换新版本的security.huks.d.ts文件。

通用密钥库密码算法规格

支持的算法类型及参数组合

导入\生成密钥规格

算法

API级别

支持的密钥长度

AES

8+

128、192、256

RSA

8+

2048、3072、4096

HMAC

8+

8-4096(含),必须是8的倍数

ECC

8+

256、384、521

ED25519

8+

256

X25519

8+

256

SM2

9+

256

SM3

9+

256

SM4

9+

128

加密解密

算法

API级别

备注

AES/CBC/NoPadding

AES/CTR/NoPadding

AES/GCM/NoPadding

AES/CBC/PKCS7

8+

1. CBC\ECB\CTR模式IV参数必选

2. GCM模式下Nonce、AAD、AEAD参数必选

RSA/ECB/NoPadding

RSA/ECB/PKCS1_V1_5

RSA/ECB/OAEP

8+

-

SM4/CTR/NoPadding

SM4/CBC/NoPadding

9+

-

签名验签

算法

API级别

备注

RSA/SHA256/PKCS1_V1_5

RSA/SHA384/PKCS1_V1_5

RSA/SHA512/PKCS1_V1_5

RSA/SHA256/PSS

RSA/SHA384/PSS

8+

-

ECC/SHA256

ECC/SHA384

ECC/SHA512

8+

-

ED25519

8+

-

SM2/SM3

9+

-

密钥协商

算法

API级别

备注

ECDH

8+

协商密钥类型为ECC类型密钥

X25519

8+

-

密钥派生

算法

API级别

派生密钥及长度

备注

HKDF/SHA256

HKDF/SHA384

HKDF/SHA512

8+

算法:AES、HMAC、SM4 长度:256、384、512

派生出的密钥可以存储到HUKS或者直接返回明文

PBKDF2/SHA256

PBKDF2/SHA384

PBKDF2/SHA512

8+

算法:AES、HMAC、SM4 长度:256、384、512

派生出的密钥可以存储到HUKS或者直接返回明文

密钥材料格式

针对不同密码算法的密钥对、公钥、私钥,HUKS定义了一套密钥材料格式。

密钥对材料

密钥对材料 = 密钥对材料Header + 密钥对材料原文

以RSA密钥为例,应用需要申请一个Uint8Array,按照RSA密钥对材料内存格式,将各个变量赋值到对应的位置:

图4 RSA密钥材料内存结构

HarmonyOS Developer 通用密钥库开发指导-鸿蒙开发者社区

let rsa2048KeyPairMaterial = new Uint8Array([
    0x01, 0x00, 0x00, 0x00, // 密钥算法:huks.HuksKeyAlg.HUKS_ALG_RSA = 1
    0x00, 0x08, 0x00, 0x00, // 密钥大小(比特):2048
    0x00, 0x01, 0x00, 0x00, // 模数n长度(字节):256
    0x03, 0x00, 0x00, 0x00, // 公钥指数e长度(字节):3
    0x00, 0x01, 0x00, 0x00, // 私钥指数d长度(字节):256
    // 模数n
    0xc5, 0x35, 0x62, 0x48, 0xc4, 0x92, 0x87, 0x73, 0x0d, 0x42, 0x96, 0xfc, 0x7b, 0x11, 0x05, 0x06,
    0x0f, 0x8d, 0x66, 0xc1, 0x0e, 0xad, 0x37, 0x44, 0x92, 0x95, 0x2f, 0x6a, 0x55, 0xba, 0xec, 0x1d,
    0x54, 0x62, 0x0a, 0x4b, 0xd3, 0xc7, 0x05, 0xe4, 0x07, 0x40, 0xd9, 0xb7, 0xc2, 0x12, 0xcb, 0x9a,
    0x90, 0xad, 0xe3, 0x24, 0xe8, 0x5e, 0xa6, 0xf8, 0xd0, 0x6e, 0xbc, 0xd1, 0x69, 0x7f, 0x6b, 0xe4,
    0x2b, 0x4e, 0x1a, 0x65, 0xbb, 0x73, 0x88, 0x6b, 0x7c, 0xaf, 0x7e, 0xd0, 0x47, 0x26, 0xeb, 0xa5,
    0xbe, 0xd6, 0xe8, 0xee, 0x9c, 0xa5, 0x66, 0xa5, 0xc9, 0xd3, 0x25, 0x13, 0xc4, 0x0e, 0x6c, 0xab,
    0x50, 0xb6, 0x50, 0xc9, 0xce, 0x8f, 0x0a, 0x0b, 0xc6, 0x28, 0x69, 0xe9, 0x83, 0x69, 0xde, 0x42,
    0x56, 0x79, 0x7f, 0xde, 0x86, 0x24, 0xca, 0xfc, 0xaa, 0xc0, 0xf3, 0xf3, 0x7f, 0x92, 0x8e, 0x8a,
    0x12, 0x52, 0xfe, 0x50, 0xb1, 0x5e, 0x8c, 0x01, 0xce, 0xfc, 0x7e, 0xf2, 0x4f, 0x5f, 0x03, 0xfe,
    0xa7, 0xcd, 0xa1, 0xfc, 0x94, 0x52, 0x00, 0x8b, 0x9b, 0x7f, 0x09, 0xab, 0xa8, 0xa4, 0xf5, 0xb4,
    0xa5, 0xaa, 0xfc, 0x72, 0xeb, 0x17, 0x40, 0xa9, 0xee, 0xbe, 0x8f, 0xc2, 0xd1, 0x80, 0xc2, 0x0d,
    0x44, 0xa9, 0x59, 0x44, 0x59, 0x81, 0x3b, 0x5d, 0x4a, 0xde, 0xfb, 0xae, 0x24, 0xfc, 0xa3, 0xd9,
    0xbc, 0x57, 0x55, 0xc2, 0x26, 0xbc, 0x19, 0xa7, 0x9a, 0xc5, 0x59, 0xa3, 0xee, 0x5a, 0xef, 0x41,
    0x80, 0x7d, 0xf8, 0x5e, 0xc1, 0x1d, 0x32, 0x38, 0x41, 0x5b, 0xb6, 0x92, 0xb8, 0xb7, 0x03, 0x0d,
    0x3e, 0x59, 0x0f, 0x1c, 0xb3, 0xe1, 0x2a, 0x95, 0x1a, 0x3b, 0x50, 0x4f, 0xc4, 0x1d, 0xcf, 0x73,
    0x7c, 0x14, 0xca, 0xe3, 0x0b, 0xa7, 0xc7, 0x1a, 0x41, 0x4a, 0xee, 0xbe, 0x1f, 0x43, 0xdd, 0xf9,
    // 公钥指数e
    0x01, 0x00, 0x01,
    // 私钥指数d
    0x88, 0x4b, 0x82, 0xe7, 0xe3, 0xe3, 0x99, 0x75, 0x6c, 0x9e, 0xaf, 0x17, 0x44, 0x3e, 0xd9, 0x07,
    0xfd, 0x4b, 0xae, 0xce, 0x92, 0xc4, 0x28, 0x44, 0x5e, 0x42, 0x79, 0x08, 0xb6, 0xc3, 0x7f, 0x58,
    0x2d, 0xef, 0xac, 0x4a, 0x07, 0xcd, 0xaf, 0x46, 0x8f, 0xb4, 0xc4, 0x43, 0xf9, 0xff, 0x5f, 0x74,
    0x2d, 0xb5, 0xe0, 0x1c, 0xab, 0xf4, 0x6e, 0xd5, 0xdb, 0xc8, 0x0c, 0xfb, 0x76, 0x3c, 0x38, 0x66,
    0xf3, 0x7f, 0x01, 0x43, 0x7a, 0x30, 0x39, 0x02, 0x80, 0xa4, 0x11, 0xb3, 0x04, 0xd9, 0xe3, 0x57,
    0x23, 0xf4, 0x07, 0xfc, 0x91, 0x8a, 0xc6, 0xcc, 0xa2, 0x16, 0x29, 0xb3, 0xe5, 0x76, 0x4a, 0xa8,
    0x84, 0x19, 0xdc, 0xef, 0xfc, 0xb0, 0x63, 0x33, 0x0b, 0xfa, 0xf6, 0x68, 0x0b, 0x08, 0xea, 0x31,
    0x52, 0xee, 0x99, 0xef, 0x43, 0x2a, 0xbe, 0x97, 0xad, 0xb3, 0xb9, 0x66, 0x7a, 0xae, 0xe1, 0x8f,
    0x57, 0x86, 0xe5, 0xfe, 0x14, 0x3c, 0x81, 0xd0, 0x64, 0xf8, 0x86, 0x1a, 0x0b, 0x40, 0x58, 0xc9,
    0x33, 0x49, 0xb8, 0x99, 0xc6, 0x2e, 0x94, 0x70, 0xee, 0x09, 0x88, 0xe1, 0x5c, 0x4e, 0x6c, 0x22,
    0x72, 0xa7, 0x2a, 0x21, 0xdd, 0xd7, 0x1d, 0xfc, 0x63, 0x15, 0x0b, 0xde, 0x06, 0x9c, 0xf3, 0x28,
    0xf3, 0xac, 0x4a, 0xa8, 0xb5, 0x50, 0xca, 0x9b, 0xcc, 0x0a, 0x04, 0xfe, 0x3f, 0x98, 0x68, 0x81,
    0xac, 0x24, 0x53, 0xea, 0x1f, 0x1c, 0x6e, 0x5e, 0xca, 0xe8, 0x31, 0x0d, 0x08, 0x12, 0xf3, 0x26,
    0xf8, 0x5e, 0xeb, 0x10, 0x27, 0xae, 0xaa, 0xc3, 0xad, 0x6c, 0xc1, 0x89, 0xdb, 0x7d, 0x5a, 0x12,
    0x55, 0xad, 0x11, 0x19, 0xa1, 0xa9, 0x8f, 0x0b, 0x6d, 0x78, 0x8d, 0x1c, 0xdf, 0xe5, 0x63, 0x82,
    0x0b, 0x7d, 0x23, 0x04, 0xb4, 0x75, 0x8c, 0xed, 0x77, 0xfc, 0x1a, 0x85, 0x29, 0x11, 0xe0, 0x61,
    ]);

其中,密钥算法的值取自枚举类​​HuksKeyAlg​​。

  • RSA密钥对材料格式:

密钥算法

密钥大小

模数n长度Ln

公钥指数e长度Le

私钥指数d长度Ld

n

e

d

4字节

4字节

4字节

4字节

4字节

Ln字节

Le字节

Ld字节

  • ECC密钥对材料格式:

密钥算法

密钥大小

坐标x长度Lx

坐标y长度Ly

坐标z长度Lz

x

y

z

4字节

4字节

4字节

4字节

4字节

Lx字节

Ly字节

Lz字节

  • DSA密钥对材料格式:

密钥算法

密钥大小

私钥x长度Lx

公钥y长度Ly

素数p长度Lp

素因子q长度Lq

g长度Lg

x

y

p

q

g

4字节

4字节

4字节

4字节

4字节

4字节

4字节

Lx字节

Ly字节

Lp字节

Lq字节

Lg字节

  • DH密钥对材料格式:

密钥算法

密钥大小

公钥pk长度Lpk

私钥sk长度Lsk

保留字段

pk

sk

4字节

4字节

4字节

4字节

4字节

Lpk字节

Lsk字节

  • Curve25519密钥对材料格式:

密钥算法

密钥大小

公钥pk长度Lpk

私钥sk长度Lsk

保留字段

pk

sk

4字节

4字节

4字节

4字节

4字节

Lpk字节

Lsk字节

公钥材料

在公钥导出/导入时,密钥材料采用标准的X.509规范的DER格式封装。

如下是一个DER编码的ECC公钥:

let eccP256PubKey = new Uint8Array([
  0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
  0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xc0, 0xfe, 0x1c, 0x67, 0xde,
  0x86, 0x0e, 0xfb, 0xaf, 0xb5, 0x85, 0x52, 0xb4, 0x0e, 0x1f, 0x6c, 0x6c, 0xaa, 0xc5, 0xd9, 0xd2,
  0x4d, 0xb0, 0x8a, 0x72, 0x24, 0xa1, 0x99, 0xaf, 0xfc, 0x3e, 0x55, 0x5a, 0xac, 0x99, 0x3d, 0xe8,
  0x34, 0x72, 0xb9, 0x47, 0x9c, 0xa6, 0xd8, 0xfb, 0x00, 0xa0, 0x1f, 0x9f, 0x7a, 0x41, 0xe5, 0x44,
  0x3e, 0xb2, 0x76, 0x08, 0xa2, 0xbd, 0xe9, 0x41, 0xd5, 0x2b, 0x9e]);
私钥材料

复用密钥对的材料格式,私钥材料的封装是把密钥对材料Header中的公钥部分的长度字段置0,同时密钥对材料原文部分拼接私钥材料即可。

私钥材料 = 密钥对材料Header + 私钥材料原文

以RSA私钥材料为例:

HarmonyOS Developer 通用密钥库开发指导-鸿蒙开发者社区

let rsa2048PrivateKeyMaterial = new Uint8Array([
    0x01, 0x00, 0x00, 0x00, // 密钥算法:huks.HuksKeyAlg.HUKS_ALG_RSA = 1
    0x00, 0x08, 0x00, 0x00, // 密钥大小(比特):2048
    0x00, 0x01, 0x00, 0x00, // 模数n长度(字节):256
    0x00, 0x00, 0x00, 0x00, // 公钥指数e长度(字节):0
    0x00, 0x01, 0x00, 0x00, // 私钥指数d长度(字节):256
    // 模数n
    0xc5, 0x35, 0x62, 0x48, 0xc4, 0x92, 0x87, 0x73, 0x0d, 0x42, 0x96, 0xfc, 0x7b, 0x11, 0x05, 0x06,
    0x0f, 0x8d, 0x66, 0xc1, 0x0e, 0xad, 0x37, 0x44, 0x92, 0x95, 0x2f, 0x6a, 0x55, 0xba, 0xec, 0x1d,
    0x54, 0x62, 0x0a, 0x4b, 0xd3, 0xc7, 0x05, 0xe4, 0x07, 0x40, 0xd9, 0xb7, 0xc2, 0x12, 0xcb, 0x9a,
    0x90, 0xad, 0xe3, 0x24, 0xe8, 0x5e, 0xa6, 0xf8, 0xd0, 0x6e, 0xbc, 0xd1, 0x69, 0x7f, 0x6b, 0xe4,
    0x2b, 0x4e, 0x1a, 0x65, 0xbb, 0x73, 0x88, 0x6b, 0x7c, 0xaf, 0x7e, 0xd0, 0x47, 0x26, 0xeb, 0xa5,
    0xbe, 0xd6, 0xe8, 0xee, 0x9c, 0xa5, 0x66, 0xa5, 0xc9, 0xd3, 0x25, 0x13, 0xc4, 0x0e, 0x6c, 0xab,
    0x50, 0xb6, 0x50, 0xc9, 0xce, 0x8f, 0x0a, 0x0b, 0xc6, 0x28, 0x69, 0xe9, 0x83, 0x69, 0xde, 0x42,
    0x56, 0x79, 0x7f, 0xde, 0x86, 0x24, 0xca, 0xfc, 0xaa, 0xc0, 0xf3, 0xf3, 0x7f, 0x92, 0x8e, 0x8a,
    0x12, 0x52, 0xfe, 0x50, 0xb1, 0x5e, 0x8c, 0x01, 0xce, 0xfc, 0x7e, 0xf2, 0x4f, 0x5f, 0x03, 0xfe,
    0xa7, 0xcd, 0xa1, 0xfc, 0x94, 0x52, 0x00, 0x8b, 0x9b, 0x7f, 0x09, 0xab, 0xa8, 0xa4, 0xf5, 0xb4,
    0xa5, 0xaa, 0xfc, 0x72, 0xeb, 0x17, 0x40, 0xa9, 0xee, 0xbe, 0x8f, 0xc2, 0xd1, 0x80, 0xc2, 0x0d,
    0x44, 0xa9, 0x59, 0x44, 0x59, 0x81, 0x3b, 0x5d, 0x4a, 0xde, 0xfb, 0xae, 0x24, 0xfc, 0xa3, 0xd9,
    0xbc, 0x57, 0x55, 0xc2, 0x26, 0xbc, 0x19, 0xa7, 0x9a, 0xc5, 0x59, 0xa3, 0xee, 0x5a, 0xef, 0x41,
    0x80, 0x7d, 0xf8, 0x5e, 0xc1, 0x1d, 0x32, 0x38, 0x41, 0x5b, 0xb6, 0x92, 0xb8, 0xb7, 0x03, 0x0d,
    0x3e, 0x59, 0x0f, 0x1c, 0xb3, 0xe1, 0x2a, 0x95, 0x1a, 0x3b, 0x50, 0x4f, 0xc4, 0x1d, 0xcf, 0x73,
    0x7c, 0x14, 0xca, 0xe3, 0x0b, 0xa7, 0xc7, 0x1a, 0x41, 0x4a, 0xee, 0xbe, 0x1f, 0x43, 0xdd, 0xf9,
    // 私钥指数d
    0x88, 0x4b, 0x82, 0xe7, 0xe3, 0xe3, 0x99, 0x75, 0x6c, 0x9e, 0xaf, 0x17, 0x44, 0x3e, 0xd9, 0x07,
    0xfd, 0x4b, 0xae, 0xce, 0x92, 0xc4, 0x28, 0x44, 0x5e, 0x42, 0x79, 0x08, 0xb6, 0xc3, 0x7f, 0x58,
    0x2d, 0xef, 0xac, 0x4a, 0x07, 0xcd, 0xaf, 0x46, 0x8f, 0xb4, 0xc4, 0x43, 0xf9, 0xff, 0x5f, 0x74,
    0x2d, 0xb5, 0xe0, 0x1c, 0xab, 0xf4, 0x6e, 0xd5, 0xdb, 0xc8, 0x0c, 0xfb, 0x76, 0x3c, 0x38, 0x66,
    0xf3, 0x7f, 0x01, 0x43, 0x7a, 0x30, 0x39, 0x02, 0x80, 0xa4, 0x11, 0xb3, 0x04, 0xd9, 0xe3, 0x57,
    0x23, 0xf4, 0x07, 0xfc, 0x91, 0x8a, 0xc6, 0xcc, 0xa2, 0x16, 0x29, 0xb3, 0xe5, 0x76, 0x4a, 0xa8,
    0x84, 0x19, 0xdc, 0xef, 0xfc, 0xb0, 0x63, 0x33, 0x0b, 0xfa, 0xf6, 0x68, 0x0b, 0x08, 0xea, 0x31,
    0x52, 0xee, 0x99, 0xef, 0x43, 0x2a, 0xbe, 0x97, 0xad, 0xb3, 0xb9, 0x66, 0x7a, 0xae, 0xe1, 0x8f,
    0x57, 0x86, 0xe5, 0xfe, 0x14, 0x3c, 0x81, 0xd0, 0x64, 0xf8, 0x86, 0x1a, 0x0b, 0x40, 0x58, 0xc9,
    0x33, 0x49, 0xb8, 0x99, 0xc6, 0x2e, 0x94, 0x70, 0xee, 0x09, 0x88, 0xe1, 0x5c, 0x4e, 0x6c, 0x22,
    0x72, 0xa7, 0x2a, 0x21, 0xdd, 0xd7, 0x1d, 0xfc, 0x63, 0x15, 0x0b, 0xde, 0x06, 0x9c, 0xf3, 0x28,
    0xf3, 0xac, 0x4a, 0xa8, 0xb5, 0x50, 0xca, 0x9b, 0xcc, 0x0a, 0x04, 0xfe, 0x3f, 0x98, 0x68, 0x81,
    0xac, 0x24, 0x53, 0xea, 0x1f, 0x1c, 0x6e, 0x5e, 0xca, 0xe8, 0x31, 0x0d, 0x08, 0x12, 0xf3, 0x26,
    0xf8, 0x5e, 0xeb, 0x10, 0x27, 0xae, 0xaa, 0xc3, 0xad, 0x6c, 0xc1, 0x89, 0xdb, 0x7d, 0x5a, 0x12,
    0x55, 0xad, 0x11, 0x19, 0xa1, 0xa9, 0x8f, 0x0b, 0x6d, 0x78, 0x8d, 0x1c, 0xdf, 0xe5, 0x63, 0x82,
    0x0b, 0x7d, 0x23, 0x04, 0xb4, 0x75, 0x8c, 0xed, 0x77, 0xfc, 0x1a, 0x85, 0x29, 0x11, 0xe0, 0x61,
    ]);




文章转载自:​​https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/huks-appendix-0000001446834210-V3?catalogVersion=V3​

标签
已于2023-3-31 15:25:33修改
收藏
回复
举报
回复