文档管理中心
您当前浏览的HarmonyOS 5.0.0(API 12)文档归档不再维护,推荐您使用最新版本。详细请参考文档维护策略变更

应用端开发

查询应用公私钥对是否存在

查询用于设备真实性证明的应用公私钥对是否存在,如果应用公私钥对已存在,则不需要重复创建应用公私钥对。

样例代码:

收起
自动换行
深色代码主题
复制
  1. import { huks } from '@kit.UniversalKeystoreKit';
  2. let keyAlias = 'serviceKey'; //业务密钥别名
  3. let isKeyExist: Boolean;
  4. let huksOptions: huks.HuksOptions = {
  5. properties: []
  6. }
  7. try {
  8. huks.hasKeyItem(keyAlias, huksOptions, (error, data) => {
  9. if (error) {
  10. console.error(`callback: hasKeyItem failed, ` + JSON.stringify(error));
  11. } else {
  12. if (data !== null && data.valueOf() !== null) {
  13. isKeyExist = data.valueOf();
  14. console.info(`callback: hasKeyItem success, isKeyExist = ${isKeyExist}`);
  15. }
  16. }
  17. });
  18. } catch (error) {
  19. console.error(`callback: hasKeyItem input arg invalid, ` + JSON.stringify(error));
  20. }

创建应用公私钥对

创建一个用于证明设备真实性和应用身份的非对称算法密钥对,称为应用公私钥对(包含应用公钥和应用私钥),比如RSA、EC算法的密钥对。通过Universal Keystore Kit场景的密钥对基于硬件的安全环境进行生成和安全存储。

安全建议:对于有用户登录的应用场景,为了提高安全性,建议为终端设备中登录的每个用户生成不同的密钥对,并在应用服务器绑定用户与应用公钥之间的关系。

样例代码:

收起
自动换行
深色代码主题
复制
  1. import { huks } from '@kit.UniversalKeystoreKit';
  2. import { BusinessError } from '@kit.BasicServicesKit';
  3. let keyAlias = 'serviceKey'; //业务密钥别名
  4. function GetGenerateProperties() {
  5. let properties: Array<huks.HuksParam> = new Array();
  6. let index = 0;
  7. properties[index++] = {
  8. tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
  9. value: huks.HuksKeyAlg.HUKS_ALG_ECC
  10. };
  11. properties[index++] = {
  12. tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
  13. value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
  14. };
  15. properties[index++] = {
  16. tag: huks.HuksTag.HUKS_TAG_PURPOSE,
  17. value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN |
  18. huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY
  19. };
  20. properties[index++] = {
  21. tag: huks.HuksTag.HUKS_TAG_DIGEST,
  22. value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256
  23. }
  24. return properties;
  25. }
  26. async function GenerateKey(keyAlias: string) {
  27. let genProperties = GetGenerateProperties();
  28. let options: huks.HuksOptions = {
  29. properties: genProperties
  30. }
  31. await huks.generateKeyItem(keyAlias, options)
  32. .then(() => {
  33. console.info(`promise: generate Key success.`);
  34. }).catch((err: BusinessError) => {
  35. console.error(`promise: generate Key failed, error: ` + err.message);
  36. })
  37. }

对应用公钥进行证明

应用调用Universal Keystore Kit接口对生成的应用公钥和调用的应用身份进行证明,Universal Keystore Kit会使用基于硬件的设备证书对应用公钥进行证明,证明公钥来自真实的设备。

Universal Keystore Kit返回密钥证明证书链,证书链采用X509标准格式。

安全建议:为了在发送密钥证明证书链给应用服务器时能够防重放攻击,建议应用先从应用服务器获取一次性的挑战值Challenge。应用服务器采用安全随机数生成挑战值Challenge,并缓存到服务器中

样例代码:

收起
自动换行
深色代码主题
复制
  1. import { huks } from '@kit.UniversalKeystoreKit';
  2. class HuksProperties {
  3. tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
  4. value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyDigest |
  5. huks.HuksKeyStorageType | huks.HuksKeyPadding | huks.HuksKeyGenerateType |
  6. huks.HuksCipherMode | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_ECC;
  7. }
  8. let challenge = stringToUint8Array('challenge_data'); //从服务器获取的挑战字Challenge
  9. let keyAlias = 'serviceKey'; //业务密钥别名
  10. function stringToUint8Array(str: string): Uint8Array {
  11. let arr: number[] = [];
  12. for (let i = 0, j = str.length; i < j; ++i) {
  13. arr.push(str.charCodeAt(i));
  14. }
  15. let tmpUint8Array = new Uint8Array(arr);
  16. return tmpUint8Array;
  17. }
  18. async function anonAttestKey(): Promise<void> {
  19. let aliasString = keyAlias;
  20. let properties: HuksProperties[] = [
  21. {
  22. tag: huks.HuksTag.HUKS_TAG_ATTESTATION_CHALLENGE,
  23. value: challenge
  24. }
  25. ];
  26. let options: huks.HuksOptions = {
  27. properties: properties
  28. };
  29. try {
  30. let data = await huks.anonAttestKeyItem(aliasString, options);
  31. //todo:把证书链信息(data变量)发送到云侧的服务器。如下示例代码把证书链打印到日志中,供调测使用,商用代码不需要打印。
  32. console.info(`anonAttestKeyItem success`);
  33. data.certChains?.forEach(cert => {
  34. console.info(cert);
  35. });
  36. } catch (error) {
  37. console.error(`promise: anonAttestKeyItem fail`);
  38. }
  39. }

使用应用私钥对业务请求进行签名

在密钥证明流程处理成功后,应用在进行一些安全敏感的端云业务时,可以使用已证明的密钥对业务请求进行安全保护。

应用可以调用Universal Keystore Kit接口使用应用私钥对业务请求数据(如HTTP请求的Body)进行签名,然后把签名数据添加到请求消息中(如HTTP的Header字段)。为了方便应用服务器查找应用公钥用于验签,可以在业务请求中携带应用公钥的密钥ID(如:通过对应用公钥计算Hash)。

安全建议:为了在发送业务请求时能够防重放攻击,建议应用先从应用服务器获取一次性的挑战值Challenge。应用服务器采用安全随机数生成挑战值Challenge,并缓存到服务器中

样例代码:

收起
自动换行
深色代码主题
复制
  1. import { huks } from '@kit.UniversalKeystoreKit';
  2. import { BusinessError } from '@kit.BasicServicesKit';
  3. import { util } from '@kit.ArkTS';
  4. let keyAlias = 'serviceKey'; //业务密钥别名
  5. let handle: number;
  6. let plaintext = '123456'; //待签名的明文数据,建议包含服务器端返回的Challenge
  7. let signature: Uint8Array; //存储签名结果数据的变量
  8. function StringToUint8Array(str: String) {
  9. let arr: number[] = new Array();
  10. for (let i = 0, j = str.length; i < j; ++i) {
  11. arr.push(str.charCodeAt(i));
  12. }
  13. return new Uint8Array(arr);
  14. }
  15. function GetSignProperties() {
  16. let properties: Array<huks.HuksParam> = new Array();
  17. let index = 0;
  18. properties[index++] = {
  19. tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
  20. value: huks.HuksKeyAlg.HUKS_ALG_ECC
  21. };
  22. properties[index++] = {
  23. tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
  24. value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
  25. };
  26. properties[index++] = {
  27. tag: huks.HuksTag.HUKS_TAG_PURPOSE,
  28. value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN
  29. };
  30. properties[index++] = {
  31. tag: huks.HuksTag.HUKS_TAG_DIGEST,
  32. value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256
  33. }
  34. return properties;
  35. }
  36. async function Sign(keyAlias: string, plaintext: string) {
  37. let signProperties = GetSignProperties();
  38. let options: huks.HuksOptions = {
  39. properties: signProperties,
  40. inData: StringToUint8Array(plaintext)
  41. }
  42. await huks.initSession(keyAlias, options)
  43. .then((data) => {
  44. handle = data.handle;
  45. }).catch((err: BusinessError) => {
  46. console.error(`promise: init sign failed, error: ` + err.message);
  47. })
  48. await huks.finishSession(handle, options)
  49. .then((data) => {
  50. signature = data.outData as Uint8Array;
  51. let base64 = new util.Base64Helper();
  52. let signatureBase64 = base64.encodeToStringSync(signature);
  53. //todo:把签名结果的Base64编码(signatureBase64变量)发送到云侧的服务器。如下示例代码把签名结果打印到日志中,供调测使用,商用代码不需要打印。
  54. console.info(`sign success, result:` + signatureBase64);
  55. }).catch((err: BusinessError) => {
  56. console.error(`promise: sign failed, error: ` + err.message);
  57. })
  58. }
在 指南 中进行搜索
请输入您想要搜索的关键词