一、数据交互
我们自己的系统需要和第三方系统进行对接,实现业务的完全系统化、自动化操作等,系统对接其实就是数据的对接,有数据的传输那么就得考虑数据的安全交互,一般需要我们做到两点:数据加密和数据签名。数据加密是为了解决明文暴露的问题,数据签名是为了确保数据完整性和防篡改。
二、非对称加密
非对称加密算法存在两个密钥,一个称之为公钥,一个称之为私钥,这两个密钥完全不同但又完全匹配。只有使用匹配的一对公钥和私钥,才能完成对明文的加密和解密过程。常见的非对称加密有RSA、SM2等
三、公钥与私钥
由服务端生成公钥与私钥,然后把公钥发送给客户端,客户端通过公钥对数据加密,然后把加密的数据发送给服务端,服务端通过私钥对数据解密。
实际项目中,客户端和服务端是相对而言的,客户端也有可能是服务端来接收数据,所以一般两端都会生成一对公钥和私钥,然后把公钥发送给对方,接口交互过程中,通过公钥加密,私钥解密进行数据传输。
公钥和私钥都可以用于加解密操作,用公钥加密的数据只能由对应的私钥解密,反之亦然。虽说两者都可用于加密,但是不同场景使用不同的密钥来加密,规则如下:
1、私钥用于签名、公钥用于验签(私钥加密,公钥解密)
签名和加密作用不同,签名并不是为了保密,而是为了保证这个签名是由特定的某个人签名的,而不是被其它人伪造的签名,所以私钥的私有性就适合用在签名用途上。
2、公钥用于加密、私钥用于解密
公钥加密,只能由私钥解密,而私钥是私有不公开的,只能由特定的私钥持有人解密,保证数据的安全性(即使截获数据也不知道是什么内容)
四、RSA加解密代码
/**
* RSA非对称加密
*/
public class RSAUtils {
/**
* 非对称密钥算法
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* 密钥长度,DH算法的默认密钥长度是1024
* 密钥长度必须是64的倍数,在512到65536位之间
*/
private static final int KEY_SIZE = 1024;
/**
* 公钥
*/
private static final String PUBLIC_KEY = "RSAPublicKey";
/**
* 私钥
*/
private static final String PRIVATE_KEY = "RSAPrivateKey";
/**
* 初始化密钥对
*
* @return Map 甲方密钥的Map
*/
public static Map<String, Object> initKey() throws Exception {
//实例化密钥生成器
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
//初始化密钥生成器
keyPairGenerator.initialize(KEY_SIZE);
//生成密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
//甲方公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
//甲方私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
//将密钥存储在map中
Map<String, Object> keyMap = new HashMap<String, Object>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* 私钥加密
*
* @param data 待加密数据
* @param key 密钥
* @return byte[] 加密数据
*/
public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {
//取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
//数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 公钥加密
*
* @param data 待加密数据
* @param key 密钥
* @return byte[] 加密数据
*/
public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {
//实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//初始化公钥
//密钥材料转换
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
//产生公钥
PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
//数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return cipher.doFinal(data);
}
/**
* 私钥解密
*
* @param data 待解密数据
* @param key 密钥
* @return byte[] 解密数据
*/
public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
//取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
//数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 公钥解密
*
* @param data 待解密数据
* @param key 密钥
* @return byte[] 解密数据
*/
public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {
//实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//初始化公钥
//密钥材料转换
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
//产生公钥
PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
//数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, pubKey);
return cipher.doFinal(data);
}
/**
* 取得私钥
*
* @param keyMap 密钥map
* @return byte[] 私钥
*/
public static byte[] getPrivateKey(Map<String, Object> keyMap) {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
/**
* 取得公钥
*
* @param keyMap 密钥map
* @return byte[] 公钥
*/
public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
}
五、接口设计
请求体类:
public class RequestData {
/**
* 序列号,全局唯一,用来标识一个请求
*/
private String seqNo;
/**
* 时间戳,毫秒
*/
private String timestamp;
/**
* 交易服务码
*/
private String transCode;
/**
* 数据签名
*/
private String signature;
/**
* 请求数据体,数据JSON串
*/
private String plain;
public String getSeqNo() {
return seqNo;
}
public void setSeqNo(String seqNo) {
this.seqNo = seqNo;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getTransCode() {
return transCode;
}
public void setTransCode(String transCode) {
this.transCode = transCode;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public String getPlain() {
return plain;
}
public void setPlain(String plain) {
this.plain = plain;
}
}
响应体类:
public class ResponseData {
/**
* 序列号,全局唯一,用来标识一个请求
*/
private String seqNo;
/**
* 时间戳,毫秒
*/
private Long timestamp;
/**
* 交易服务码
*/
private String transCode;
/**
* 数据签名
*/
private String signature;
/**
* 请求数据体
*/
private String plain;
public String getSeqNo() {
return seqNo;
}
public void setSeqNo(String seqNo) {
this.seqNo = seqNo;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
public String getTransCode() {
return transCode;
}
public void setTransCode(String transCode) {
this.transCode = transCode;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public String getPlain() {
return plain;
}
public void setPlain(String plain) {
this.plain = plain;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。