使用非对称加密算法加密登录
面临的问题
明文密码登录
- 被抓包后泄露用户密码
- 攻击者模拟登录
MD5/BASE64 加密登录
- 可通过抓包获取加密后的密文,进而模拟登录
解决方案
对称加密与非对称加密
对称加密
需要对加密和解密使用相同密钥的加密算法。由于其速度快,对称性加密通常在消息发送方需要加密大量数据时使用。对称性加密也称为密钥加密。
所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密。密钥是控制加密及解密过程的指令。算法是一组规则,规定如何进行加密和解密。
因此加密的安全性不仅取决于加密算法本身,密钥管理的安全性更是重要。因为加密和解密都使用同一个密钥,如何把密钥安全地传递到解密者手上就成了必须要解决的问题。
常用的对称加密算法:
1、DES(Data Encryption Standard):数据加密标准(美国发布的,我国三级等保不承认),速度较快,适用于加密大量数据的场合;
2、3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高;
3、AES(Advanced Encryption Standard):高级加密标准(美国发布的,我国三级等保不承认),是下一代的加密算法标准,速度快,安全级别高,支持128、192、256、512位密钥的加密;
算法特征
1、加密方和解密方使用同一个密钥;
2、加密解密的速度比较快,适合数据比较长时的使用;
3、密钥传输的过程不安全,且容易被破解,密钥管理也比较麻烦;
加密工具
1、openssl,它使用了libcrypto加密库、libssl库即TLS/SSL协议的实现库等。TLS/SSL是基于会话的、实现了身份认证、数据机密性和会话完整性的TLS/SSL库。
2、gpg ,常用来对文件和邮件进行加密。
优缺点
对称加密算法的优点是算法公开、计算量小、加密速度快、加密效率高。
对称加密算法的缺点是在数据传送前,发送方和接收方必须商定好秘钥,然后使双方都能保存好秘钥。其次如果一方的秘钥被泄露,那么加密信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的独一秘钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。
非对称加密
与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
非对称密码体制也叫公钥加密技术,该技术是针对私钥密码体制(对称加密算法)的缺陷被提出来的。与对称密码体制不同,公钥加密系统中,加密和解密是相对独立的,加密和解密会使用两把不同的密钥,加密密钥(公开密钥)向公众公开,谁都可以使用,解密密钥(秘密密钥)只有解密人自己知道,非法使用者根据公开的加密密钥无法推算出解密密钥,这样就大大加强了信息保护的力度。公钥密码体制不仅解决了密钥分配的问题,它还为签名和认证提供了手段。
1、乙方生成一对密钥(公钥和私钥)并将公钥向其它方公开。
2、得到该公钥的甲方使用该密钥对机密信息进行加密后再发送给乙方。
3、乙方再用自己保存的另一把专用密钥(私钥)对加密后的信息进行解密。乙方只能用其专用密钥(私钥)解密由对应的公钥加密后的信息。
在传输过程中,即使攻击者截获了传输的密文,并得到了乙的公钥,也无法破解密文,因为只有乙的私钥才能解密密文。
同样,如果乙要回复加密信息给甲,那么需要甲先公布甲的公钥给乙用于加密,甲自己保存甲的私钥用于解密。
原理:
欧拉定理:若n,a为正整数,且n,a互质,如果算出不大于n且与n互质的正整数个数φ(n)(读音 /faɪ/),那么a的φ(n)次方除于n的余数为1.
用公式表明即为:
以3和5两个数为例,假设a=3,n=5,那么不大于5且与5互质的数有1,2,3,4四个数字,那么φ(n)=4,根据公式就可以得出来3的4次方81除于5余数是1.
延伸—求7的222次方的个位数字:
其实这道题也就算要计算7的222次方除以10的余数。因为7和10是互质数且φ(10)=4,那么根据欧拉定理便有7的4次方(2401)除以10余数是1。当然无论多少个个位数为1的数相乘其个位数字仍然是1,所以整个题目就转变成算7的二次方了结果是9.
RSA算法的基本步骤可以分为以下几步:(以假设A和B通信为例子)
1,A首先选择两个质数,假设这里选择,61和53,实际选择的质数都相当大
2,将两个数相乘得到3233,然后计算出不大于3233且和3233互质的数,根据欧拉函数的定义可以算出是φ(3233)=(61-1)*(53-1)=3120
3,寻找一个不大于3120的质数e,这里选择e=17,然后计算摸反元素,也就是计算一个整数d,是的e和d相乘的数除以3120余数为1。由于e=17,所以这一步可以写出以下等式:17*d = 3120k+1.由于K的值我们不关心,所以也可以写成17d+3120k=1.于是通过解这个二元一次不定方程就可以算出d来。通过辗转相除法计算出一组解为(2753,-15).此时加密公钥为(3233,17),私钥为(3233,2753).
4,真正个通信此时开始,假设A要把信息65发给B,实际上首先计算下式中的C:6517 ≡ C(mod 3233),这里计算出的C=2790。然后A将2790发给B
5,当B收到2790后解密,解密实际上就是计算下面的C:27902753 ≡ C (mod 3233),算出来就是65.此时加密解密的过程就结束了。
常用的对称加密算法:
RSA:RSA算法是第一个能同时用于加密和数字签名的算法,在公开密钥加密和电子商业中RSA被广泛使用;
SM2/3/4/9:国家密码管理局发布,国家等保三级承认的唯一加密算法;
优缺点:
其主要的优点是:
(1)密钥分配简单。
(2)密钥的保存量少。
(3)可以满足互不相识的人之间进行私人谈话时的保密性要求。
(4)可以完成数字签名和数字鉴别。
但在实际应用中,公钥密码体制并没有完全取代私钥密码体制,这是因为公钥密码体制在应用中存在以下几个缺点:
(1)公钥密码是对大数进行操作,计算量特别浩大,速度远比不上私钥密码体制。
在登录过程中的使用
演示一个完整的登录示例:
引用自:https://blog.csdn.net/waterlordvip/article/details/51249454
1、在浏览器端请求公钥,使用js加密登录数据。
<script type='text/javascript' src="js/jquery/rsa/jsbn.js"></script>
<script type='text/javascript' src="js/jquery/rsa/prng4.js"></script>
<script type='text/javascript' src="js/jquery/rsa/rng.js"></script>
<script type='text/javascript' src="js/jquery/rsa/rsa.js"></script>
<script type='text/javascript' src="js/jquery/rsa/base64.js"></script>
var modulus,exponent;
jQuery(function(){
jQuery.getJSON("getPublicKey.do",function(data){
modulus = data["modulus"];
exponent = data["exponent"];
});
});
function dl() {
var password = jQuery("#password").val();
if (jQuery("#userName") == "" || password == "") {
showAlert("用户名和密码不能为空!");
return false;
}
var rsaKey = new RSAKey();
rsaKey.setPublic(b64tohex(modulus), b64tohex(exponent));
var enPassword = hex2b64(rsaKey.encrypt(password));
jQuery("#password").val(enPassword);
jQuery("#loginForm").submit();
}
java示例返回公钥,RAS工具类生成密钥对(返回公钥、将私钥存储于session中)
/*****生成密钥对,返回公钥、私钥放session********/
public RSAPublicKey generateKey(HttpServletRequest request) {
KeyPair keyPair = RSAUtils.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
HttpSession session = request.getSession();
session.setAttribute(PRIVATE_KEY_ATTRIBUTE_NAME, privateKey);
return publicKey;
}
/**
* 获取加密登录公共key
* @return
*/
public String getPublicKey(){
RSALoginService rsaLoginService = new RSALoginService();
RSAPublicKey publicKey = rsaLoginService.generateKey(request);
byte[] modulus = publicKey.getModulus().toByteArray();
byte[] exponent = publicKey.getPublicExponent().toByteArray();
Map<String,String> map = new HashMap<String,String>();
map.put("modulus", org.apache.commons.codec.binary.Base64.encodeBase64String(modulus));
map.put("exponent", org.apache.commons.codec.binary.Base64.encodeBase64String(exponent));
getValueStack().set(DATA, map);
return DATA;
}
2、登录解密
String enPassword = request.getParameter("password");
RSALoginService rsaLoginService = new RSALoginService();
String password = rsaLoginService.decryptParameter(enPassword, request);
rsaLoginService.removePrivateKey(request);
/*********解密字符串*****************/
public String decryptParameter(String parameter, HttpServletRequest request) {
if (parameter != null) {
HttpSession session = request.getSession();
RSAPrivateKey privateKey = (RSAPrivateKey) session.getAttribute(PRIVATE_KEY_ATTRIBUTE_NAME);
if (privateKey != null && StringUtils.isNotNull(parameter)) {
return RSAUtils.decrypt(privateKey, parameter);
}
}
return null;
}
这样就完成了登录表单提交前的加密,并且在控制层解密请求数据。
点击下载示例