首先解释一下 web 中的流程:
前端会有专门的方法利用对应的公/私钥 对需要加密的内容进行加密,后台得到加密后的内容后 利用对应的公/私钥 进行解密 或相应操作。
非对称性加密:
解决浏览器传输过程中 明文传输易被窃取的情况。
算法生成两个密匙 公钥 -私钥; 公钥是的可以对外公开的,私钥是自己保留的。
避免频繁交换秘钥带来的不便。
RSA算法一次生成 一对秘钥,用其中一个加密 则可以使用另一个解密。
(PS:也就是说会有2种情况,1.公钥加密-私钥解密 , 2私钥加密-公钥解密)
踩过的坑:
每次生成的一对秘钥 头尾一致,身子不是一致的,请注意。
常规的网上给出的RSA加密例子都是从头到尾 加密解密过一遍,但是! 你要是自己尝试分离的话,请注意 :
- 1 生成秘钥的语句执行一次就好。保留住你的公私钥。然后直接去愉快的尝试,不要反复生成公私密钥 拿不匹配秘钥去解密文,必报错javax.crypto.BadPaddingException: Decryption error。
- 2 类型转换,你保存的是 String类型的key 普通分离出来的方法需要传入RSAPublicKey/RSAPrivateKey类型的参数,然后去尝试类型转换,头疼。
- 3 前端传到后台的密文 “+” 号可能被替换成 “ 空格”,
谨以此文纪念我逝去的一个早上。
常见的优快云上的加密解密不分离的例子:来自https://blog.youkuaiyun.com/jijianshuai/article/details/80582187
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;
/**
* 非对称加密 唯一广泛接受并实现 数据加密&数字签名 公钥加密、私钥解密 私钥加密、公钥解密
*
* @author jjs
*
*/
public class RSADemo {
private static String src = "infcn";
private static RSAPublicKey rsaPublicKey;
private static RSAPrivateKey rsaPrivateKey;
static {
// 1、初始化密钥
KeyPairGenerator keyPairGenerator;
try {
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);// 64的整倍数
KeyPair keyPair = keyPairGenerator.generateKeyPair();
rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
System.out.println("Public Key : " + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
System.out.println("Private Key : " + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 公钥加密,私钥解密
* @author jijs
*/
public static void pubEn2PriDe() {
//公钥加密
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("公钥加密,私钥解密 --加密: " + Base64.encodeBase64String(result));
//私钥解密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
result = cipher.doFinal(result);
System.out.println("公钥加密,私钥解密 --解密: " + new String(result));
}
/**
* 私钥加密,公钥解密
* @author jijs
*/
public static void priEn2PubDe() {
//私钥加密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("私钥加密,公钥解密 --加密 : " + Base64.encodeBase64String(result));
//公钥解密
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
result = cipher.doFinal(result);
System.out.println("私钥加密,公钥解密 --解密: " + new String(result));
}
public static void main(String[] args) {
pubEn2PriDe(); //公钥加密,私钥解密
priEn2PubDe(); //私钥加密,公钥解密
}
}
想快速使用的话建议使用别人封装好的。
https://www.jianshu.com/p/bdf59b6a01ab