目录
一、背景介绍
常见的渗透测试会将网站登录时密码使用明文传输视为风险。推荐使用国密算法或者RSA算法对密码进行加密传输。
二、工作原理
前端js使用公钥进行加密,后端使用私钥进行解密(后端可以是C#或java语言)。
三、实现步骤
(一)JS前端加密,.NET后端解密
1.生成RSA加密的公钥和私钥。
使用.net自带的类就可以生成公钥和私钥(详见附件代码),比如我们使用以下公钥和私钥:
公钥(C#使用):
<RSAKeyValue><Modulus>0aeb0hFOWt+2hyKvaYP1Dr0F1Q7g/aWC5P8ebDRUMdHZPhD636u4AVOkQHY42jUt7xPbGuWRlQFAv6USrHtEw3nkFcRWz+4NCfaINonZtCu6+K/WNCJ/EH/OdyX4XDIDgJ7PNLspVbZDKRXwV4/aN+u/8LOwIyewJDd8uL8T/Zbebm/7ywqZ07V9G/pxXJ2PREy9ruMS6jmFd6j9YcE6Z6YnsBpo8n814nlGLLrk9igC9z1pLxE55cuO5Ma38sptNnx3SGzZvEwmsYq40Ry7OyfD7EUBP18yrmVs5c19BY1/7yZSlD9TorM6aHSV8Fjxu9G1of00MFHt+WYzGMZy7Q==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
私钥(C#使用):
<RSAKeyValue><Modulus>0aeb0hFOWt+2hyKvaYP1Dr0F1Q7g/aWC5P8ebDRUMdHZPhD636u4AVOkQHY42jUt7xPbGuWRlQFAv6USrHtEw3nkFcRWz+4NCfaINonZtCu6+K/WNCJ/EH/OdyX4XDIDgJ7PNLspVbZDKRXwV4/aN+u/8LOwIyewJDd8uL8T/Zbebm/7ywqZ07V9G/pxXJ2PREy9ruMS6jmFd6j9YcE6Z6YnsBpo8n814nlGLLrk9igC9z1pLxE55cuO5Ma38sptNnx3SGzZvEwmsYq40Ry7OyfD7EUBP18yrmVs5c19BY1/7yZSlD9TorM6aHSV8Fjxu9G1of00MFHt+WYzGMZy7Q==</Modulus><Exponent>AQAB</Exponent><P>/3KZwPKJTD424QinIkumbgTnKy/hFGpUCZ/QsJd5G2vsdUoLf1oX936IWyej2SmcgAP5qEysTMMfuSYUuPcEby7HwqUtALRRjzoGS540JLIQ8Jw8HQC9FACJBqTydYW/Su8YorBcdKsH3/+kGwaoYhpNrsulddLBCIVHzgBtGk8=</P><Q>0huo+OeUfQum3k3EYhfa5sw0ldRj4znN0b8OFdNorMK2T90pBp0ZVmv0cKyqiJLrIw8Iwxly4NIuz5KtvwzdJhxxazTlDJl/+7XzmnDS0gjfeGAfsWekYKHQq08IOCPsqX7HRFUQ8UEXfN3kWyy9aeN3vk8TAI8RlT0Y4KpZnAM=</Q><DP>RXJJfJwzWWf8kXdBwOAiMfzhP+t3XI5/pFIvcSLtCNhxY32q3IeIxn8+4NFJCSv34RGzmN6nZQMTJ8nDjnmRWgy0wCUZs/xRxAd5WKt875D9a/x9l0DxJnPyzLyhMfQXim6wGuKpcApjTLF6UuKfenQ+NEwnAn42fnOFjuqsvp8=</DP><DQ>yj2bsTLgSFkt3y/GB5HkwGHxgAM3vuHGDs4zlaiwShMGf+tm8RnI6NnzKX3ajKm2skFncryNSoCmVGFg4tRUDro0Jjh8/VrHyZdDi/Zrx4aI7IrCFvanT+iSPkNNqxRRWnlQ/6JOM5svK58+jtCK5mDwwvvEU7Zi+18bEi6HINc=</DQ><InverseQ>tMxQlEUbCRiTmgO8DiirTtQc4QyfU6JSPeCBgCvV3O8nN7ub7P0+aJmo83Yn7mS88Kwt713TSMAb7iu9NP7dCeVR7mhbqTEze6E5kSS0tEDGyK0cB9otyTvzDs7wmvjli7vwfIND3Meqhby3XaDHKq/K10g/NlOpblcbIihnxi0=</InverseQ><D>HyfELRxrQ2/ZRQ2veYOliBIo6rdyUd8lq3gKAlRoaprfqKyHS3POPUw7rWSkIDEk6VFPDxksYDM2dwRF2SHcXxwe++kYaX/bqi5boZcspeyVtV0T/N1feokzmlsnJDQ+dv+ilRh3FQinxFRBShHTgNnkxRU+yIqeT1N7kky64MUki6/OC8p1Vvabed86ce5y9SlDcutZ7DmaCmMKdfdQlw5ctzFKYMP8A8seN0Ow4IBnn5fwnMrzb4aUwzfCdHNfmtN99wtBM+2+da5a04K+l7siJWLHLlG4yzt3BXapX+MNgyF+3FNv+uDQXFOoh8CuTCaxJIDfn+8lcXe9bUdCtQ==</D></RSAKeyValue>
这里需要注意下,.net生成的公钥和私钥都是xml格式的,js使用的公钥是需要pem格式的,需要将xml转换为pem PKCS1模式。
公钥(js使用):
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0aeb0hFOWt+2hyKvaYP1
Dr0F1Q7g/aWC5P8ebDRUMdHZPhD636u4AVOkQHY42jUt7xPbGuWRlQFAv6USrHtE
w3nkFcRWz+4NCfaINonZtCu6+K/WNCJ/EH/OdyX4XDIDgJ7PNLspVbZDKRXwV4/a
N+u/8LOwIyewJDd8uL8T/Zbebm/7ywqZ07V9G/pxXJ2PREy9ruMS6jmFd6j9YcE6
Z6YnsBpo8n814nlGLLrk9igC9z1pLxE55cuO5Ma38sptNnx3SGzZvEwmsYq40Ry7
OyfD7EUBP18yrmVs5c19BY1/7yZSlD9TorM6aHSV8Fjxu9G1of00MFHt+WYzGMZy
7QIDAQAB
-----END PUBLIC KEY-----
2.前端js加密。
前端加密将使用到JSEncrypt库,
详见这里
调用方式:
<html>
<head>RSA加密测试</head>
<script type="text/javascript" src="jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="RSA.js"></script>
<style type="text/css">
textarea {
width: 800px;
height: 120px;
outline: none;
border: 1px solid #ccc;
border-radius: 5px
}
</style>
<body>
<div>
<div>
公钥:<textarea type="text" id="publicKey"></textarea><br />
明文:<textarea type="text" id="input"></textarea><br />
<input type="button" value="加密" id="btnEncode" />
</div>
<div class="output">
密文:<textarea type="text" id="output"></textarea>
</div>
<script type="text/javascript">
$(function () {
$("#btnEncode").click(function () {
var publickey = $("#publicKey").val();
var input = $("#input").val();
publickey = publickey.replace("-----BEGIN PUBLIC KEY-----", "");
publickey = publickey.replace("-----END PUBLIC KEY-----", "");
publickey = publickey.replace(/\n/g, "");
publickey = publickey.trim();
var encrypt = new JSEncrypt();
encrypt.setPublicKey(publickey);
var result = encrypt.encrypt(input);
$("#output").val(result);
});
})
</script>
</div>
</body>
</html>
比如:使用上面的公钥(js使用)加密:
明文:
abcdefghighklmnopqrstuvwxyz1234567890!@#$%^&*()
得到密文:
SRPE/BUm/fk8uCyOjcvBYOiGWSpI3p2/Arndyx4m3GECVV4YG3t74zzw54zfvhO6IW8cZ86UGBqqpgeBOv6ajZz/696KtsLxI7VssgkwMSgY5i68V1mA6H98rw3wA/pJN0vOheKC3yAr1O3oyrOHX/KSGNPTu/HwkxgBPsvoXRR49yEx3G8rFL8w2H3j/zcgQiQXPR/g4Z2TTA6WqzIi2JlnwQQO5a381/OOy0Yuf+OQIrzD4DFYzbo3o+DVVfK27enigQVkjHf3dDmz37Yy4SB6/ftA5ThGQoOmAZ5kp/o51OjSr+DEUtbDuyIzQRIlono79se0AHraLUWXGUUBDw==
每次加密结果都不一样。
3.C#解密
将上面得到的密文,在后台用C#进行解密。注意:这里需要使用上面.net的xml格式的私钥。
/// <summary>
/// RSA私钥解密 加密文本
/// </summary>
/// <param name="encryptedText">加密的密文</param>
/// <param name="privateKey">私钥</param>
/// <returns>未加密数据的字符串</returns>
public string Decrypt(string encryptedText, string privateKey)
{
using (var rsa = new RSACryptoServiceProvider(2048))
{
try
{
rsa.FromXmlString(privateKey);
var encrypted = Convert.FromBase64String(encryptedText);
var bytes = rsa.Decrypt(encrypted, false);
return Encoding.UTF8.GetString(bytes);
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
}
至此,就完成了js加密,C#解密的功能。
(二)JS前端加密,Java后端解密
1.前端js加密
过程与上文对应章节一样,我们只需要在后端用Java对以下密文进行解密即可。
密文:
SRPE/BUm/fk8uCyOjcvBYOiGWSpI3p2/Arndyx4m3GECVV4YG3t74zzw54zfvhO6IW8cZ86UGBqqpgeBOv6ajZz/696KtsLxI7VssgkwMSgY5i68V1mA6H98rw3wA/pJN0vOheKC3yAr1O3oyrOHX/KSGNPTu/HwkxgBPsvoXRR49yEx3G8rFL8w2H3j/zcgQiQXPR/g4Z2TTA6WqzIi2JlnwQQO5a381/OOy0Yuf+OQIrzD4DFYzbo3o+DVVfK27enigQVkjHf3dDmz37Yy4SB6/ftA5ThGQoOmAZ5kp/o51OjSr+DEUtbDuyIzQRIlono79se0AHraLUWXGUUBDw==
2.Java解密
注意:使用Java解密时,私钥需是Pem PCSK8模式,否则无法正常解密。需要将.net的xml私钥进行转换,转换后的PCSK8私钥为:(转换工具见文末附件)
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDRp5vSEU5a37aH
Iq9pg/UOvQXVDuD9pYLk/x5sNFQx0dk+EPrfq7gBU6RAdjjaNS3vE9sa5ZGVAUC/
pRKse0TDeeQVxFbP7g0J9og2idm0K7r4r9Y0In8Qf853JfhcMgOAns80uylVtkMp
FfBXj9o367/ws7AjJ7AkN3y4vxP9lt5ub/vLCpnTtX0b+nFcnY9ETL2u4xLqOYV3
qP1hwTpnpiewGmjyfzXieUYsuuT2KAL3PWkvETnly47kxrfyym02fHdIbNm8TCax
irjRHLs7J8PsRQE/XzKuZWzlzX0FjX/vJlKUP1OiszpodJXwWPG70bWh/TQwUe35
ZjMYxnLtAgMBAAECggEAHyfELRxrQ2/ZRQ2veYOliBIo6rdyUd8lq3gKAlRoaprf
qKyHS3POPUw7rWSkIDEk6VFPDxksYDM2dwRF2SHcXxwe++kYaX/bqi5boZcspeyV
tV0T/N1feokzmlsnJDQ+dv+ilRh3FQinxFRBShHTgNnkxRU+yIqeT1N7kky64MUk
i6/OC8p1Vvabed86ce5y9SlDcutZ7DmaCmMKdfdQlw5ctzFKYMP8A8seN0Ow4IBn
n5fwnMrzb4aUwzfCdHNfmtN99wtBM+2+da5a04K+l7siJWLHLlG4yzt3BXapX+MN
gyF+3FNv+uDQXFOoh8CuTCaxJIDfn+8lcXe9bUdCtQKBgQD/cpnA8olMPjbhCKci
S6ZuBOcrL+EUalQJn9Cwl3kba+x1Sgt/Whf3fohbJ6PZKZyAA/moTKxMwx+5JhS4
9wRvLsfCpS0AtFGPOgZLnjQkshDwnDwdAL0UAIkGpPJ1hb9K7xiisFx0qwff/6Qb
BqhiGk2uy6V10sEIhUfOAG0aTwKBgQDSG6j455R9C6beTcRiF9rmzDSV1GPjOc3R
vw4V02iswrZP3SkGnRlWa/RwrKqIkusjDwjDGXLg0i7Pkq2/DN0mHHFrNOUMmX/7
tfOacNLSCN94YB+xZ6RgodCrTwg4I+ypfsdEVRDxQRd83eRbLL1p43e+TxMAjxGV
PRjgqlmcAwKBgEVySXycM1ln/JF3QcDgIjH84T/rd1yOf6RSL3Ei7QjYcWN9qtyH
iMZ/PuDRSQkr9+ERs5jep2UDEyfJw455kVoMtMAlGbP8UcQHeVirfO+Q/Wv8fZdA
8SZz8sy8oTH0F4pusBriqXAKY0yxelLin3p0PjRMJwJ+Nn5zhY7qrL6fAoGBAMo9
m7Ey4EhZLd8vxgeR5MBh8YADN77hxg7OM5WosEoTBn/rZvEZyOjZ8yl92oyptrJB
Z3K8jUqAplRhYOLUVA66NCY4fP1ax8mXQ4v2a8eGiOyKwhb2p0/okj5DTasUUVp5
UP+iTjObLyufPo7QiuZg8ML7xFO2YvtfGxIuhyDXAoGBALTMUJRFGwkYk5oDvA4o
q07UHOEMn1OiUj3ggYAr1dzvJze7m+z9PmiZqPN2J+5kvPCsLe9d00jAG+4rvTT+
3QnlUe5oW6kxM3uhOZEktLRAxsitHAfaLck78w7O8Jr45Yu78HyDQ9zHqoW8t12g
xyqvytdIPzZTqW5XGyIoZ8Yt
-----END PRIVATE KEY-----
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;
public class Main {
//注意:此处的私钥为PCKS8
private static final String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDRp5vSEU5a37aHIq9pg/UOvQXVDuD9pYLk/x5sNFQx0dk+EPrfq7gBU6RAdjjaNS3vE9sa5ZGVAUC/pRKse0TDeeQVxFbP7g0J9og2idm0K7r4r9Y0In8Qf853JfhcMgOAns80uylVtkMpFfBXj9o367/ws7AjJ7AkN3y4vxP9lt5ub/vLCpnTtX0b+nFcnY9ETL2u4xLqOYV3qP1hwTpnpiewGmjyfzXieUYsuuT2KAL3PWkvETnly47kxrfyym02fHdIbNm8TCaxirjRHLs7J8PsRQE/XzKuZWzlzX0FjX/vJlKUP1OiszpodJXwWPG70bWh/TQwUe35ZjMYxnLtAgMBAAECggEAHyfELRxrQ2/ZRQ2veYOliBIo6rdyUd8lq3gKAlRoaprfqKyHS3POPUw7rWSkIDEk6VFPDxksYDM2dwRF2SHcXxwe++kYaX/bqi5boZcspeyVtV0T/N1feokzmlsnJDQ+dv+ilRh3FQinxFRBShHTgNnkxRU+yIqeT1N7kky64MUki6/OC8p1Vvabed86ce5y9SlDcutZ7DmaCmMKdfdQlw5ctzFKYMP8A8seN0Ow4IBnn5fwnMrzb4aUwzfCdHNfmtN99wtBM+2+da5a04K+l7siJWLHLlG4yzt3BXapX+MNgyF+3FNv+uDQXFOoh8CuTCaxJIDfn+8lcXe9bUdCtQKBgQD/cpnA8olMPjbhCKciS6ZuBOcrL+EUalQJn9Cwl3kba+x1Sgt/Whf3fohbJ6PZKZyAA/moTKxMwx+5JhS49wRvLsfCpS0AtFGPOgZLnjQkshDwnDwdAL0UAIkGpPJ1hb9K7xiisFx0qwff/6QbBqhiGk2uy6V10sEIhUfOAG0aTwKBgQDSG6j455R9C6beTcRiF9rmzDSV1GPjOc3Rvw4V02iswrZP3SkGnRlWa/RwrKqIkusjDwjDGXLg0i7Pkq2/DN0mHHFrNOUMmX/7tfOacNLSCN94YB+xZ6RgodCrTwg4I+ypfsdEVRDxQRd83eRbLL1p43e+TxMAjxGVPRjgqlmcAwKBgEVySXycM1ln/JF3QcDgIjH84T/rd1yOf6RSL3Ei7QjYcWN9qtyHiMZ/PuDRSQkr9+ERs5jep2UDEyfJw455kVoMtMAlGbP8UcQHeVirfO+Q/Wv8fZdA8SZz8sy8oTH0F4pusBriqXAKY0yxelLin3p0PjRMJwJ+Nn5zhY7qrL6fAoGBAMo9m7Ey4EhZLd8vxgeR5MBh8YADN77hxg7OM5WosEoTBn/rZvEZyOjZ8yl92oyptrJBZ3K8jUqAplRhYOLUVA66NCY4fP1ax8mXQ4v2a8eGiOyKwhb2p0/okj5DTasUUVp5UP+iTjObLyufPo7QiuZg8ML7xFO2YvtfGxIuhyDXAoGBALTMUJRFGwkYk5oDvA4oq07UHOEMn1OiUj3ggYAr1dzvJze7m+z9PmiZqPN2J+5kvPCsLe9d00jAG+4rvTT+3QnlUe5oW6kxM3uhOZEktLRAxsitHAfaLck78w7O8Jr45Yu78HyDQ9zHqoW8t12gxyqvytdIPzZTqW5XGyIoZ8Yt";
public static void main(String[] args) throws Exception {
String cipherText = "SRPE/BUm/fk8uCyOjcvBYOiGWSpI3p2/Arndyx4m3GECVV4YG3t74zzw54zfvhO6IW8cZ86UGBqqpgeBOv6ajZz/696KtsLxI7VssgkwMSgY5i68V1mA6H98rw3wA/pJN0vOheKC3yAr1O3oyrOHX/KSGNPTu/HwkxgBPsvoXRR49yEx3G8rFL8w2H3j/zcgQiQXPR/g4Z2TTA6WqzIi2JlnwQQO5a381/OOy0Yuf+OQIrzD4DFYzbo3o+DVVfK27enigQVkjHf3dDmz37Yy4SB6/ftA5ThGQoOmAZ5kp/o51OjSr+DEUtbDuyIzQRIlono79se0AHraLUWXGUUBDw==";
String plainText = decryptByPrivateKey(privateKey, cipherText);
System.out.println(plainText);
}
// 私钥解密
public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(Base64.getDecoder().decode(text));
return new String(result);
}
}
运行效果:
至此,js加密,Java解密功能已完成。
(三)辅助工具
.NET RSA 加密解密辅助工具
用他就可以生成对应的公钥和私钥。源码下载