上一篇讲到了对称加密,本文主要讲非对称加密。
非对称加密就是指加密解密使用不同的密钥。
经常有人问我公钥私钥到底哪个用来加密哪个用来解密,哪个用来加签,哪个验签。
今天就讲一个比较通俗易懂的方法:
你只要去想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。
RSA加密解密类静态常量
public static final String KEY_ALGORTHM="RSA";//
public static final String SIGNATURE_ALGORITHM="MD5withRSA";
public static final String PUBLIC_KEY = "RSAPublicKey";//公钥
public static final String PRIVATE_KEY = "RSAPrivateKey";//私钥
/**
* BASE64解密
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptBASE64(String key) throws Exception{
return (new BASE64Decoder()).decodeBuffer(key);
}
/**
* BASE64加密
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64(byte[] key)throws Exception{
return (new BASE64Encoder()).encodeBuffer(key);
}
/**
* 初始化密钥
* @return
* @throws Exception
*/
public static Map<String,Object> initKey()throws Exception{
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
//公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
//私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String,Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* 取得公钥,并转化为String类型
* @param keyMap
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Object> keyMap)throws Exception{
Key key = (Key) keyMap.get(PUBLIC_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 取得私钥,并转化为String类型
* @param keyMap
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{
Key key = (Key) keyMap.get(PRIVATE_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 用公钥加密
* @param data 加密数据
* @param key 密钥
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{
//对公钥解密
byte[] keyBytes = decryptBASE64(key);
//取公钥
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
//对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 用私钥解密
* @param data 加密数据
* @param key 密钥
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{
//对私钥解密
byte[] keyBytes = decryptBASE64(key);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 用私钥对信息生成数字签名
* @param data //加密数据
* @param privateKey //私钥
* @return
* @throws Exception
*/
public static String sign(byte[] data,String privateKey)throws Exception{
//解密私钥
byte[] keyBytes = decryptBASE64(privateKey);
//构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
//指定加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
//取私钥匙对象
PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//用私钥对信息生成数字签名
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateKey2);
signature.update(data);
return encryptBASE64(signature.sign());
}
/**
* 校验数字签名
* @param data 加密数据
* @param publicKey 公钥
* @param sign 数字签名
* @return
* @throws Exception
*/
public static boolean verify(byte[] data,String publicKey,String sign)throws Exception{
//解密公钥
byte[] keyBytes = decryptBASE64(publicKey);
//构造X509EncodedKeySpec对象
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
//指定加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
//取公钥匙对象
PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicKey2);
signature.update(data);
//验证签名是否正常
return signature.verify(decryptBASE64(sign));
}
加密解密,加签验签测试
public static void main(String[] args) {
String content = "{name:tansen,age:25,sex:man,address:湖南省常德市澧县}";
//1.初始化公钥私钥
String rsaPublicKey = null;
String rsaPrivateKey = null;
try {
Map<String, Object> map = RSA.initKey();
rsaPublicKey = getPublicKey(map);
rsaPrivateKey = getPrivateKey(map);
} catch (Exception e) {
e.printStackTrace();
}
//2.使用公钥加密
try {
System.out.println("加密前=="+content);
byte[] result_m = RSA.encryptByPublicKey(content.getBytes(), rsaPublicKey);
content = encryptBASE64(result_m);
System.out.println("加密后=="+content);
} catch (Exception e) {
e.printStackTrace();
}
//3.私钥解密
try {
byte[] b1 = decryptBASE64(content);
byte[] b2 = decryptByPrivateKey(b1, rsaPrivateKey);
content = new String(b2);
System.out.println("解密后=="+content);
} catch (Exception e) {
e.printStackTrace();
}
//4.私钥加签
String sign = null;
try {
sign = sign(content.getBytes(), rsaPrivateKey);
System.out.println("签名=="+sign);
} catch (Exception e) {
e.printStackTrace();
}
//5.公钥验签
try {
boolean flag = verify(content.getBytes(), rsaPublicKey, sign);
System.out.println("延签结果=="+flag);
} catch (Exception e) {
e.printStackTrace();
}
}
结果
加密前=={name:tansen,age:25,sex:man,address:湖南省常德市澧县}
加密后==rDed52QWJ3DNZTUAxqLuO5Ok6vTE7RNQwkHk/GJxIN8yXNiB2dE
dqvjMPwzVR97uAx9hjng+QpMRE9JGFRp9YFE+PumA0m+bseLV+x7O2xJ3hGLqGdyQi18zB7eiTmBQoDD2LljMGeMn5EgtXntE9knx1WYPIKS2Uvh17JRQq1c=
解密后=={name:tansen,age:25,sex:man,address:湖南省常德市澧县}
签名==d5CkI95rVRwHxwIilrAj1O2nLq4mLrKwMbGGZojTQdS/jXZJkiB1bS
R7dxCwLX+WqqJnP7soES4octa5TebjcloMRQXrpY3ePKhvAWxBzF60MUlWiPLib8SX0HQzeWxsf9ifi9wASus+ICNqF7udVRKLWZctYqHe3TjCMURV22c=
延签结果==true