05_Java中的加解密之非对称加密
一.简介:
对称加密算法在加密和解密时使用的是同一个秘钥;而非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。
二.概念:
1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。
与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
三.工作原理:
如下图所示,甲乙之间使用非对称加密的方式完成了重要信息的安全传输。

非对称加密工作过程简要示意图
1、乙方生成一对密钥(公钥和私钥)并将公钥向甲方公开。
2、得到该公钥的甲方使用该密钥对机密信息进行加密后再发送给乙方。
3、乙方再用自己保存的另一把专用密钥(私钥)对加密后的信息进行解密。乙方只能用其专用密钥(私钥)解密由对应的公钥加密后的信息。
在传输过程中,即使攻击者截获了传输的密文,并得到了乙的公钥,也无法破解密文,因为只有乙的私钥才能解密密文。
同样,如果乙要回复加密信息给,那么需要甲先公布甲的公钥给乙用于加密,甲自己保存甲的私钥用于解密。
四.优缺点:
非对称加密与对称加密相比,其安全性更好:对称加密的通信双方使用相同的秘钥,如果一方的秘钥遭泄露,那么整个通信就会被破解。而非对称加密使用一对秘钥,一个用来加密,一个用来解密,而且公钥是公开的,秘钥是自己保存的,不需要像对称加密那样在通信之前要先同步秘钥。
非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。
五.常用算法:
在非对称加密中使用的主要算法有:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。
不同算法的实现机制不同,可参考对应算法的详细资料。
六.RSA非对称加密算法:
1⃣️.概述:
RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困 难!
因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。
关于RSA其它需要了解的知识,参考维基百科:http://zh.wikipedia.org/zh-cn/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95
在项目开发中对于一些比较敏感的信息需要对其进行加密处理,我们就可以使用RSA这种非对称加密算法来对数据进行加密处理。
七.RSA算法工具类:
public class RSAUtil {
//模
private static final String MODULUS = "100631058000714094813874361191853577129731636346684218206605779824931626830750623070803100189781211343851763275329364056640619755337779928985272486091431384128027213365372009648233171894708338213168824861061809490615593530405056055952622249066180336803996949444124622212096805545953751253607916170340397933039";
//公钥指数,2的16次方+1
private static final String PUB_KEY = "65537";
//私钥
private static final String PRI_KEY = "26900155715313643087786516528374548998821559381075740707715132776187148793016466508650068087107695523642202737697714709374658856733792614490943874205956727606674634563665154616758939576547663715234643273055658829482813503959459653708062875625210008961239643775661357655599312857249418610810177817213648575161";
//加密方法
public static byte[] encrypt(byte[] content) {
try{
//得到一个RSA算法
Cipher rsa = Cipher.getInstance("RSA");
//得到一个产生key的工厂
KeyFactory factory = KeyFactory.getInstance("RSA");
//根据提供的模和指数来产生一个公钥的说明(要求)
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(new BigInteger(MODULUS), new BigInteger(PUB_KEY));
//根据指定的要求产生对应的公钥
PublicKey publicKey = factory.generatePublic(publicKeySpec);
//利用公钥初始化rsa算法
rsa.init(Cipher.ENCRYPT_MODE, publicKey);
//进行加密
return rsa.doFinal(content);
}catch (NoSuchAlgorithmException | NoSuchPaddingException |
InvalidKeySpecException | InvalidKeyException |
BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
return null;
}
}
//解密方法
public static byte[] decrypt(byte[] content) {
try {
//得到RSA加密算法
Cipher rsa = Cipher.getInstance("RSA");
//得到一个密钥生成工厂
KeyFactory factory = KeyFactory.getInstance("RSA");
//根据模和私钥来生成一个密钥规格
RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(new BigInteger(MODULUS), new BigInteger(PRI_KEY));
//生成私钥
PrivateKey privateKey =factory.generatePrivate(privateKeySpec);
//用私钥初始化rsa算法
rsa.init(Cipher.DECRYPT_MODE, privateKey);
//进行最终的解密
return rsa.doFinal(content);
} catch (NoSuchAlgorithmException | NoSuchPaddingException |
InvalidKeySpecException | InvalidKeyException |
BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
}