高级加密标准(英语:Advanced Encryption Standard,缩写:AES),是目前对称密钥加密中比较通用的一种加密方式。
AES密钥有什么用
支付宝开放平台所有OpenAPI均支持对接口的请求内容和响应内容进行AES加密。加密后,在网络上传输的接口报文内容将会由明文内容变为密文内容,可以大大提升接口内容传输的安全性。
AES密钥与RSA密钥的关系
AES密钥是对接口请求和响应内容进行加密,密文无法被第三方识别,从而防止接口传输数据泄露。
RSA密钥是对接口请求和响应内容进行签名,开发者和支付宝开放平台分别加签验签,以确认接口传输的内容没有被篡改。不论接口内容是明文还是密文,RSA均可正常签名。
开发者可对请求参数先做AES加密,然后对密文进行RSA签名。
AES密钥使用说明
配置AES密钥
AES密钥配置入口有以下3处:
1. 登录支付宝开放平台创建任意类型应用并审核通过后在“应用详情-应用环境”页面可见。
2. 在应用详情页
3. 账户密钥管理页面点击配置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"),
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 < 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 < 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就可以了。
关于此文档暂时还没有FAQ