HarmonyOS Next在支付场景中的安全通信设计:基于NFC和Secure Element的数据加密

本文旨在深入探讨华为鸿蒙HarmonyOS Next系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。

一、场景描述

在当今数字化支付时代,便捷性与安全性是支付场景中两个至关重要的因素。HarmonyOS Next利用其强大的NFC(近场通信)和安全单元(Secure Element)功能,为支付场景构建了一道坚固的安全防线。想象一下,在商场购物结账时,只需将支持HarmonyOS Next的设备轻轻靠近支付终端,就能快速、安全地完成支付过程。整个过程无需繁琐的操作,同时确保了支付数据的保密性、完整性和可用性。

二、架构设计

  1. NFC实现无接触式支付通信
    • NFC技术使得支付设备与终端之间能够进行短距离的无线通信。当设备靠近支付终端时,NFC功能自动被触发,建立起两者之间的通信链路。例如,在乘坐地铁时,手机靠近闸机的NFC读卡器,即可自动开启支付流程,方便快捷。
  2. Secure Element保障支付数据安全
    • 安全单元在支付架构中扮演着核心角色。它负责对支付信息进行加密处理,确保数据在传输过程中不被窃取或篡改。通过生成强大的加密密钥,只有拥有正确密钥的设备才能对支付数据进行解密和访问,从而有效保护用户的资金安全。
  3. 多层安全策略集成
    • 系统中集成了多层安全防护机制。在设备层面,只有经过严格身份验证的设备才能启用支付功能,防止非法设备进行支付操作。同时,在数据传输过程中,采用加密算法和数字签名等技术,进一步验证数据的来源和完整性。

三、实现步骤

  1. 配置NFC支付功能
    • 首先,通过NFC接口开启标签读写或HCE(Host Card Emulation)功能。在module.json5文件中声明相关权限和action,如下所示:
{
  "abilities": [
    {
      "name": "EntryAbility",
      "srcEntry": "./ets/entryability/EntryAbility.ts",
      "description": "$string:EntryAbility_desc",
      "icon": "$media:icon",
      "label": "$string:EntryAbility_label",
      "startWindowIcon": "$media:icon",
      "startWindowBackground": "$color:start_window_background",
      "exported": true,
      "skills": [
        {
          "entities": [
            "entity.system.home"
          ],
          "actions": [
            "action.system.home",
            "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE"
          ]
        }
      ]
    }
  ],
  "requestPermissions": [
    {
      "name": "ohos.permission.NFC_CARD_EMULATION",
      "reason": "$string:app_name"
    }
  ]
}
  • 然后在应用代码中进行相应的初始化操作,例如:
import { cardEmulation } from '@kit.ConnectivityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

let hceElementName;
let hceService;

export default class EntryAbility extends UIAbility {
    onCreate(want, launchParam) {
        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
        // 判断设备是否支持NFC能力和HCE能力
        if (!canIUse("SystemCapability.Communication.NFC.Core")) {
            hilog.error(0x0000, 'testTag', 'nfc unavailable.');
            return;
        }
        if (!cardEmulation.hasHceCapability()) {
            hilog.error(0x0000, 'testTag', 'hce unavailable.');
            return;
        }
        hceElementName = {
            bundleName: want.bundleName?? '',
            abilityName: want.abilityName?? '',
            moduleName: want.moduleName
        };
        hceService = new cardEmulation.HceService();
    }
}
  1. Secure Element密钥管理与支付数据加密
    • 使用Secure Element API生成加密密钥并存储在安全单元中。示例代码如下:
import { omapi } from '@kit.ConnectivityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

let seService;
let seReaders;
let seSession;
let seChannel;
let aidArray = [0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10];
let p2 = 0x00;

export default class EntryAbility extends UIAbility {
    onCreate(want, launchParam) {
        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
        // 判断设备是否支持安全单元能力
        if (!canIUse("SystemCapability.Communication.SecureElement")) {
            hilog.error(0x0000, 'testTag', 'secure element unavailable.');
            return;
        }
        // 获取安全单元服务
        try {
            seService = omapi.newSEService("serviceState", (state) => {
                hilog.info(0x0000, 'testTag', 'se service state ='+ JSON.stringify(state));
            });
        } catch (error) {
            hilog.error(0x0000, 'testTag', 'newSEService error'+ JSON.stringify(error));
        }
        if (seService == undefined ||!seService.isConnected()) {
            hilog.error(0x0000, 'testTag', 'secure element service disconnected.');
            return;
        }
        // 获取安全单元读取器
        try {
            seReaders = seService.getReaders();
        } catch (error) {
            hilog.error(0x0000, 'testTag', 'getReaders error'+ JSON.stringify(error));
        }
        if (seReaders == undefined || seReaders.length == 0) {
            hilog.error(0x0000, 'testTag', 'no valid reader found.');
            return;
        }
        // 打开安全单元会话
        try {
            let reader = seReaders[0];
            seSession = reader.openSession();
        } catch (error) {
            hilog.error(0x0000, 'testTag', 'openSession error'+ JSON.stringify(error));
        }
        if (seSession == undefined) {
            hilog.error(0x0000, 'testTag', 'seSession invalid.');
            return;
        }
        // 打开逻辑通道
        try {
            seSession.openLogicalChannel(aidArray, p2, (error, data) => {
                if (error) {
                    hilog.error(0x0000, 'testTag', 'openLogicalChannel error'+ JSON.stringify(error));
                } else {
                    seChannel = data;
                }
            });
        } catch (exception) {
            hilog.error(0x0000, 'testTag', 'openLogicalChannel exception'+ JSON.stringify(exception));
        }
        if (seChannel == undefined) {
            hilog.error(0x0000, 'testTag', 'seChannel invalid.');
            return;
        }
        // 生成加密密钥(这里仅为示例,实际密钥生成可能更复杂)
        let keyData = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
        seChannel.generateKey(keyData).then((generatedKey) => {
            hilog.info(0x0000, 'testTag', 'Generated key:'+ JSON.stringify(generatedKey));
            // 存储密钥(假设存储在安全单元的特定位置)
            seChannel.storeKey(generatedKey).then(() => {
                hilog.info(0x0000, 'testTag', 'Key stored successfully.');
            }).catch((error) => {
                hilog.error(0x0000, 'testTag', 'Key storage error:'+ JSON.stringify(error));
            });
        }).catch((error) => {
            hilog.error(0x0000, 'testTag', 'Key generation error:'+ JSON.stringify(error));
        });
    }
}
  • 当进行支付时,使用存储的密钥对支付数据进行加密。假设支付数据为一个包含金额、商户信息等的对象,将其转换为字节数组后进行加密:
// 假设支付数据对象
let paymentData = {
    amount: 100.00,
    merchantId: '123456',
    // 其他支付相关信息
};
let paymentDataBuffer = JSON.stringify(paymentData).split('').map(c => c.charCodeAt(0));
let paymentDataArray = new Uint8Array(paymentDataBuffer);
seChannel.encrypt(paymentDataArray).then((encryptedData) => {
    hilog.info(0x0000, 'testTag', 'Encrypted payment data:'+ JSON.stringify(encryptedData));
    // 发送加密后的支付数据(这里省略发送过程,实际应用中需要通过NFC或其他方式将数据发送到支付终端)
}).catch((error) => {
    hilog.error(0x0000, 'testTag', 'Payment data encryption error:'+ JSON.stringify(error));
});
  1. NFC与Secure Element协同完成支付流程
    • 在支付过程中,NFC负责建立设备与支付终端之间的通信链路,将加密后的支付数据传输到支付终端。支付终端收到数据后,通过预先共享的密钥或证书等方式,与设备的安全单元进行身份验证和数据解密。如果身份验证成功且数据解密无误,支付终端完成支付操作,并向设备返回支付结果。设备的安全单元收到支付结果后,进行相应的处理,如更新支付状态、通知用户等。

四、技术亮点

  1. 双重安全保障支付数据
    • NFC和Secure Element的结合为支付数据提供了双重保险。NFC确保了支付过程的便捷性,而Secure Element则从数据加密和身份验证层面保障了安全性。即使在数据传输过程中被拦截,没有正确的密钥也无法获取支付信息的真实内容。
  2. HCE卡模拟提升支付便捷性
    • 支持HCE卡模拟功能使得设备无需依赖物理卡片,即可实现支付功能。用户只需在设备上进行简单的设置,就能将银行卡等支付卡片信息模拟到设备中,大大提升了支付的便捷性。同时,通过安全单元的加密和身份验证,保证了模拟卡片的安全性。

五、示例代码

以下是一个完整的NFC支付场景代码示例,包括Secure Element的密钥生成、支付数据加密以及NFC通信相关操作(部分代码参考前面的实现步骤并进行整合):

import { cardEmulation } from '@kit.ConnectivityKit';
import { omapi } from '@kit.ConnectivityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit';
import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit';

let hceElementName: bundleManager.ElementName;
let hceService: cardEmulation.HceService;
let seService: omapi.SEService;
let seReaders: omapi.Reader[];
let seSession: omapi.Session;
let seChannel: omapi.Channel;
let aidArray: number[] = [0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10];
let p2: number = 0x00;

const hceCommandCb: AsyncCallback<number[]> = (error: BusinessError, hceCommand: number[]) => {
    if (!error) {
        if (hceCommand == null || hceCommand == undefined) {
            hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.');
            return;
        }
        // 这里可以根据接收到的命令进行处理,例如验证支付结果等
        hilog.info(0x0000, 'testTag', 'Received HCE command:'+ JSON.stringify(hceCommand));
    } else {
        hilog.error(0x0000, 'testTag', 'hceCommandCb error'+ JSON.stringify(error));
    }
};

export default class EntryAbility extends UIAbility {
    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
        // 判断设备是否支持NFC能力和HCE能力
        if (!canIUse("SystemCapability.Communication.NFC.Core")) {
            hilog.error(0x0000, 'testTag', 'nfc unavailable.');
            return;
        }
        if (!cardEmulation.hasHceCapability()) {
            hilog.error(0x0000, 'testTag', 'hce unavailable.');
            return;
        }
        hceElementName = {
            bundleName: want.bundleName?? '',
            abilityName: want.abilityName?? '',
            moduleName: want.moduleName
        };
        hceService = new cardEmulation.HceService();

        // 判断设备是否支持安全单元能力
        if (!canIUse("SystemCapability.Communication.SecureElement")) {
            hilog.error(0x0000, 'testTag', 'secure element unavailable.');
            return;
        }
        // 获取安全单元服务
        try {
            seService = omapi.newSEService("serviceState", (state) => {
                hilog.info(0x0000, 'testTag', 'se service state ='+ JSON.stringify(state));
            });
        } catch (error) {
            hilog.error(0x0000, 'testTag', 'newSEService error'+ JSON.stringify(error));
        }
        if (seService == undefined ||!seService.isConnected()) {
            hilog.error(0x0000, 'testTag', 'secure element service disconnected.');
            return;
        }
        // 获取安全单元读取器
        try {
            seReaders = seService.getReaders();
        } catch (error) {
            hilog.error(0x0000, 'testTag', 'getReaders error'+ JSON.stringify(error));
        }
        if (seReaders == undefined || seReaders.length == 0) {
            hilog.error(0x0000, 'testTag', 'no valid reader found.');
            return;
        }
        // 打开安全单元会话
        try {
            let reader = seReaders[0];
            seSession = reader.openSession();
        } catch (error) {
            hilog.error(0x0000, 'testTag', 'openSession error'+ JSON.stringify(error));
        }
        if (seSession == undefined) {
            hilog.error(0x0000, 'testTag', 'seSession invalid.');
            return;
        }
        // 打开逻辑通道
        try {
            seSession.openLogicalChannel(aidArray, p2, (error, data) => {
                if (error) {
                    hilog.error(0x0000, 'testTag', 'openLogicalChannel error'+ JSON.stringify(error));
                } else {
                    seChannel = data;
                }
            });
        } catch (exception) {
            hilog.error(0x0000, 'testTag', 'openLogicalChannel exception'+ JSON.stringify(exception));
        }
        if (seChannel == undefined) {
            hilog.error(0x0000, 'testTag', 'seChannel invalid.');
            return;
        }
    }

    onForeground() {
        // 使能前台HCE应用程序优先处理NFC刷卡功能
        let aidList = ["A0000000031010"]; // 根据实际情况修改AID
        hceService.start(hceElementName, aidList);
        // 订阅HCE APDU数据的接收
        hceService.on('hceCmd', hceCommandCb);

        // 生成加密密钥(这里仅为示例,实际密钥生成可能更复杂)
        let keyData = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
        seChannel.generateKey(keyData).then((generatedKey) => {
            hilog.info(0x0000, 'testTag', 'Generated key:'+ JSON.stringify(generatedKey));
            // 存储密钥(假设存储在安全单元的特定位置)
            seChannel.storeKey(generatedKey).then(() => {
                hilog.info(0x0000, 'testTag', 'Key stored successfully.');
                // 假设支付数据为一个包含金额、商户信息等的对象
                let paymentData = {
                    amount: 100.00,
                    merchantId: '123456',
                    // 其他支付相关信息
                };

let paymentDataBuffer = JSON.stringify(paymentData).split('').map(c => c.charCodeAt(0));
let paymentDataArray = new Uint8Array(paymentDataBuffer);
seChannel.encrypt(paymentDataArray).then((encryptedData) => {
    hilog.info(0x0000, 'testTag', 'Encrypted payment data:'+ JSON.stringify(encryptedData));
    // 发送加密后的支付数据(这里省略发送过程,实际应用中需要通过NFC或其他方式将数据发送到支付终端)
}).catch((error) => {
    hilog.error(0x0000, 'testTag', 'Payment data encryption error:'+ JSON.stringify(error));
});
} else {
    hilog.error(0x0000, 'testTag', 'Key generation error:'+ JSON.stringify(error));
}
}

onBackground() {
    // 退出应用程序NFC标签页面时,退出前台优先功能
    hceService.stop(hceElementName);
}

六、NFC与Secure Element在支付场景中的主要功能和技术特性对比

对比项目 NFC Secure Element
主要功能 - 建立设备与支付终端之间的短距离无线通信链路。
- 实现无接触式支付触发,如靠近支付终端自动启动支付流程。
- 传输加密后的支付数据到支付终端。
- 生成和管理加密密钥,确保支付数据的保密性。
- 对支付数据进行加密和解密操作。
- 提供安全的存储环境,存储支付相关信息(如卡片信息、密钥等)。
- 进行身份验证,确保只有合法设备和用户能够访问支付数据。
技术特性 - 工作在13.56MHz频率,通信距离一般在10厘米左右,适用于近距离支付场景。
- 通信速度相对较快,能够满足支付数据的快速传输需求。
- 支持多种通信模式,如卡模拟模式(用于模拟支付卡片)、标签读写模式等。
- 基于硬件或独立软件环境,具有高度的安全性,难以被攻击和篡改。
- 加密算法强大,能够有效防止数据泄露。
- 与设备的操作系统紧密集成,提供安全的执行环境和访问控制机制。

在实际应用中,HarmonyOS Next在支付场景中的这种安全通信设计为用户带来了诸多优势。用户无需担心支付数据被窃取或篡改,能够更加放心地使用移动支付功能。对于商家和支付机构而言,也降低了支付风险,提高了支付系统的可靠性和安全性。

未来,随着技术的不断发展,HarmonyOS Next在支付领域有望进一步创新。例如,可能会引入更先进的生物识别技术(如指纹识别、面部识别等)与NFC和Secure Element相结合,提供更加便捷和安全的支付体验。同时,随着物联网的普及,支付场景将更加多样化,HarmonyOS Next的安全通信设计也将能够适应不同场景的需求,为智能支付的发展提供坚实的技术支撑。就像一座坚固的桥梁,连接着用户、商家和金融机构,确保支付数据在这个数字生态系统中安全、顺畅地流动。哈哈,是不是感觉未来的支付方式会越来越智能、越来越安全呢?希望这篇文章能为大家在支付技术领域的探索提供一些有益的参考和启发!

posted @ 2024-11-14 09:26  SameX  阅读(4)  评论(0编辑  收藏  举报