目录

Application Development

API Description

Universal Keystore Kit provides the APIs. For details about the related operations, see:

Checking the Public/Private Key Pair of an Application

Check whether the public/private key pair of an application exists. If it already exists, you do not need to create it again.

Example

import { huks } from '@kit.UniversalKeystoreKit';

let keyAlias = 'serviceKey_user01';  // Service key alias.
let isKeyExist: Boolean;
 
let huksOptions: huks.HuksOptions = {
  properties: []
}
try {
  huks.hasKeyItem(keyAlias, huksOptions, (error, data) => {
    if (error) {
      console.error(`callback: hasKeyItem failed, ` + JSON.stringify(error));
    } else {
      if (data !== null && data.valueOf() !== null) {
        isKeyExist = data.valueOf();
        console.info(`callback: hasKeyItem success, isKeyExist = ${isKeyExist}`);
      }
    }
  });
} catch (error) {
  console.error(`callback: hasKeyItem input arg invalid, ` + JSON.stringify(error));
}

Creating a Public/Private Key Pair for an Application

Create an asymmetric key pair (including a public key and a private key), for example, an RSA or ECC key pair, for application request attestation. The key pairs are generated and stored in a hardware-backed secure environment using Universal Keystore Kit.

Implementation suggestion: In scenarios such as password-free login and payment, generate a unique key pair for each login user in the application.

Example

import { huks } from '@kit.UniversalKeystoreKit';
import { BusinessError } from '@kit.BasicServicesKit';

let keyAlias = 'serviceKey_user01'; // Service key alias.

function GetGenerateProperties() {
  let properties: Array<huks.HuksParam> = new Array();
  let index = 0;
  properties[index++] = {
    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
    value: huks.HuksKeyAlg.HUKS_ALG_ECC
  };
  properties[index++] = {
    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
  };
  properties[index++] = {
    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN |
    huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY
  };
  properties[index++] = {
    tag: huks.HuksTag.HUKS_TAG_DIGEST,
    value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256
  }
  return properties;
}

async function GenerateKey(keyAlias: string) {
  let genProperties = GetGenerateProperties();
  let options: huks.HuksOptions = {
    properties: genProperties
  }
  await huks.generateKeyItem(keyAlias, options)
    .then(() => {
      console.info(`promise: generate Key success.`);
    }).catch((err: BusinessError) => {
      console.error(`promise: generate Key failed, error: ` + err.message);
    })
}

Attesting the Application Public Key and Application ID

The application calls the offline key attestation API (recommended) or online key attestation API (unrecommended) of Universal Keystore Kit to attest the generated application public key and the identity of the called application. Universal Keystore Kit returns the key attestation certificate chain to the application. The certificate chain is in X.509 standard format. The certificate chain returned by the online key attestation API contains three certificates, and the certificate chain returned by the offline key attestation API contains four certificates.

Security suggestion: To prevent replay attacks when the key attestation certificate chain is sent to the application server, you are advised to obtain a one-time challenge from the application server and pass it when calling the key attestation API. The application server uses a random number to generate a challenge and caches it to the server.

Example

import { huks } from '@kit.UniversalKeystoreKit';
import { deviceInfo } from '@kit.BasicServicesKit';

class HuksProperties {
  tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
  value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyDigest |
    huks.HuksKeyStorageType | huks.HuksKeyPadding | huks.HuksKeyGenerateType |
    huks.HuksCipherMode | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_ECC;
}

let challenge = stringToUint8Array('challenge_data'); // Challenge obtained from the server.
let keyAlias = 'serviceKey_user01'; // Service key alias.

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

async function anonAttestKey(): Promise<void> {
  let aliasString = keyAlias;

  let properties: HuksProperties[] = [
    {
      tag: huks.HuksTag.HUKS_TAG_ATTESTATION_CHALLENGE,
      value: challenge
    }
  ];

  let options: huks.HuksOptions = {
    properties: properties
  };

  let g_secInfo :Uint8Array = stringToUint8Array("hi_security_level_info");
  let g_challenge : Uint8Array = stringToUint8Array("hi_challenge_data");
  let g_version : Uint8Array = stringToUint8Array("hi_os_version_data");
  let g_keyAlias : Uint8Array = stringToUint8Array("testKey");

  let gCommonParam: Array<huks.HuksParam> = [
    { tag : huks.HuksTag.HUKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO, value : g_secInfo },
    { tag : huks.HuksTag.HUKS_TAG_ATTESTATION_CHALLENGE, value : g_challenge },
    { tag : huks.HuksTag.HUKS_TAG_ATTESTATION_ID_VERSION_INFO, value : g_version },
    { tag : huks.HuksTag.HUKS_TAG_ATTESTATION_ID_ALIAS, value : g_keyAlias },
  ];

  try {
    let sdkApiVersionInfo: number = deviceInfo.sdkApiVersion;
    if (sdkApiVersionInfo<26) {
      let data = await huks.anonAttestKeyItem(aliasString, options);
      console.info(`anonAttestKeyItem success`);
      data.certChains?.forEach(cert => {
          console.info(cert);
      });
    } else {
      let data = await huks.anonAttestKeyItemOffline(aliasString, gCommonParam);
      // TODO: Send the certificate chain information (variable data) to the cloud server. The following sample code logs the certificate chain for debugging. Commercial code does not need to log the certificate chain.
      console.info(`anonAttestKeyItem success`);
      data.certChains?.forEach(cert => {
        console.info(cert);
      });
    }
  } catch (error) {
    console.error(`promise: anonAttestKeyItem fail`);
  }
}