在公司当前版本的中间件通信框架中,为了防止非授权第三方和到期客户端的连接,我们通过AES和RSA两种方式的加解密策略进行认证。对于非对称RSA加解密,因为其性能耗费较大,一般仅用于认证连接,不会用于每次报文本身的加解密(这一般使用AES/DES加密),对于较为安全的支付通道,则一般是约定定期交换加解密密钥,交换过程本身的报文则是通过RSA进行加解密的。这样就在单纯的对称加密的基础上提供了更好的保障,只要签名复杂,定期的更新足以使得破坏的成本高昂到超过破解的成本。
一般来说,公钥会发布给客户端,客户端勇气加密报文。私钥则用于解密报文。在java 实现的RSA中,可参考如下:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import org.apache.commons.codec.binary.Base64; public class RSAUtils { /** * 生成公钥和私钥, 一般一次性生成, 存储在文件中进行分发和使用 */ public static void generateKey() { try { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(1024); KeyPair kp = kpg.genKeyPair(); PublicKey pbkey = kp.getPublic(); PrivateKey prkey = kp.getPrivate(); // 保存公钥 FileOutputStream f1 = new FileOutputStream("d:/pubkey.dat"); ObjectOutputStream b1 = new ObjectOutputStream(f1); b1.writeObject(pbkey); // 保存私钥 FileOutputStream f2 = new FileOutputStream("d:/privatekey.dat"); ObjectOutputStream b2 = new ObjectOutputStream(f2); b2.writeObject(prkey); } catch (Exception e) { } } /** * 公钥加密, 一般调用者传递明文, 从本地存储读取公钥进行加密 * @param plainTxt * @return * @throws Exception */ public static String pubEncrypt(String plainTxt) throws Exception { String s = Base64.encodeBase64String(plainTxt.getBytes("UTF-8")); // 获取公钥及参数e,n FileInputStream f = new FileInputStream("d:/pubkey.dat"); ObjectInputStream b = new ObjectInputStream(f); RSAPublicKey pbk = (RSAPublicKey) b.readObject(); BigInteger e = pbk.getPublicExponent(); BigInteger n = pbk.getModulus(); // 获取明文m byte ptext[] = s.getBytes("UTF-8"); BigInteger m = new BigInteger(ptext); // 计算密文c BigInteger c = m.modPow(e, n); // 保存密文 String ciperTxt = c.toString(); return ciperTxt; } /** * 私钥解密, 一般调用者传递密文, 从本地存储读取私钥进行解密 * @param ciperTxt * @return * @throws Exception */ public static String privDecrypt(String ciperTxt) throws Exception { BigInteger c = new BigInteger(ciperTxt); // 读取私钥 FileInputStream f = new FileInputStream("d:/privatekey.dat"); ObjectInputStream b = new ObjectInputStream(f); RSAPrivateKey prk = (RSAPrivateKey) b.readObject(); BigInteger d = prk.getPrivateExponent(); // 获取私钥参数及解密 BigInteger n = prk.getModulus(); BigInteger m = c.modPow(d, n); // 显示解密结果 byte[] mt = m.toByteArray(); String plainTxt = new String(Base64.decodeBase64(mt),"UTF-8"); return plainTxt; } public static void main(String args[]) { try { // generateKey(); String ciperTxt = pubEncrypt("测试大中华123区"); System.out.println("公钥加密密文:" + ciperTxt); System.out.println("私钥解密:" + privDecrypt(ciperTxt)); } catch (Exception e) { System.out.println(e.toString()); } } }
PS:关于哪个加密、哪个解密的问题,记住以下原则即可(这个是从合理性角度,不是纯技术角度):
既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。
时间: 2024-10-05 01:34:27