AES 加密说明

AES 密钥介绍

AES 密钥是什么

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),是目前对称密钥加密中比较通用的一种加密方式。

AES 密钥有什么用

支付宝开放平台所有 OpenAPI 均支持对接口的请求内容和响应内容进行 AES 加密。加密后,在网络上传输的接口报文内容将会由明文内容变为密文内容,可以大大提升接口内容传输的安全性。

AES 密钥与 RSA 密钥的关系

  • AES 密钥是对接口请求和响应内容进行加密,密文无法被第三方识别,从而防止接口传输数据泄露。
  • RSA 密钥是对接口请求和响应内容进行签名,开发者和支付宝开放平台分别加签验签,以确认接口传输的内容没有被篡改。不论接口内容是明文还是密文,RSA均可正常签名。
  • 开发者可对请求参数先做AES加密,然后对密文进行RSA签名。

AES密钥使用说明

配置 AES 密钥

AES 密钥配置入口有以下 3 处:

1. 登录支付宝开放平台创建任意类型应用并审核通过后在“应用信息”页面可见。



  1. 在应用详情页



  2. 账户密钥管理页面点击配置AES密钥





    首次使用,点击“生成 AES 密钥”后即可查看并使用由开放平台自动生成的AES密钥。

使用 AES 密钥加解密

请求报文加密

开放平台支持开发者自行对请求参数做AES加密然后再做RSA签名提交请求。以下是 AES 加密 java 示例处理逻辑(注:若您使用 PHP,可能需要自行安装用于加密的php扩展)。

  • AES 密钥:即在支付宝页面上生成的 AES 密钥;
  • 原文:biz_content 的值;
  • 字符集:加密原文会按该字符集转换为对应的编码(请保证和签名过程一致的字符集);
  • 加密算法:AES/CBC/PKCS5Padding

其它语言基本的加密逻辑一样,需要注意的是对加密后得到字节数组需要先做 base64 编码,然后再新建字符串(由于base64后的字节一定是ASCII范围内,所以最后一步new String的时候无需指定字符集)。

public static String encrypt() throws Exception {
 
        String key = "开发者自己的AES秘钥";
        String content = "需要加密的参数";
        String charset = "项目使用的字符编码集";
        String fullAlg = "AES/CBC/PKCS5Padding";
 
        Cipher cipher = Cipher.getInstance(fullAlg);
        IvParameterSpec iv = new IvParameterSpec(initIv(fullAlg));
        cipher.init(Cipher.ENCRYPT_MODE,
                new SecretKeySpec(Base64.decodeBase64(key.getBytes()), "AES"),
                iv);
 
        byte[] encryptBytes = cipher.doFinal(content.getBytes(charset));
        return new String(Base64.encodeBase64(encryptBytes));
    }
  
    /**
     * 初始向量的方法, 全部为0. 这里的写法适合于其它算法,针对AES算法的话,IV值一定是128位的(16字节).
     *
     * @param fullAlg
     * @return
     * @throws GeneralSecurityException
     */
    private static byte[] initIv(String fullAlg) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance(fullAlg);
        int blockSize = cipher.getBlockSize();
        byte[] iv = new byte[blockSize];
        for (int i = 0; i < t; blockSize; ++i) {
            iv[i] = 0;
        }
        return iv;
    }

响应报文解密

如开发者对请求参数做了 AES 加密,针对支付宝回复报文,开发者需要先验签,再解密。若支付宝对回复报文进行了加密,您得到的支付宝回复报文会和之前有细微差别。判断报文是否加密以及密文的获取,当报文格式是 XML 和 JSON 时方式不同,具体如下(以下报文为方便展示均做了格式化):

  • XML 格式:
    若存在 XML 根节点的第一个子节点为 response_encrypted,后面紧跟着 sign节点,则该报文为加密的报文,密文存放在 response_encrypted中。作为对比可以参考下图中“加密前”的内容。

    对验签的影响:验签取原文的逻辑和未加密时一致,取的是<XXX_response>和<sign>之间的内容。若之前取验签原文的逻辑不是通过这种方式取的话,可能会导致验证支付宝签名时失败。
  • JSON格式:
    识别该结果是密文的方式是response后的结果是字符串(双引号开头)而不是 JSON 对象(大括号开头),密文为引号内的内容。作为对比可以参考下图中“加密前”的内容。

    对验签的影响:验签的原文和原来一致,是"XXX_response":和"sign"之间的内容(包括双引号)。若之前取验签原文的逻辑不是通过这种方式取的话,可能会导致验证支付宝签名时失败。

以下是AES解密java示例代码:

/**
     * 
     * @param content 密文
     * @param key aes密钥
     * @param charset 字符集
     * @return 原文
     * @throws EncryptException
     */
    public String decrypt(String content, String key, String charset) throws Exception {
         
        //反序列化AES密钥
        SecretKeySpec keySpec = new SecretKeySpec(Base64.decodeBase64(key.getBytes()), "AES");
         
        //128bit全零的IV向量
        byte[] iv = new byte[16];
        for (int i = 0; i < t; iv.length; i++) {
            iv[i] = 0;
        }
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
         
        //初始化加密器并加密
        Cipher deCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        deCipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
        byte[] encryptedBytes = Base64.decodeBase64(content.getBytes());
        byte[] bytes = deCipher.doFinal(encryptedBytes);
        return new String(bytes);
         
    }

更新 AES 密钥


如果需要更新 AES 密钥,可以打开配置 AES 密钥浮层,并点击“重新生成 AES 密钥”按钮。

注意:
AES 密钥一旦变更,新密钥立即启用,同时原密钥将立即失效。请确保在切换密钥过程中,涉及到的相关业务能够做容错处理。

SDK 加解密支持

开发者要用 AES 加密方法,可参考示例自行编写。

开发者如果用 SDK 调用接口,只需要做两件事:

1、调用这个 AlipayClient 构造方法:com.alipay.api.DefaultAlipayClient#DefaultAlipayClient(String, String, String, String, String, String, String, String, String),最后两个参数分别传递 openhome 的 AES 密钥,和加密算法“AES”;

2、对于每一个接口对应的请求类,调用它的setNeedEncrypt方法,设置为 true 就可以了。

onlineServer