Usually we do a Web application when we need to login, login to enter the user name and login password, and, the user name and login password are clear text transmission, so it is possible to be intercepted halfway, especially in the Internet cafes and other occasions.
Here incidentally an episode, I used to have a company, the office decoration time to arrange the network is relatively small, not enough, so I and another colleague used a hub to share a network port, which led to a very interesting phenomenon: any of his network package I can catch, of course, my he can catch. Is this a big security risk? I might inadvertently leak my password.
Therefore, many security-demanding sites do not transmit passwords in clear text, they use HTTPS to ensure the security of the transfer process, HTTPS is a certificate to achieve, the certificate is from the certification authority, of course, you can also build a certificate yourself, but so that other people visit your site, you will still encounter trouble, Because the certificate you created is not within the trust of the user's browser, you also have to install your certificate on the user's browser to let the user's browser trust your website, many users do not know how to operate, even if they can operate, but also do not want to do; the other option is to request a certificate from an authoritative certification authority. But there's a certain threshold, and there's a fee, and it's not something we'd like to do.
So, I'm going to implement a password encryption transfer method myself.
RSA asymmetric encryption algorithm used here, symmetric encryption Maybe everyone is already familiar with, that is, encryption and decryption with the same key, without the key, can not be decrypted, this is symmetric encryption. In an asymmetric encryption algorithm, the key used for encryption is not the same as the key used to decrypt it: You use my public key to encrypt, I use my private key to decrypt it, and if you don't encrypt it with my public key, I can't decrypt it, and if I don't have a private key, I can't decrypt it.
I designed this login password encryption transfer method schematic diagram is as follows:
First, we'll walk through asymmetric cryptography:
static void Main (string[] args)
{
Used for cross-transfer between strings and byte[]
UTF8Encoding Utf8encoder = new UTF8Encoding ();
Generating a pair of public key keys
RSACryptoServiceProvider rsakeygenerator = new RSACryptoServiceProvider (1024);
String PublicKey = Rsakeygenerator.toxmlstring (false);
String Privatekey = Rsakeygenerator.toxmlstring (true);
Encrypt passwords with public keys
RSACryptoServiceProvider rsatoencrypt = new RSACryptoServiceProvider ();
Rsatoencrypt.fromxmlstring (PublicKey);
String strpassword = "@123#abc$";
Console.WriteLine ("The original password is: {0}", strpassword);
byte[] byencrypted = Rsatoencrypt.encrypt (utf8encoder. GetBytes (strpassword), false);
Console.Write ("Encoded bytes:");
foreach (Byte b in byencrypted)
{
Console.Write ("{0}", B.tostring ("X"));
}
Console.Write ("\ n");
Console.WriteLine ("The Encrypted code length is: {0}", byencrypted.length);
Decrypt
RSACryptoServiceProvider rsatodecrypt = new RSACryptoServiceProvider ();
Rsatodecrypt.fromxmlstring (Privatekey);
byte[] bydecrypted = Rsatodecrypt.decrypt (byencrypted, false);
String strdecryptedpwd = Utf8encoder. GetString (bydecrypted);
Console.WriteLine ("Decrypted Password is: {0}", strdecryptedpwd);
}
You can clearly see that the password is encrypted to 128-byte length of the ciphertext, why is fixed 128 bytes it? This is because our RSACryptoServiceProvider default generated key length is 1024, that is, 1024-bit encryption, so no matter how long the password you want to encrypt, it will generate a cipher length is 128 bytes, also because of this, the length of the password is limited, 1024-bit RSA algorithm, can only encrypt about 100 bytes of the length of the plaintext, to improve the length of the encrypted plaintext limit, you have to increase the length of the key, such as the key to 2048-bit, so that the length of the encrypted plaintext limit will become about 200 early such ... It's still too little! And this will bring a significant decrease in encryption speed, RSA is very slow ... Yes, compared to symmetric encryption with no length limit, this kind of asymmetric encryption can be very restrictive, even if it is 200 characters, what can be transmitted? --Password! This is enough, after the password is transmitted, we use symmetric encryption, so RSA is often used to "negotiate" a symmetric encryption key.
Next, the real challenge is to implement an RSA-compatible algorithm with. NET with JavaScript. Cryptography, for me really like the Heavenly Book general, every time I look at the head big, this job is not able to do their own, can only be found on the internet, it is quite laborious ah, find many JS RSA implementation, but all and. NET this set of things incompatible, finally or kungfu not bear, finally found a set. Not much to say, on the code:
<title>rsa Login test</title>
<script src= "Scripts/jquery-1.4.1.js" type= "Text/javascript" ></script>
<script src= "Scripts/jquery.md5.js" type= "Text/javascript" ></script>
<script src= "Scripts/bigint.js" type= "Text/javascript" ></script>
<script src= "Scripts/rsa.js" type= "Text/javascript" ></script>
<script src= "Scripts/barrett.js" type= "Text/javascript" ></script>
<script type= "Text/javascript" >
function Cmdencrypt () {
Setmaxdigits (129);
var key = new Rsakeypair ("<%=strPublicKeyExponent%>", "", "<%=strPublicKeyModulus%>");
var pwdmd5twice = $.md5 ($.MD5 ($ ("#txtPassword"). attr ("value"));
var pwdrtn = encryptedstring (key, Pwdmd5twice);
$ ("#encrypted_pwd"). attr ("value", PWDRTN);
$ ("#formLogin"). Submit ();
Return
}
</script>
<body>
<form action= "default.aspx" id= "Formlogin" method= "POST" >
<div>
<div>
User Name:
</div>
<div>
<input id= "txtUserName" name= "txtUserName" value= "<%=postbackUserName%>" type= "text" maxlength= "/>"
</div>
<div>
Password:
</div>
<div>
<input id= "txtpassword" type= "password" maxlength= "/>"
</div>
<div>
<input id= "Btnlogin" type= "button" value= "Login" onclick= "return Cmdencrypt ()"/>
</div>
</div>
<div>
<input type= "hidden" name= "Encrypted_pwd" id= "Encrypted_pwd"/>
</div>
</form>
<div>
<%=LoginResult%>
</div>
</body>
This is the client code, you can see, basically there is no server-side code,<%=postbackusername%> for echo input user name,<%=loginresult%> used to display the login results, <%= Strpublickeyexponent%> and <%=strPublicKeyModulus%> are used to tell the client RSA public key. Description of the required JavaScript file:
- JQuery.md5.js-Used to encrypt the password two times MD5, (I usually save the user password in the database is the result of two times MD5)
- Bigint.js-Used to generate a large integer; (This is required by the RSA algorithm)
- The main algorithm of Rsa.js-rsa;
- A supporting file required by the BARRETT.JS-RSA algorithm;
For cryptography, I almost know nothing, so there is no way to explain the principle of RSA algorithm, I'm sorry, I only knew how to use. About this line of code in javascript: "Setmaxdigits (129);" I'm not sure what that means, I just know that changing the parameter to a number less than 129 causes the client's JavaScript to execute into a dead loop. The server-side code is also simple:
protected void Page_Load (object sender, EventArgs e)
{
Loginresult = "";
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider ();
if (String.Compare (Request.requesttype, "get", true) ==0)
{
Save the private key in the session
session["Private_key"] = RSA. Toxmlstring (TRUE);
}
Else
{
BOOL Bloginsucceed = false;
Try
{
String strusername = request.form["txtUserName"];
Postbackusername = strUserName;
String strpwdtodecrypt = request.form["Encrypted_pwd"];
Rsa. Fromxmlstring (String) session["Private_key"]);
Byte[] result = RSA. Decrypt (Hexstringtobytes (Strpwdtodecrypt), false);
System.Text.ASCIIEncoding enc = new ASCIIEncoding ();
String strPwdMD5 = Enc. GetString (result);
if (string. Compare (strUserName, "user1", True) ==0 && string. Compare (strPwdMD5, "14e1b600b1fd579f47433b88e8d85291", true) ==0)
Bloginsucceed = true;
}
catch (Exception)
{
}
if (bloginsucceed)
Loginresult = "Login Successful";
Else
Loginresult = "Login Failed";
}
Convert the public key appropriately, ready to be sent to the client
RSAParameters parameter = RSA. Exportparameters (TRUE);
Strpublickeyexponent = bytestohexstring (parameter. Exponent);
Strpublickeymodulus = bytestohexstring (parameter. modulus);
}
User name "User1"
Password "123456"
Login Successful!
Grab the HTTP message to see the "password" of the post:
Such a "password" of the crack has become theoretically feasible. :)
Complete code download is available below (using the VS2010 development environment):
Http://files.cnblogs.com/guogangj/RSALoginTest.zip
Encrypted transmission of Web login password with RSA encryption