My Java Web login RSA encryption

Source: Internet
Author: User
Tags md5 digest ming modulus jboss asymmetric encryption

has not been concerned about the Web application login password encryption problem, these two days with AppScan scanning application, the most serious problem is this, prompted me to send a password in clear text. This is really unsafe, and probably thought about it before, but no specific research, all did nothing, this time to take this opportunity to finally fix the problem.

First of all, there are many posts in the client with JS to the password MD5 digest, and then submitted to the login processing URL. This practice is nothing more than self-deception, even if others catch the bag can't catch your original password, with this MD5 password can be simulated login system, nothing more secure a little bit, that is, directly through the login page can not directly enter the user name password to log in, but people's means you know what? It's not too difficult to use a program to simulate landing.

HTTPS is also a choice, but for general applications, but also need to generate keys and the like, but also need to give those certification bodies to sign, trouble not to say, silver is necessary. If the user installs the certificate, the application system can also, the website is not very realistic, after all, not all users have so high level of computer operation, even if there is a feeling so troublesome, it is not necessarily to operate.

This time to concentrate on the search for 1 hours, or feel that asymmetric encryption is more reliable, there are some RSA encryption articles worth learning from. I pay tribute to the author of these articles, I can refer to more than one article, because there are a lot of questions. This is the end of the crap, tell me how I handle it.

The process of encrypting and decrypting:

A) in login.jsp, add a piece of Java code, generate the public and private keys, the private key object is stored in the session, the public key, I put exponent, modulus in the request attribute, and output to the JS encryption function on the page, Used for password encryption. Using the Security.js feature to encrypt

var key = new Rsautils.getkeypair ("${publickeyexponent}", "", "${publickeymodulus}");       var encrypedpwd = rsautils.encryptedstring (Key,password);

b) Call the login JS function when the Submit button is clicked. This function is to use the Ajax method to submit the user name, password to the login processing URL. Before committing, use the public key exponent in step a, and modulus to encrypt the password before sending it to the server side.

c) in the login processing URL, (I am login.action), get the private key object from the session, decrypt the password. The next steps are the same, to the library to inquire about the kind of, do not elaborate.

Let's talk about the steps I've dealt with and the major problems I've encountered.


1. This asymmetric encryption can only be used by RSA to make password cracking a mere "theoretical" possibility. So decided to use this encryption method.

2. Find the appropriate client-side JavaScript encryption code. I do not understand this, only to find. Finally found the security.js. Some of the online articles with 3 files, Bigint.js,rsa.js also have a what again, barrett.js these 3 to realize, started I used. But with the service can not match (my own problem), the results later found this security.js, in fact, the 3 JS are encapsulated into 1 inside, and the last modified time is 2010, relatively new, use this bar. The 3 JS files should also be available.

3. Generate the public key and private key on the server side, this originally wanted to be simple, the code can refer to a lot. But I have a lot of problems, decryption is always wrong.

Issue one: In login.jsp, the exponent of the public key, and the modulus output format problem

The beginning is always what: the length is too large, you must start with an exception of 0. I thought it was probably JS encryption and pure Java encryption where the difference is caused. Later found that the original is my public key exponent, and the modulus output directly with the ToString () method, in fact should be used with ToString (16), with 16 output, because in Security.js, the

Rsautils.getkeypair (Publickeyexponent, "", ${publickeymodulus), inside the method, is obviously converted from a 16 binary. This should be done after the change:

String publickeyexponent = Publickey.getpublicexponent (). toString (16);//16 binary    string publickeymodulus = Publickey.getmodulus (). toString (16),//16    request.setattribute ("Publickeyexponent", publickeyexponent);    Request.setattribute ("Publickeymodulus", Publickeymodulus);

Question two: There is something padding, such as the exception, is the RSA algorithm in front of the problem, the reason when JS and Java default Java RSA algorithm inconsistent.

After analysis, with RSA other provider can solve this problem, so in the code to generate password pair, use the

Keypairgenerator Keypairgen = keypairgenerator.getinstance ("RSA", new Org.bouncycastle.jce.provider.BouncyCastleProvider ());  

This way of completion and JS is the same.

Question three: provider's authentication problem

Just used, feeling can pass, but immediately is an anomaly: JCE cannot authenticate the provider BC. The meaning is good to understand, is not certified. How do I get him through? I added the following code in the Javahome\jre\lib\security\java.security file that ran the application server:

Security.provider.11=org.bouncycastle.jce.provider.bouncycastleprovider
11 is the serial number, along with its original addition can be.
Feel OK, start a look, or that question. The problem was that I appeared on the jboss-eap-6.2. Other application servers may not have this problem.

So check JBoss data, finally found, said is in JBoss, can not let this provider jar package in the application of the LIB, need to use the global, if using MAVEN, it must let this package scope is provided. Need to be configured under eap6.2:

Under Jboss_home/modules, set up the directory Org\bouncycastle\main, in the main directory, put Bcprov-jdk16-1.46.jar, and add the module's configuration file Module.xml, the contents are as follows:

<?xml version= "1.0" encoding= "UTF-8"? ><module xmlns= "urn:jboss:module:1.1" name= "Org.bouncycastle" >    <resources>        <resource-root path= "Bcprov-jdk16-1.46.jar"/>    </resources>    < dependencies>        <module name= "Javax.api" slot= "main" export= "true"/>    </dependencies></ Module>
Meta-inf\manifest also needs to be in the Web App. MF added to the Dependencies:org.bouncycastle

I am a MAVEN project and need to configure POM:

<plugin>            <artifactId>maven-war-plugin</artifactId>            <version>${ version.war.plugin}</version>            <configuration>               <!--Java EE 6 doesn ' t require Web. XML, Maven Needs to catch up! -               <failOnMissingWebXml>true</failOnMissingWebXml>               <version>3.0</version>               <archive>            <manifestentries><dependencies>org.bouncycastle</dependencies></ manifestentries></archive>            </configuration>                     </plugin>

Is mainly the configuration of the archive node, so the contents of MANIFEST.MF will change after packing.

How can I complete the attachment without transmitting it? Paste the Code bar:

login.jsp

<script src= "Js/lib/security.js" type= "Text/javascript" ></script><script type= "Text/javascript"      ><%hashmap<string, object> map = Rsautils.getkeys ();      Generate the public and private keys rsapublickey PublicKey = (rsapublickey) map.get ("publicly");        Rsaprivatekey Privatekey = (rsaprivatekey) map.get ("private"); Session.setattribute ("Privatekey", privatekey);//The private key is saved in session for decryption//Public key information is saved on the page for encrypting String publickeyexponent =    Publickey.getpublicexponent (). toString (16);    String publickeymodulus = Publickey.getmodulus (). toString (16);    Request.setattribute ("Publickeyexponent", publickeyexponent); Request.setattribute ("Publickeymodulus", Publickeymodulus);%> function login () {//login var username = $ ("       #txtUsername "). Val ();       var password = $ ("#txtPassword"). Val ();       var Randcode = $ ("#txtRandCode"). Val ();       var remembermeobj = document.getElementById ("Cbrememberme"); var rem = remembermeobj.checked?              "1": ""; RsautIls.setmaxdigits (200);       Setmaxdigits (256);       var key = new Rsautils.getkeypair ("${publickeyexponent}", "", "${publickeymodulus}");       var encrypedpwd = rsautils.encryptedstring (Key,password); $.post ("Login.action", {username:username, password:encrypedpwd, Randcode:randcode, Rememberme:rem}, function (JsonD               ATA) {//Request complete//If true, prove that the user has downloaded, display the downloaded prompt, otherwise directly download if (jsondata.success = = True) {           Login Success window.location.href = ' index.jsp ';               } else {//Hint error message diverrors var etttext = "";               if (username = = "") {etttext= "user name cannot be empty";               } else if (password = = "") {etttext= "Password cannot be empty";               } else if (Randcode = = "") {etttext= "Verification code cannot be empty";               } else {etttext=jsondata.msg;           } alert (Etttext);    }       }); }</scRipt> 
Login.action

Rsaprivatekey Privatekey = (rsaprivatekey) request.getsession (). getattribute ("Privatekey"); String descrypedpwd = rsautils.decryptbyprivatekey (password, privatekey); After the decrypted password, password is the password submitted.


Rsautils.java

Package Com.myapp.util;import Java.math.BigInteger;  Import Java.security.KeyFactory;  Import Java.security.KeyPair;  Import Java.security.KeyPairGenerator;  Import java.security.NoSuchAlgorithmException;  Import Java.security.interfaces.RSAPrivateKey;  Import Java.security.interfaces.RSAPublicKey;  Import Java.security.spec.RSAPrivateKeySpec;  Import Java.security.spec.RSAPublicKeySpec; Import Java.util.HashMap; Import Javax.crypto.Cipher; public class Rsautils {/** * generates and the private key * @throws nosuchalgorithmexception * * * * static HASHM Ap<string, Object> Getkeys () throws nosuchalgorithmexception{hashmap<string, object> map = new HashM          Ap<string, object> (); Keypairgenerator Keypairgen = keypairgenerator.getinstance ("RSA", new          Org.bouncycastle.jce.provider.BouncyCastleProvider ());          Keypairgen.initialize (1024);          KeyPair KeyPair = Keypairgen.generatekeypair (); Rsapublickey PublicKey = (rsapublickey) keypAir.getpublic ();          Rsaprivatekey Privatekey = (rsaprivatekey) keypair.getprivate ();          Map.put ("Public", PublicKey);          Map.put ("Private", Privatekey);      return map;            /** * Use modulo and exponent to generate RSA public key * * * @param modulus * modulo * @param exponent *          Index * @return */public static Rsapublickey Getpublickey (string modulus, string exponent) {              try {BigInteger B1 = new BigInteger (modulus);              BigInteger b2 = new BigInteger (exponent);              Keyfactory keyfactory = keyfactory.getinstance ("RSA", New Org.bouncycastle.jce.provider.BouncyCastleProvider ());              Rsapublickeyspec KeySpec = new Rsapublickeyspec (B1, B2);          Return (Rsapublickey) keyfactory.generatepublic (KEYSPEC);              } catch (Exception e) {e.printstacktrace ();          return null;    }}/** * Use modulo and exponent to generate RSA private key */none/nopadding "  * * @param modulus * @param exponent * Index * @return */Pub Lic static Rsaprivatekey Getprivatekey (string modulus, string exponent) {try {BigInteger B1 = new              BigInteger (modulus);              BigInteger b2 = new BigInteger (exponent);              Keyfactory keyfactory = keyfactory.getinstance ("RSA", New Org.bouncycastle.jce.provider.BouncyCastleProvider ());              Rsaprivatekeyspec KeySpec = new Rsaprivatekeyspec (B1, B2);          Return (Rsaprivatekey) keyfactory.generateprivate (KEYSPEC);              } catch (Exception e) {e.printstacktrace ();          return null;       }}/** * Public key Encryption * * @param data * @param publickey * @return * @throws Exception           */public static string Encryptbypublickey (string data, Rsapublickey PublicKey) throws Exception { Cipher Cipher = cipher.getinstance ("RSA", New Org.bouNcycastle.jce.provider.BouncyCastleProvider ());          Cipher.init (Cipher.encrypt_mode, PublicKey);          modulo length int key_len = Publickey.getmodulus (). Bitlength ()/8;          Encrypted data length <= modulus length -11 string[] datas = splitstring (data, key_len-11);          String mi = "";          If the clear text length is greater than die Length-11 then encrypt for (String s:datas) {mi + bcd2str (cipher.dofinal (S.getbytes ()));      } return mi;      /** * Private Key decryption * * @param data * @param privatekey * @return * @throws Exception          */public static string Decryptbyprivatekey (string data, Rsaprivatekey Privatekey) throws Exception {          Cipher Cipher = cipher.getinstance ("RSA", New Org.bouncycastle.jce.provider.BouncyCastleProvider ());          Cipher.init (Cipher.decrypt_mode, Privatekey);          modulo length int key_len = Privatekey.getmodulus (). Bitlength ()/8;          byte[] bytes = Data.getbytes (); Byte[] BCD= Ascii_to_bcd (bytes, bytes.length);          System.err.println (bcd.length);          If the cipher length is larger than the modulus, the String ming = "" should be decrypted.          byte[][] Arrays = Splitarray (BCD, Key_len);          For (byte[] arr:arrays) {ming + = new String (cipher.dofinal (arr));      } return Ming;          }/** * ASCII to BCD code * */public static byte[] ASCII_TO_BCD (byte[] ASCII, int asc_len) {          byte[] BCD = new BYTE[ASC_LEN/2];          int j = 0;              for (int i = 0; I < (Asc_len + 1)/2; i++) {Bcd[i] = ASC_TO_BCD (ascii[j++]);          Bcd[i] = (byte) (((J >= Asc_len) 0X00:ASC_TO_BCD (ascii[j++])) + (Bcd[i] << 4));      } return BCD;            } public static byte ASC_TO_BCD (byte asc) {byte BCD;          if (ASC >= ' 0 ') && (ASC <= ' 9 ')) BCD = (byte) (ASC-' 0 '); else if (ASC >= ' A ') && (ASC <= ' F ')) BCD = (byte) (ASC-' A ' + 10);          else if (ASC >= ' a ') && (ASC <= ' F ')) BCD = (byte) (ASC-' a ' + 10);          else BCD = (byte) (asc-48);      return BCD; }/** * BCD to String */public static string Bcd2str (byte[] bytes) {char temp[] = new char[bytes.            Length * 2], Val;              for (int i = 0; i < bytes.length; i++) {val = (char) (((Bytes[i] & 0xf0) >> 4) & 0x0f);                Temp[i * 2] = (char) (Val > 9? val + ' A '-10:val + ' 0 ');              val = (char) (Bytes[i] & 0x0f);          Temp[i * 2 + 1] = (char) (Val > 9? val + ' A '-10:val + ' 0 ');      } return new String (temp); }/** * Split String * * public static string[] Splitstring (string string, int len) {int x = string.          Length ()/Len;          int y = string.length ()% Len;          int z = 0;          if (Y! = 0) {z = 1; } string[] StriNGS = new String[x + z];          String str = "";  for (int i=0; i<x+z; i++) {if (i==x+z-1 && y!=0) {str = string.substring (I*len,              I*len+y);              }else{str = string.substring (I*len, I*len+len);          } strings[i] = str;      } return strings;  }/** * Split fraction Group */public static byte[][] Splitarray (byte[] Data,int len) {int x = data.length/          Len          int y = data.length% len;          int z = 0;          if (y!=0) {z = 1;          } byte[][] Arrays = new byte[x+z][];          Byte[] arr;              for (int i=0; i<x+z; i++) {arr = new Byte[len];              if (i==x+z-1 && y!=0) {system.arraycopy (data, I*len, arr, 0, y);              }else{system.arraycopy (data, I*len, arr, 0, Len);          } Arrays[i] = arr;      } return arrays; }   public static void Main (string[] args) throws exception{hashmap<string, object> map = Getkeys ();          Generate the public and private keys rsapublickey PublicKey = (rsapublickey) map.get ("publicly");                    Rsaprivatekey Privatekey = (rsaprivatekey) map.get ("private");          modulo String modulus = Publickey.getmodulus (). toString ();        System.out.println ("PubKey modulus=" +modulus);        Public key index String public_exponent = Publickey.getpublicexponent (). toString ();        System.out.println ("PubKey exponent=" +public_exponent);          Private key index String private_exponent = Privatekey.getprivateexponent (). toString ();        System.out.println ("Private exponent=" +private_exponent);          Clear text String ming = "111";          Generate public and private keys using modulo and exponent rsapublickey PubKey = Rsautils.getpublickey (modulus, public_exponent);          Rsaprivatekey Prikey = Rsautils.getprivatekey (modulus, private_exponent); Encrypted ciphertext, String mi = rsautils.Encryptbypublickey (Ming, PubKey);          System.err.println ("mi=" +mi);          decrypted plaintext String ming2 = Rsautils.decryptbyprivatekey (mi, prikey);      System.err.println ("ming2=" +ming2); }}


My Java Web login RSA encryption

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.