- 什么是非对称加密
非对称加密需要两个密钥:公钥 (publickey) 和私钥 (privatekey)。公钥和私钥是一对,如果用公钥对数据加密,那么只能用对应的私钥解密。如果用私钥对数据加密,只能用对应的公钥进行解密。因为加密和解密用的是不同的密钥,所以称为非对称加密。
非对称加密算法的保密性好,它消除了最终用户交换密钥的需要。但是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比对称加密慢上1000倍。
- 常见的非对称加密算法
- RSA算法:
RSA 是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。
- DSA算法
DSA (Digital Signature Algorithm) 是 Schnorr 和 ElGamal 签名算法的变种,被美国 NIST 作为 DSS (DigitalSignature Standard)。 DSA 是基于整数有限域离散对数难题的。
简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名,如果数据和签名不匹配则认为验证失败。数字签名的作用就是校验数据在传输过程中不被修改,数字签名,是单向加密的升级。
- ECC算法
椭圆加密算法(ECC)是一种公钥加密算法,最初由 Koblitz 和 Miller 两人于1985年提出,其数学基础是利用椭圆曲线上的有理点构成 Abel 加法群上椭圆离散对数的计算困难性。公钥密码体制根据其所依据的难题一般分为三类:大整数分解问题类、离散对数问题类、椭圆曲线类。有时也把椭圆曲线类归为离散对数类。
ECC 的主要优势是在某些情况下它比其他的方法使用更小的密钥 (比如 RSA),提供相当的或更高等级的安全。ECC 的另一个优势是可以定义群之间的双线性映射,基于 Weil 对或是 Tate 对;双线性映射已经在密码学中发现了大量的应用,例如基于身份的加密。不过一个缺点是加密和解密操作的实现比其他机制花费的时间长。
- DH算法
DH,全称为"Diffie-Hellman",它是一种确保共享 KEY 安全穿越不安全网络的方法,也就是常说的密钥一致协议。由公开密钥密码体制的奠基人 Diffie 和 Hellman 所提出的一种思想。简单的说就是允许两名用户在公开媒体上交换信息以生成"一致"的、可以共享的密钥。也就是由甲方产出一对密钥 (公钥、私钥),乙方依照甲方公钥产生乙方密钥对 (公钥、私钥)。
以此为基线,作为数据传输保密基础,同时双方使用同一种对称加密算法构建本地密钥 (SecretKey) 对数据加密。这样,在互通了本地密钥 (SecretKey) 算法后,甲乙双方公开自己的公钥,使用对方的公钥和刚才产生的私钥加密数据,同时可以使用对方的公钥和自己的私钥对数据解密。不单单是甲乙双方两方,可以扩展为多方共享数据通讯,这样就完成了网络交互数据的安全通讯。
- RSA算法的JAVA实现
public class RSAUtil {
public static Map<String, String> initKeyPair(){
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair keyPair = kpg.generateKeyPair();
PublicKey aPublic = keyPair.getPublic();
PrivateKey aPrivate = keyPair.getPrivate();
String publicKey = Base64Utils.encodeToString(aPublic.getEncoded());
String privateKey = Base64Utils.encodeToString(aPrivate.getEncoded());
Map<String, String> keyMap = new HashMap<>();
keyMap.put("publicKey", publicKey);
keyMap.put("privateKey", privateKey);
return keyMap;
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static String encrypt(String plainText, String key){
try {
PublicKey publicKey = KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(Base64Utils.decodeFromString(key)));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] bytes = cipher.doFinal(plainText.getBytes());
return Base64Utils.encodeToString(bytes);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static String decrypt(String cipherText, String key){
try{
PrivateKey privateKey = KeyFactory.getInstance("RSA")
.generatePrivate(new PKCS8EncodedKeySpec(Base64Utils.decodeFromString(key)));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] bytes = cipher.doFinal(Base64Utils.decodeFromString(cipherText));
return new String(bytes);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static String sign(String str, String key){
try{
PrivateKey privateKey = KeyFactory.getInstance("RSA")
.generatePrivate(new PKCS8EncodedKeySpec(Base64Utils.decodeFromString(key)));
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(str.getBytes());
return Base64Utils.encodeToString(signature.sign());
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
public static boolean verify(String str, String key, String sign){
try{
PublicKey publicKey = KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(Base64Utils.decodeFromString(key)));
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
signature.update(str.getBytes());
return signature.verify(Base64Utils.decodeFromString(sign));
}catch (Exception ex){
ex.printStackTrace();
return false;
}
}
public static void main(String[] args) {
Map<String, String> keyPair = RSAUtil.initKeyPair();
System.out.println("publicKey: " + keyPair.get("publicKey"));
System.out.println("privateKey: " + keyPair.get("privateKey"));
String plainText = "hello world";
String cipherText = RSAUtil.encrypt(plainText, keyPair.get("publicKey"));
System.out.println("cipherText: " + cipherText);
String decryptText = RSAUtil.decrypt(cipherText, keyPair.get("privateKey"));
System.out.println("decryptText: " + decryptText);
String sign = RSAUtil.sign(plainText, keyPair.get("privateKey"));
System.out.println("sign: " + sign);
boolean verify = RSAUtil.verify(plainText, keyPair.get("publicKey"), sign);
System.out.println("verify: " + verify);
}
}
输出: publicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKcpnfBJNdxdEOIbFDJG/LiIQvWmZyqwK/3uyAMFr7lBmMve6NTVhiCG+rrKQK4SkASDsUkVGqyl9NdreusP4xSPin7YFtuB9qiwUoBt9Mr6G1PCdFkHU41AGbUh8r+/NbjjEgeeDUHAfX2VKwTFITpsjfDxh0ykehePkPXKlrmwIDAQAB
privateKey: MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMpymd8Ek13F0Q4hsUMkb8uIhC9aZnKrAr/e7IAwWvuUGYy97o1NWGIIb6uspArhKQBIOxSRUarKX012t66w/jFI+KftgW24H2qLBSgG30yvobU8J0WQdTjUAZtSHyv781uOMSB54NQcB9fZUrBMUhOmyN8PGHTKR6F4+Q9cqWubAgMBAAECgYEAp4EU4Vr216LCK5AjC+vM+Dm3LTr+AyiNuNWpFxNrZDcQwMux4oY5d7uFMiVBAaN0+j/JamYmjUquefidWFQnrIRzqtCam9EJx5neRjCmhx1O+FRCpIdHRPNGR97tMEB+hj1RUm6+YxZaZk7oJNLe4Po5/ypbQXaPyZg8E+4xm+kCQQDwCpp8yLJG22ZoTzg4er4XfOyC0tpQFvbzzlGEfGVh/mjiq8dofl4pFCicobSEF1VI0dC3sFy8xpvDjpWiXsidAkEA1+grNclX+dRJ/X2IqlWojmYk705OYLQpLC4eN6Wtq8Gd837kA24TS0fi6swrMOlBA0EqX5we+YXzSqol1UBDlwJBALi5UD3rLNa+jMaFAFzmiFcG+fOLVBoCMjVZdv4fxN1urUSSsThG1yuBqecvwf1M/4K0hIx3mkZkCQarOZfknTkCQCfh4Sl8Wd3yUwCaUcZ1MD+tqqDx7BR88yYQFtDcr+oMR+sUw3XGvZWoX8hTkp7kV3gMb5Fdu3MIRVrDd12fE10CQQCtteQKyKnawfsTah2XV2syzdu+0Lpm+4qG6KSPXZ4kIGfeh/XES3vcjxTZSZqqLhUoAObDE45/65ek9SOkFF/P
cipherText: Zhm3QbT1Szp/Ca2wvPYiadoTOOt4HSiiGzHODVzsLEYVxSUusYCGx1plMzTUmo1FpyT5I0gjnCQDK9xj0hwVFS89FG+UE0rFIaLHlwqjdSxZ7MrFhC1minTTjHd3pusVBTNgKmyif2y935lM7b4yZIFxzRQcWwqk1lZdgh4lBow=
decryptText: hello world
sign: vcjrtvvGi98Qv2P4khsHxGp8AENK3cdPyOUWyUI3Me400FERIh0Bg9Ps1tfNasbSAVN8ZZgPJa3KIReDVdj/5Q57Yyulpo83XjeP8uSoQ3+axWBi53sKezN0wZxnayTgkbW6Caox9w6TFaPetD+62d6k2F0EAueOgUk87mXHnjk=
verify: true
- openssl工具生成rsa密钥并对文件进行加解密
生成私钥:
openssl genrsa -out private.pem
生成公钥:
openssl rsa -in private.pem -out public.pem -pubout
公钥加密:
openssl pkeyutl -encrypt -in hello.txt -inkey public.pem -pubin -out hello.en
私钥解密:
openssl pkeyutl -decrypt -in hello.en -inkey private.pem -out hello.de
私钥签名:
openssl dgst -sha256 -sign private.pem -out sign.txt hello.txt
公钥验签:
openssl dgst -verify public.pem -sha256 -signature sign.txt hello.txt Verified OK