跳到主要内容

交易信息密码认证

场景介绍

在交易信息密码认证场景中,可以利用创建的数字盾密码对交易信息进行认证,可通过密钥管理服务提供的签名认证功能来确认交易内容是否被篡改,以确保整个交易过程的安全性。

约束与限制

本功能目前仅在手机设备支持。

业务流程

接口说明

接口及使用方法请参见API参考

接口名描述
procContentAuthentication(challenge: Uint8Array, authID: bigint, authMsg: AuthReqParams, label: TUILable): Promise<AuthToken>交易信息处理接口

交易信息密码认证界面介绍

如图1、图2、图3为使用数字盾密码进行交易认证时对应的TUI界面示例,其中交易信息密码认证分为两种场景:

  1. 当用户交易信息不超过6行时,则以下图1中无翻页形式进行密码认证。
  2. 当用户交易信息超过6行时,则以下图2-3中翻页形式进行密码认证,且当交易信息超过19行时,则Device Security Kit拒绝拉起TUI界面。

图1 无翻页密码认证

图2 翻页密码认证-1

图3 翻页密码认证-2

交易信息格式说明如下:

  1. 带标记格式,以key:value|flag形式,flag取值如下:

    • 0:表示不展示该行内容。
    • 1:单行截断展示(若内容超出一行则截断)。
    • 2:自动换行展示(若内容超出一行则换行)。

    如当交易信息为“收款户名:王**|1”,表示key为“收款户名”, value为“王**”,flag为1,该内容若超过一行则截断显示。

    • 当行内出现“|”符号时,系统默认按此格式解析,若交易内容格式未全部以该格式输出,则会显示失败。
    • 若flag=1(截断模式)的key过长导致value无法显示时,则会显示失败。
  2. 无标记格式,直接输入内容(无“|”符号)。

    • 系统将完整展示所有内容,超出一行时自动换行。

开发步骤

  1. 导入huks 、trustedAuthentication 和相关依赖模块。

    import { resourceManager } from '@kit.LocalizationKit'
    import { huks } from '@kit.UniversalKeystoreKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    import { trustedAuthentication } from '@kit.DeviceSecurityKit';
    import { cryptoFramework } from '@kit.CryptoArchitectureKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';
    import { common } from '@kit.AbilityKit';
    import { util } from '@kit.ArkTS';
  2. 发起交易认证前,需从服务器获取当前账号在设置数字盾密码时获取的authID。

  3. 参考密钥管理服务提供的签名/验签指导,初始化签名会话。

    • 设置签名密钥时密钥属性集合中需要指定tag: huks.HuksTag.HUKS_TAG_KEY_SECURE_SIGN_TYPE值为huks.HuksSecureSignType.HUKS_SECURE_SIGN_WITH_AUTHINFO,即可对附加的交易信息做签名认证。
    // 设置签名密钥属性示例
    let properties: Array<huks.HuksParam> = [{
    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
    value: huks.HuksKeyAlg.HUKS_ALG_ECC
    }, {
    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_SIGN
    }, {
    tag: huks.HuksTag.HUKS_TAG_DIGEST,
    value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256
    },
    // 表示对附加的交易信息做签名认证
    {
    tag: huks.HuksTag.HUKS_TAG_KEY_SECURE_SIGN_TYPE,
    value: huks.HuksSecureSignType.HUKS_SECURE_SIGN_WITH_AUTHINFO
    }];
  4. 调用交易认证接口,发起密码认证交易申请,当用户密码认证通过后,即可获得携带交易信息hash的authToken。

    async function ContentVerifyByPwd(challenge: Uint8Array, context: common.UIAbilityContext):Promise<trustedAuthentication.AuthToken> {
    try {
    const authID: bigint = 11842183505170721246n;//实际填充为从服务器获取到的账号对应的authID值
    const resourceMgr: resourceManager.ResourceManager = context.resourceManager;
    const fileData : Uint8Array = await resourceMgr.getRawFileContent('test_logo_rgba.png'); //实际使用时请替换为应用要在TUI界面展示的logo图片名称
    const reqParams:trustedAuthentication.AuthReqParams = {
    reqType: trustedAuthentication.AuthType.AUTH_TYPE_TUI_PIN,
    authContent: ["用户:王xx", "账号:95588180804408xxxx", "交易金额:1000000000"],//实际使用时填充为交易信息,每一行交易信息为其中的一个字符串成员
    }
    const buffer = fileData.buffer;
    const label:trustedAuthentication.TUILable = {
    image: buffer as ArrayBuffer,
    title: "密码交易认证",
    }
    const result = await trustedAuthentication.procContentAuthentication(challenge, authID, reqParams, label);
    return result;
    } catch (err) {
    hilog.error(0x0000, 'testTag', `Failed to procContentAuthentication, code:${err.code}, message:${err.message}`);
    throw new Error('Content verify by password failed:' + (err as BusinessError).message);
    }
    }
    const rand = cryptoFramework.createRandom();
    const len: number = 32;
    const challenge: Uint8Array = rand?.generateRandomSync(len)?.data;//实际使用时请替换为通过UniversalKeystoreKit初始化会话获取的challenge
    let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    const authToken: trustedAuthentication.AuthToken = await ContentVerifyByPwd(challenge, context);
  5. 参考密钥管理服务提供的针对携带认证信息的签名/验签指导, 对交易信息authToken数据进行签名验证,并结束会话。

    需要注意的是,在交易认证过程中输入的交易信息格式如下:

    //示例交易信息
    authContent: ["用户:王xx", "账号:95588180804408xxxx", "交易金额:1000000000"];

    而密钥管理服务验签时的inputData信息为Uint8Array,需要将所有信息按照\n拼接,并将UTF-8信息转换为Uint8Array

    function encodeUtf8(s: string): number[] {
    const encoder = new util.TextEncoder();

    const dest = new Uint8Array(s.length * 4);
    const result = encoder.encodeIntoUint8Array(s, dest);
    const encodedBytes = dest.subarray(0, result.written);
    return Array.from(encodedBytes);
    };
    //实际为应用向密钥管理服务传入的验签数据
    let str = "用户:王xx\n账号:95588180804408xxxx\n交易金额:1000000000";
    const utf8Bytes = new Uint8Array(encodeUtf8(str));
  6. 参考密钥管理服务提供的签名/验签指导, 对签名数据进行验签操作,验签通过后可完成对应账户的转账扣款。