为确保数据交互安全,使用RSA私钥签名+AES加密接口调用方式。
RSA私钥签名+AES加密:使用RSA私钥对数据生成签名,用分配的secret_key对数据进行AES加密,以防止敏感信息泄露。
1、RSA签名+AES加密
字段名 | 字段类型 | 字段说明 |
version | String | 当前接口版本号,默认为:1.0 |
sign | String | RSA签名 |
content | String | json字符串通过secret_key AES加密并转换为16进制的字符串 |
└─phone | String | 手机号 |
└─smscontent | String | 发送内容 |
请求参数参考: { "version": "1.0", "sign": "V3CP+NalLWGawdxZKjRv", "content": "EC18C4D91553D4227AB8F615" } |
字段名 | 字段类型 | 字段说明 |
code | String | 返回码,200成功,其他失败 |
errorCode | String | 错误编码,英文错误码 |
msg | String | 返回消息 |
返回格式参考: { "code": "200", "errorCode": "SUCCESS", "msg": "ok" } |
1、首先对data(明文)中各字段参数按参数名做字典序升序排列
2、将上一步所得结果中字段按照key=value格式化,并通过&拼接为字符串。
3、调用方对上一步所得字符串计算RSA私钥签名,签名方式为'SHA256withRSA'; 被调用方(即发货方)用分配的secret_key对数据进行AES解密,然后用分配的RSA公钥进行验签。
示例:
data:{"phone": “18353521235”, "smscontent":”xxxxxx”}
签名字符串: phone=18353521235&smscontent=xxxxxx
RSA签名计算方式参考:
/**
* 用私钥对信息生成数字签名
* @param rasPrivateKey RSA私钥
* @param data 待签名数据,须转成二进制格式
* @return 签名
*/
public static String sign(String rasPrivateKey, byte[] data) throws Exception{
// 解密私钥
byte[] keyBytes = Base64.decodeBase64(rasPrivateKey);
//构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
//指定加密算法
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//取私钥匙对象
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//用私钥对信息生成数字签名
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
return Base64.encodeBase64String(signature.sign()).replaceAll("[\r\n]", "");
}
验签样例:
/**
* 校验数字签名
* @param data 待签名数据
* @param sign RSA私钥签名
* @param rasPublicKey RSA公钥
* @return 验签成功返回true, 否则返回false
*/
public static boolean verify(byte[] data, String sign, String rasPublicKey)throws Exception{
//解密公钥
byte[] keyBytes = decryptBASE64(rasPublicKey);
//构造X509EncodedKeySpec对象
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
//指定加密算法
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//取公钥匙对象
PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey2);
signature.update(data);
//验证签名是否正常
return signature.verify(decryptBASE64(sign));
}
加密:
/**
* AES 加密操作
* @param content 待加密内容
* @param password 加密密码
*/
public static byte[] encrypt(String content, String password) {
try {
byte[] byteContent = content.getBytes("utf-8");
// 创建密码器
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// 初始化为加密模式的密码器,秘钥长度 16/24/32
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(password.getBytes("utf-8"), "AES"));
return cipher.doFinal(byteContent);
} catch (Exception e) {
e.printStackTrace();
}
// 如果有错就返回null
return null;
}
解密:
/**
* AES 解密操作
* @param content 待解密内容
* @param password 加密密码
* @return
*/
public static String decrypt(byte[] content, String password) {
try {
//实例化
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
//使用密钥初始化,设置为解密模式,秘钥长度 16/24/32
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(password.getBytes("utf-8"), "AES"));
//执行操作
byte[] result = cipher.doFinal(content);
return new String(result, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
// 如果有错就返回null
return null;
}
/**
* 将二进制转换为16进制
* @param buf 待转换二进制数组
* @return 16进制字符串
*/
static String parseByte2HexStr(byte[] buf) {
StringBuilder sb = new StringBuilder();
for (byte b : buf) {
String hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**
* 将16进制转换为二进制
* @param hexStr 待转换16进制字符串
* @return 2进制字节数组
*/
static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1) {
return null;
}
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
POST方式请求。
UTF-8
application/json