签名/验签(ArkTS)
============

当前指导提供以下示例，供开发者参考完成签名、验签开发：

*   [密钥算法为RSA、摘要算法为SHA256、填充模式为PSS](#rsasha256pss)

具体的场景介绍及支持的算法规格，请参考[签名/验签介绍及算法规格](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/huks-ukey-signing-signature-verification-overview)。

#### 开发步骤

**签名**

1.  通过证书管理系统能力提供的[证书选择接口](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-certmanagerdialog#certificatemanagerdialogopenauthorizedialog22)获取[keyUri](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-certmanagerdialog#certreference22)作为resourceId，并作为密钥别名，[打开资源](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/huks-open-close-resource-ndk#打开资源)后完成PIN码认证。
    
2.  指定待签名的明文数据。
    
3.  获取属性参数[HuksOptions](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-huks#huksoptions)，包括两个字段properties和inData。inData传入明文数据，properties传入算法参数配置。
    
4.  调用[initSession](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-huks#huksinitsession9)初始化密钥会话，并获取会话的句柄handle。
    
5.  调用[finishSession](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-huks#huksfinishsession9)结束密钥会话，获取签名signature。
    

**验签**

1.  通过证书管理系统能力提供的[证书选择接口](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-certmanagerdialog#certificatemanagerdialogopenauthorizedialog22)获取[keyUri](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-certmanagerdialog#certreference22)作为resourceId，并作为密钥别名，然后[打开资源](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/huks-open-close-resource-ndk#打开资源)。
    
2.  获取待验证的签名。
    
3.  获取属性参数[HuksOptions](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-huks#huksoptions)，包括两个字段properties和inData。inData传入签名signature，properties传入算法参数配置。
    
4.  调用[initSession](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-huks#huksinitsession9)初始化密钥会话，并获取会话的句柄handle。
    
5.  调用[updateSession](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-huks#huksupdatesession9)更新密钥会话。
    
6.  调用[finishSession](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-huks#huksfinishsession9)结束密钥会话，验证签名。
    

#### 开发案例

#### \[h2\]RSA/SHA256/PSS

/\*
 \* 密钥算法为RSA，摘要算法为SHA256，填充模式为PSS
 \*/
import { huks } from '@kit.UniversalKeystoreKit';
import { BusinessError } from '@kit.BasicServicesKit';

let handle: number;
let plaintext = '123456';
let signature: Uint8Array;

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

function Uint8ArrayToString(fileData: Uint8Array) {
  let dataString = '';
  for (let i = 0; i < fileData.length; i++) {
    dataString += String.fromCharCode(fileData\[i\]);
  }
  return dataString;
}

function GetRsaSignProperties() {
  let properties: Array<huks.HuksParam> = \[{
    tag: huks.HuksTag.HUKS\_TAG\_ALGORITHM,
    value: huks.HuksKeyAlg.HUKS\_ALG\_RSA
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_KEY\_SIZE,
    value: huks.HuksKeySize.HUKS\_RSA\_KEY\_SIZE\_2048
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_PADDING,
    value: huks.HuksKeyPadding.HUKS\_PADDING\_PSS
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_DIGEST,
    value: huks.HuksKeyDigest.HUKS\_DIGEST\_SHA256
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_PURPOSE,
    value: huks.HuksKeyPurpose.HUKS\_KEY\_PURPOSE\_SIGN
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_KEY\_CLASS,
    value: huks.HuksKeyClassType.HUKS\_KEY\_CLASS\_EXTENSION
  }\];
  return properties;
}

function GetRsaVerifyProperties() {
  let properties: Array<huks.HuksParam> = \[{
    tag: huks.HuksTag.HUKS\_TAG\_ALGORITHM,
    value: huks.HuksKeyAlg.HUKS\_ALG\_RSA
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_KEY\_SIZE,
    value: huks.HuksKeySize.HUKS\_RSA\_KEY\_SIZE\_2048
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_PADDING,
    value: huks.HuksKeyPadding.HUKS\_PADDING\_PSS
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_DIGEST,
    value: huks.HuksKeyDigest.HUKS\_DIGEST\_SHA256
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_PURPOSE,
    value: huks.HuksKeyPurpose.HUKS\_KEY\_PURPOSE\_VERIFY
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_KEY\_CLASS,
    value: huks.HuksKeyClassType.HUKS\_KEY\_CLASS\_EXTENSION
  }\];
  return properties;
}

async function initSession(keyAlias: string, huksOptions: huks.HuksOptions) {
  console.info(\`promise: enter initSession\`);
  try {
    await huks.initSession(keyAlias, huksOptions)
      .then((data) => {
        handle = data.handle;
        console.info(\`promise: initSession success\`);
      }).catch((error: BusinessError) => {
        console.error(\`promise: initSession failed, errCode : ${error.code}, errMsg : ${error.message}\`);
      })
  } catch (error) {
    console.error(\`promise: initSession input arg invalid\`);
  }
}

async function updateSession(handle: number, huksOptions: huks.HuksOptions) {
  console.info(\`promise: enter updateSession\`);
  try {
    await huks.updateSession(handle, huksOptions)
      .then((data) => {
        let outData = data.outData as Uint8Array;
        console.info(\`promise: updateSession success, data = ${Uint8ArrayToString(outData)}\`);
      }).catch((error: BusinessError) => {
        console.error(\`promise: updateSession failed, errCode : ${error.code}, errMsg : ${error.message}\`);
      })
  } catch (error) {
    console.error(\`promise: updateSession input arg invalid\`);
  }
}

async function finishSession(handle: number, huksOptions: huks.HuksOptions) {
  console.info(\`promise: enter finishSession\`);
  try {
    await huks.finishSession(handle, huksOptions)
      .then((data) => {
        signature = data.outData as Uint8Array;
        console.info(\`promise: finishSession success, data = ${Uint8ArrayToString(signature)}\`);
      }).catch((error: BusinessError) => {
        console.error(\`promise: finishSession failed, errCode : ${error.code}, errMsg : ${error.message}\`);
      })
  } catch (error) {
    console.error(\`promise: finishSession input arg invalid\`);
  }
}

async function Sign(keyAlias: string, plaintext: string) {
  console.info(\`enter Sign\`);
  let signProperties = GetRsaSignProperties();
  let options: huks.HuksOptions = {
    properties: signProperties,
  }
  await initSession(keyAlias, options);

  if (handle !== undefined) {
    options.inData = StringToUint8Array(plaintext);
    await finishSession(handle, options);
  }
}

async function Verify(keyAlias: string, plaintext: string, signature: Uint8Array) {
  console.info(\`enter Verify\`);
  let verifyProperties = GetRsaVerifyProperties();
  let options: huks.HuksOptions = {
    properties: verifyProperties,
  }

  await initSession(keyAlias, options);

  if (handle !== undefined) {
    options.inData = StringToUint8Array(plaintext);
    await updateSession(handle, options);
    options.inData = signature;
    await finishSession(handle, options);
  }
}

async function testSignVerify() {
  // 假设keyAlias是已获取的resourceId
  let keyAlias = JSON.stringify({
    providerName: "testProviderName",
    bundleName: "com.example.cryptoapplication",
    abilityName: "CryptoExtension",
    index: {
      key: "testKey"
    } as ESObject
  });
  await Sign(keyAlias, plaintext);
  await Verify(keyAlias, plaintext, signature);
}