一、数据交互
咱们本人的零碎须要和第三方零碎进行对接,实现业务的齐全系统化、自动化操作等,零碎对接其实就是数据的对接,有数据的传输那么就得思考数据的平安交互,个别须要咱们做到两点:数据加密和数据签名。数据加密是为了解决明文裸露的问题,数据签名是为了确保数据完整性和防篡改。
二、非对称加密
非对称加密算法存在两个密钥,一个称之为公钥,一个称之为私钥,这两个密钥齐全不同但又齐全匹配。只有应用匹配的一对公钥和私钥,能力实现对明文的加密和解密过程。常见的非对称加密有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; }}