支付宝应用和小程序开发:使用阿里云KMS保护应用私钥

一、支付宝开放平台的公私钥机制

支付宝开放平台的应用管理体系,使用了公私钥的机制,来保障商户应用和支付宝交互的安全性。这一机制包括两个部分:

  1. 商户应用使用自己的私钥对消息加签之后,将消息和签名传递给支付宝,支付宝则使用应用的公钥验证消息的真实性(来自于合法应用的真实消息)。
  2. 对于支付宝返回消息给商户应用的情形,应用则使用支付宝的“平台公钥”来验证返回消息的真实性。

下图简单描述了上述第一部分的交互机制:

支付宝应用和小程序开发:使用阿里云KMS保护应用私钥

这一机制的关键前提假定是:

商户应用必须保障应用私钥的安全性,从而保障应用和和支付宝交互的安全性。

反之,一旦私钥发生泄露,商户则会面临较大的安全风险。若应用和支付宝的交互涉及到资金类接口则风险更甚。

二、阿里云KMS带来的价值

相比于在应用中使用应用私钥的明文来对消息进行加签,阿里云KMS为用户带来了如下几个方面的优势:

  1. 保障私钥安全性:用户可以将签名私钥安全托管在KMS的托管密码机内。用户通过KMS的开放API使用私钥加签时,私钥会在密码机的硬件安全边界之内,完成运算后返回签名值,从而防止私钥的泄露。
  2. 控制谁可以使用私钥:用户可以通过阿里云访问控制服务(RAM服务),中心化的管理和控制谁可以使用KMS中的密钥,用于应用加签。
  3. 审计对私钥的调用日志:通过阿里云操作审计服务可以查看每一次调用KMS的记录;而商家应用自行保管私钥则很难产生“客观”的审计事件。
  4. 对安全事件的响应能力:在应用系统遭遇恶意者攻击等安全事件的情形下,也可以通过多种手段阻止对私钥的非法使用:例如用户可以通过RAM服务撤销对私钥的使用权限,或者通过KMS禁用私钥等。

支付宝应用和小程序开发:使用阿里云KMS保护应用私钥

三、使用阿里云KMS配置应用密钥

第一步:在阿里云KMS中创建应用密钥

  1. 登录阿里云KMS的管理控制台
  2. 在左上角的地域选择栏,选择合适的地域。通常情况下,建议您选择和应用部署相同的KMS地域创建密钥。
  3. 点击 创建密钥,选择密钥类型和密钥用途。

    • 密钥类型使用 RSA_2048
    • 密钥用途选择 Sign/Verify
    • 保护级别选择 Hsm,即通过KMS系统的硬件加密机产生和保护密钥

支付宝应用和小程序开发:使用阿里云KMS保护应用私钥

第二步:在支付宝配置应用密钥

支付宝开放平台提供了两种配置方法,普通公钥方式公钥证书方式

公钥证书方式是对普通公钥方式的增强机制,从数字签名的角度来看,机制大同小异,商户应用只需要二选一即可。注意:对于涉及到资金往来的商户应用,应当使用公钥证书的方式。

方法一:普通公钥方式

以下步骤参考支付宝开放平台普通公钥方式,并做恰当修改:

  1. 在阿里云KMS的管理控制台,选择之前创建的RSA_2048类型的密钥,进入详情页之后,点击查看公钥可以复制或者下载应用公钥。
  2. 进入 支付宝开放平台 并打开对应的应用,在应用的开发配置页面进行 接口加签方式 设置。点击 设置 后,输入手机验证码。
  3. 复制上一步生成的公钥,粘贴到 填写公钥字符 对应的位置,点击 保存设置,即可完成公钥的设置。

支付宝应用和小程序开发:使用阿里云KMS保护应用私钥

普通公钥方式的一句话总结:

从阿里云KMS获取应用公钥,注册到支付宝开放平台对应的应用中。

方法二:公钥证书方式

以下步骤参考支付宝开放平台公钥证书方式,并做恰当修改:

  1. 在阿里云KMS的管理控制台,选择之前创建的RSA_2048类型的密钥,进入详情页之后,点击 生成CSR。注意:填写证书属性时,企业/单位名称 一定要和开发者中心门户账号信息的公司名称保持一致,否则会导致后续步骤中上传 CSR 证书文件校验失败。
    支付宝应用和小程序开发:使用阿里云KMS保护应用私钥
  2. 进入 支付宝开放平台 并打开对应的应用,在应用的开发配置页面进行 接口加签方式 设置。点击 设置 后,输入手机验证码。
  3. 加签模式 选择 公钥证书上传证书文件 选择 上传CSR文件在线生成证书。最后点击 上传CSR文件在线生成证书,即可完成公钥证书的设置。
    支付宝应用和小程序开发:使用阿里云KMS保护应用私钥

公钥证书方式的一句话总结:

从阿里云KMS获取应用私钥的证书请求 CSR,到支付宝开放平台一键完成应用证书签发和注册。

四、应用中调用阿里云KMS

支付宝开放平台新版SDK,也就是EasySDK集成了阿里云KMS作为加签提供器(Sign Provider),简化使用。以Java为例,您需要在应用中引用EasySDK 2.0.1以及之后的版本。

<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-easysdk</artifactId>
    <version>2.0.1</version>
</dependency>

当然,如果遵循支付宝开放API的签名规则,也可以不使用EasySDK,通过阿里云KMS的AsymmetricSign接口自行实现签名。

代码示例:普通公钥方式

本示例来自于阿里云KMS的Github代码样例库

package com.aliyun.kms.samples;

import com.alipay.easysdk.base.qrcode.models.AlipayOpenAppQrcodeCreateResponse;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kms.aliyun.AliyunKMSConfig;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;

/**
 * Alipay-easysdk使用KMS签名示例,本示例展示了公钥模式调用
 */
public class KmsAlipayEasySDKPublicKeyDemo {
    public static void main(String[] args) {
        Factory.setOptions(getOptions());
        try {
            AlipayOpenAppQrcodeCreateResponse response = Factory.Base.Qrcode().create("page/component/component-pages/view/view", "x=1", "二维码描述");
            if ("10000".equals(response.code)) {
                System.out.println("调用成功");
            } else {
                System.err.println("调用失败,原因:" + response.msg + "," + response.subMsg);
            }
        } catch (Exception e) {
            System.err.println("调用遭遇异常,原因:" + e.getMessage());
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    private static AliyunKMSConfig getOptions() {
        AliyunKMSConfig config = new AliyunKMSConfig();
        config.protocol = "https";
        config.gatewayHost = "openapi.alipay.com";
        config.signType = "RSA2";

        // 请更换为您的AppId
        config.appId = "202100****";
        // 请修改如下的支付宝公钥字符串为自己的支付宝公钥
        config.alipayPublicKey = "MIIBIjANB...";

        // 如果使用阿里云KMS签名,则需要指定签名提供方名称,阿里云KMS的名称为"AliyunKMS"
        config.signProvider = "AliyunKMS";

        // 如果使用阿里云KMS签名,请更换为您的阿里云AccessKeyId
        config.aliyunAccessKeyId = getAliyunAccessKey("AccessKeyId");
        // 如果使用阿里云KMS签名,请更换为您的阿里云AccessKeySecret
        config.aliyunAccessKeySecret = getAliyunAccessKey("AccessKeySecret");
        // 如果使用阿里云KMS签名,请更换为您的KMS服务密钥ID
        config.kmsKeyId = "4358f298-8e30-4849-9791-****";
        // 如果使用阿里云KMS签名,请更换为您的KMS服务密钥版本ID
        config.kmsKeyVersionId = "e71daa69-c321-4014-b0c4-****";

        // 如果使用阿里云KMS签名,需要更换为您的KMS服务地址
        // KMS服务地址列表详情,请参考:
        // https://help.aliyun.com/document_detail/69006.html?spm=a2c4g.11186623.2.9.783f77cfAoNhY6#concept-69006-zh
        config.kmsEndpoint = "kms.cn-hangzhou.aliyuncs.com";

        return config;
    }

    /**
     * 从文件中读取阿里云AccessKey配置信息
     * 此处为了测试执行的环境普适性,AccessKey信息配置在resources资源下,实际过程中请不要这样做。
     *
     * @param key AccessKey配置对应的key
     * @return AccessKey配置字符串
     */
    private static String getAliyunAccessKey(String key) {
        InputStream stream = KmsAlipayEasySDKPublicKeyDemo.class.getResourceAsStream("/fixture/aliyunAccessKey.json");
        Map<String, String> result = new Gson().fromJson(new InputStreamReader(stream), new TypeToken<Map<String, String>>() {
        }.getType());
        return result.get(key);
    }
}

代码示例:公钥证书方式

使用公钥证书模式时,EasySDK的使用方式和上述示例类似,区别主要在于配置了商户应用和支付宝平台的公钥证书。

请参考阿里云KMS的Github代码样例库了解更多。

上一篇:Linux系统环境查看已经登录用户信息及管理


下一篇:C# 子窗体中调用父窗体中的方法(或多窗体之间方法调用)