About RSA implementation using JS foreground encryption and JAVA background decryption, RSA encryption and signature

accomplish:

Implemented with RSA asymmetric encryption. The rsa key pair is generated in the background, and then the rsa public key is set on the login page. When submitting, the password is encrypted with the public key. The generated ciphertext is sent to the background, decrypted with the private key, and the plaintext of the password is obtained.

In this way, the client only needs to know the RSA encryption method and public key, and the foreground does not know that the private key cannot be decrypted. This solution is relatively safe.

The attachment is the implementation of java+JS with reference to netizens' information, and is here for everyone to download. Access method/RSA/login.jsp.

You need to download the bcprov-jdk14-123.jar file from http://www.bouncycastle.org.

Because the background needs to be converted to bigint, there are some restrictions on the length of the plaintext:

The total length does not exceed 126 (the length of 1 Chinese character is 9), the following two strings:

Ah send Dafa, send Dafa, send Dafa, send
1232132131231231232131232K123213213123123123213131231231232131232K1232132131231231232131232K1234234567891078

 

 

RSA speed 
 * Due to the large number of calculations, the fastest case of RSA is 100 times slower than DES, whether it is implemented in software or hardware. 
 * Speed ​​has always been a drawback of RSA. Generally only used for small amount of data encryption.

 

 

Util.java

    package RSA;  
      
    /**
     *  
     */  
      
    import java.io.ByteArrayOutputStream;  
    import java.io.FileInputStream;  
    import java.io.FileOutputStream;  
    import java.io.ObjectInputStream;  
    import java.io.ObjectOutputStream;  
    import java.math.BigInteger;  
    import java.security.KeyFactory;  
    import java.security.KeyPair;  
    import java.security.KeyPairGenerator;  
    import java.security.NoSuchAlgorithmException;  
    import java.security.PrivateKey;  
    import java.security.PublicKey;  
    import java.security.SecureRandom;  
    import java.security.interfaces.RSAPrivateKey;  
    import java.security.interfaces.RSAPublicKey;  
    import java.security.spec.InvalidKeySpecException;  
    import java.security.spec.RSAPrivateKeySpec;  
    import java.security.spec.RSAPublicKeySpec;  
      
    import javax.crypto.Cipher;  
      
    /**
     * RSA tool class. Provides encryption, decryption, key generation, etc. methods.
     * You need to download bcprov-jdk14-123.jar from http://www.bouncycastle.org.
     *  
     */  
    public class RSAUtil {  
          
        private static String RSAKeyStore = "C:/RSAKey.txt";  
        /**
         * * Generate key pair *
         *  
         * @return KeyPair *
         * @throws EncryptException
         */  
        public static KeyPair generateKeyPair() throws Exception {  
            try {  
                KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",  
                        new org.bouncycastle.jce.provider.BouncyCastleProvider());  
                final int KEY_SIZE = 1024;// There is nothing to say, this value is related to the size of the block encryption and can be changed, but it should not be too large, otherwise the efficiency will be low  
                keyPairGen.initialize(KEY_SIZE, new SecureRandom());  
                KeyPair keyPair = keyPairGen.generateKeyPair();  
                  
                System.out.println(keyPair.getPrivate());  
                System.out.println(keyPair.getPublic());  
                  
                saveKeyPair(keyPair);  
                return keyPair;  
            } catch (Exception e) {  
                throw new Exception(e.getMessage());  
            }  
        }  
      
        public static KeyPair getKeyPair() throws Exception {  
            FileInputStream fis = new FileInputStream(RSAKeyStore);  
            ObjectInputStream oos = new ObjectInputStream(fis);  
            KeyPair kp = (KeyPair) oos.readObject();  
            oos.close();  
            fis.close();  
            return kp;  
        }  
      
        public static void saveKeyPair(KeyPair kp) throws Exception {  
      
            FileOutputStream fos = new FileOutputStream(RSAKeyStore);  
            ObjectOutputStream oos = new ObjectOutputStream(fos);  
            // generate key  
            oos.writeObject (kp);  
            oos.close();  
            fos.close();  
        }  
      
        /**
         * * Generate public key *
         *  
         * @param modulus *
         * @param publicExponent *
         * @return RSAPublicKey *
         * @throws Exception
         */  
        public static RSAPublicKey generateRSAPublicKey(byte[] modulus,  
                byte[] publicExponent) throws Exception {  
            KeyFactory keyFac = null;  
            try {  
                keyFac = KeyFactory.getInstance("RSA",  
                        new org.bouncycastle.jce.provider.BouncyCastleProvider());  
            } catch (NoSuchAlgorithmException ex) {  
                throw new Exception(ex.getMessage());  
            }  
      
            RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(  
                    modulus), new BigInteger(publicExponent));  
            try {  
                return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);  
            } catch (InvalidKeySpecException ex) {  
                throw new Exception(ex.getMessage());  
            }  
        }  
      
        /**
         * * Generate private key *
         *  
         * @param modulus *
         * @param privateExponent *
         * @return RSAPrivateKey *
         * @throws Exception
         */  
        public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,  
                byte[] privateExponent) throws Exception {  
            KeyFactory keyFac = null;  
            try {  
                keyFac = KeyFactory.getInstance("RSA",  
                        new org.bouncycastle.jce.provider.BouncyCastleProvider());  
            } catch (NoSuchAlgorithmException ex) {  
                throw new Exception(ex.getMessage());  
            }  
      
            RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(  
                    modulus), new BigInteger(privateExponent));  
            try {  
                return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);  
            } catch (InvalidKeySpecException ex) {  
                throw new Exception(ex.getMessage());  
            }  
        }  
      
        /**
         * * Encryption *
         *  
         * @param key
         *encrypted key*
         * @param data
         * Plaintext data to be encrypted *
         * @return encrypted data *
         * @throws Exception
         */  
        public static byte[] encrypt(PublicKey pk, byte[] data) throws Exception {  
            try {  
                Cipher cipher = Cipher.getInstance("RSA",  
                        new org.bouncycastle.jce.provider.BouncyCastleProvider());  
                cipher.init(Cipher.ENCRYPT_MODE, pk);  
                int blockSize = cipher.getBlockSize();// Get the encrypted block size, such as: the data before encryption is 128 bytes, and key_size=1024  
                // encrypted block size is 127  
                //byte, encrypted is 128 bytes; so there are 2 encrypted blocks, the first 127  
                // The second byte is 1 byte  
                int outputSize = cipher.getOutputSize(data.length);// Get the encrypted block size after encryption  
                int leavedSize = data.length % blockSize;  
                int blocksSize = leavedSize != 0 ? data.length / blockSize + 1  
                        : data.length / blockSize;  
                byte[] raw = new byte[outputSize * blocksSize];  
                int i = 0;  
                while (data.length - i * blockSize > 0) {  
                    if (data.length - i * blockSize > blockSize)  
                        cipher.doFinal(data, i * blockSize, blockSize, raw, i  
                                * outputSize);  
                    else  
                        cipher.doFinal(data, i * blockSize, data.length - i  
                                * blockSize, raw, i * outputSize);  
                    // The doUpdate method is not available here. After viewing the source code, I found that there is no actual action after each doUpdate except putting byte[] in  
                    // In ByteArrayOutputStream, all byte[] are encrypted at the end of doFinal, but at this time the encrypted block size is likely to have exceeded  
                    // OutputSize so we had to use the dofinal method.  
      
                    i++;  
                }  
                return raw;  
            } catch (Exception e) {  
                throw new Exception(e.getMessage());  
            }  
        }  
      
        /**
         * * decrypt *
         *  
         * @param key
         * decrypted key *
         * @param raw
         *encrypted data*
         * @return decrypted plaintext *
         * @throws Exception
         */  
        public static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception {  
            try {  
                Cipher cipher = Cipher.getInstance("RSA",  
                        new org.bouncycastle.jce.provider.BouncyCastleProvider());  
                cipher.init(cipher.DECRYPT_MODE, pk);  
                int blockSize = cipher.getBlockSize();  
                ByteArrayOutputStream bout = new ByteArrayOutputStream(64);  
                int j = 0;  
      
                while (raw.length - j * blockSize > 0) {  
                    bout.write(cipher.doFinal(raw, j * blockSize, blockSize));  
                    j++;  
                }  
                return bout.toByteArray();  
            } catch (Exception e) {  
                throw new Exception(e.getMessage());  
            }  
        }  
      
        /**
         * * *
         *  
         * @param args *
         * @throws Exception
         */  
        public static void main(String[] args) throws Exception {  
            RSAPublicKey rsap = (RSAPublicKey) RSAUtil.generateKeyPair().getPublic();  
            String test = "hello world";  
            byte[] en_test = encrypt(getKeyPair().getPublic(), test.getBytes());  
            byte[] de_test = decrypt(getKeyPair().getPrivate(), en_test);  
            System.out.println(new String(de_test));  
        }  
    }  

 

LoginAction.java

    package RSA;  
      
    //login  
    /*
     * Generated by MyEclipse Struts
     * Template path: templates/java/JavaClass.vtl
     */  
    import java.math.BigInteger;  
    import java.net.URLDecoder;  
    import java.net.URLEncoder;  
      
    import javax.servlet.http.HttpServletRequest;  
    import javax.servlet.http.HttpServletResponse;  
      
    import RSA.RSAUtil;  
      
    /**
     * MyEclipse Struts Creation date: 06-28-2008
     *  
     * XDoclet definition:
     *  
     * @struts.action path="/login" name="loginForm" input="/login.jsp"
     *                scope="request" validate="true"
     * @struts.action-forward name="error" path="/error.jsp"
     * @struts.action-forward name="success" path="/success.jsp"
     */  
    public class LoginAction {  
        /*
         * Generated Methods
         */  
      
        /**
         * Method execute
         *  
         * @param mapping
         * @param form
         * @param request
         * @param response
         * @return ActionForward
         */  
        public boolean execute(HttpServletRequest request,  
                HttpServletResponse response) throws Exception {  
            String pwd ;  
            String result = request.getParameter("result");  
            System.out.println("The original text is encrypted: ");  
            System.out.println(result);  
            byte[] en_result = new BigInteger(result, 16).toByteArray();  
            //System.out.println("转成byte[]" + new String(en_result));  
            byte[] de_result = RSAUtil.decrypt(RSAUtil.getKeyPair().getPrivate(),  
                    en_result);  
            System.out.println("Restore ciphertext:");  
            System.out.println(new String(de_result));  
            StringBuffer sb = new StringBuffer();  
            sb.append(new String(de_result));  
            pwd = sb.reverse().toString();  
            System.out.println(sb);  
            System.out.println("=================================");  
            pwd = URLDecoder.decode(pwd,"UTF-8");//  
            System.out.println(pwd);  
            request.setAttribute("pwd", pwd);  
            return true;  
        }  
    }  

 

Login login.jsp

    <%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>  
      
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
    <html:html lang="true">  
    <head>  
        <title>login</title>  
      
        <script type="text/javascript" src="js/RSA.js"></script>  
        <script type="text/javascript" src="js/BigInt.js"></script>  
        <script type="text/javascript" src="js/Barrett.js"></script>  
          
        <script type="text/javascript">  
    function rsalogin(){  
        var thisPwd = document.getElementById("password").value;  
        bodyRSA();  
        var result = encryptedString(key, encodeURIComponent(thisPwd));  
        //alert(encodeURIComponent(thisPwd)+"\r\n"+result);  
        loginForm.action="loginCHK.jsp?result="+result;  
        loginForm.submit();  
    }  
    var key ;  
    function bodyRSA(){  
        setMaxDigits(130);  
        key = new RSAKeyPair("10001","","8246a46f44fc4d961e139fd70f4787d272d374532f4d2d9b7cbaad6a15a8c1301319aa6b3f30413b859351c71938aec516fa7147b69168b195e81df46b6bed7950cf3a1c719d42175f73d7c97a85d7d20a9e83688b92f05b3059bb2ff75cd7190a042cd2db97ebc2ab4da366f2a7085556ed613b5a39c9fdd2bb2595d1dc23b5");   
    }  
    </script>  
    </head>  
      
    <body>  
        <form method="post" name="loginForm" target=_blank>  
            <table border="0">  
                <tr>  
                    <td>  
                        Password:  
                    </td>  
                    <td>  
                        <input type='text' name="password" id=password style='width:400px' value="my passwd"/>  
                    </td>  
                </tr>  
                <tr>  
                    <td colspan="2" align="center">  
                        <input type="button" value="SUBMIT" onclick="rsalogin();" />  
                    </td>  
                </tr>  
            </table>  
        </form>  
    </body>  
    </html:html>  

 

Login verification loginCHK.jsp

    <%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>  
      
    <jsp:directive.page import="RSA.LoginAction"/>  
      
    <%  
    LoginAction la = new LoginAction();  
    la.execute(request ,response);  
    %>  
    pwd is [<%=request.getAttribute("pwd")%>]  

 

In addition, digital signature can also be achieved through RSA : signature with private key and verification with public key. See the code for details:

    package encode;  
      
    import java.security.KeyPair;  
    import java.security.KeyPairGenerator;  
    import java.security.Signature;  
      
    public class DigitalSignature2Example {  
        public static void main(String[] args) {  
            args = new String[] { "China" };  
              
            if (args.length != 1) {  
                System.err.println("Usage:java DigitalSignature2Example ");  
                System.exit(1);  
            }  
      
            try {  
                byte[] plainText = args[0].getBytes("UTF-8");  
                System.out.println("\nStart generating RSA key.");  
                // Generate RSA key pair  
                KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");  
                // initialize key length  
                keyGen.initialize(1024);  
                // generate key pair  
                KeyPair pair = keyGen.generateKeyPair();  
                System.out.println("\nFinish generating RSA key.");  
                // sign with private key  
                Signature sig = Signature.getInstance("SHA1WithRSA");  
                // Initialize with the specified private key  
                sig.initSign(pair.getPrivate());  
                // add the information to be signed  
                sig.update(plainText);  
                // return signed byte array  
                byte[] signature = sig.sign();  
                System.out.println(sig.getProvider().getInfo());  
                System.out.println("\nSignature: ");  
                System.out.println(new String(signature, "UTF-8"));  
      
                // use public key authentication  
                System.out.println("\nStart signature verification.");  
                sig.initVerify(pair.getPublic());  
                // add the information to be verified  
                sig.update(plainText);  
                if (sig.verify(signature)) {  
                    System.out.println("Signature verificated.");  
                } else {  
                    System.out.println("Signature failed.");  
                }  
            } catch (Exception e) {  
                e.printStackTrace ();  
            }  
        }  
    }  

 

 

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326612278&siteId=291194637