zoukankan      html  css  js  c++  java
  • Java使用RSA算法

    RSA算法代码如下:

    package gj.secure;
    
    import javax.crypto.Cipher;
    import java.io.ByteArrayOutputStream;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.Signature;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    
    /**
     * @author areful
     * Date: 2019/2/12
     */
    @SuppressWarnings("WeakerAccess")
    public class RSAUtil {
        public static final String KEY_ALGORITHM_AES = "RSA";
        public static final String KEY_ALGORITHM_AES_PCKS1PADDING = "RSA/ECB/PKCS1PADDING";
        public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
        private static final int MAX_ENCRYPT_BLOCK = 117;
        private static final int MAX_DECRYPT_BLOCK = 128;
    
        public static KeyPair genKeyPair() throws Exception {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM_AES);
            keyPairGen.initialize(1024);
            return keyPairGen.generateKeyPair();
        }
    
        public static byte[] encryptByPublicKey(byte[] data, byte[] pubKey) throws Exception {
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_AES_PCKS1PADDING);
            cipher.init(Cipher.ENCRYPT_MODE, KeyFactory.getInstance(KEY_ALGORITHM_AES).generatePublic(new X509EncodedKeySpec(pubKey)));
            return doFinal(cipher, data, data.length, true);
        }
    
        public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_AES);
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_AES_PCKS1PADDING);
            cipher.init(Cipher.ENCRYPT_MODE, keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey)));
            return doFinal(cipher, data, data.length, true);
        }
    
        public static byte[] decryptByPublicKey(byte[] encryptedData, byte[] publicKey) throws Exception {
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_AES_PCKS1PADDING);
            cipher.init(Cipher.DECRYPT_MODE, KeyFactory.getInstance(KEY_ALGORITHM_AES).generatePublic(new X509EncodedKeySpec(publicKey)));
            return doFinal(cipher, encryptedData, encryptedData.length, false);
        }
    
        public static byte[] decryptByPrivateKey(byte[] encryptedData, byte[] privateKey) throws Exception {
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_AES_PCKS1PADDING);
            cipher.init(Cipher.DECRYPT_MODE, KeyFactory.getInstance(KEY_ALGORITHM_AES).generatePrivate(new PKCS8EncodedKeySpec(privateKey)));
            return doFinal(cipher, encryptedData, encryptedData.length, false);
        }
    
        public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(KeyFactory.getInstance(KEY_ALGORITHM_AES).generatePrivate(new PKCS8EncodedKeySpec(privateKey)));
            signature.update(data);
            return signature.sign();
        }
    
        public static boolean verify(byte[] data, byte[] publicKey, byte[] sign) throws Exception {
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(KeyFactory.getInstance(KEY_ALGORITHM_AES).generatePublic(new X509EncodedKeySpec(publicKey)));
            signature.update(data);
            return signature.verify(sign);
        }
    
        private static byte[] doFinal(Cipher cipher, byte[] data, int inputLen, boolean isEncryptMode) throws Exception {
            int maxBlockSize = isEncryptMode ? MAX_ENCRYPT_BLOCK : MAX_DECRYPT_BLOCK;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > maxBlockSize) {
                    cache = cipher.doFinal(data, offSet, maxBlockSize);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * maxBlockSize;
            }
            byte[] result = out.toByteArray();
            out.close();
            return result;
        }
    }

    如果在网上传输,不能直接传byte[]类型数组,部分字节会和网络传输协议控制类字符冲突。通常都是转换一次,例如使用Base64编码发送,接收方收到后再Base64解码,这样就不会有冲突了。

    以下是Base64封装:

    package gj.secure;
    
    import java.security.KeyFactory;
    import java.security.Signature;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    
    /**
     * @author areful
     * Date: 2019/2/12
     */
    public class RSAWrapper extends RSAUtil {
        public static String encryptByPublicKey(String data, String publicKey) throws Exception {
            return encode2Base64(encryptByPublicKey(decodeFromBase64(data), decodeFromBase64(publicKey)));
        }
    
        public static String encryptByPrivateKey(String data, String privateKey) throws Exception {
            return encode2Base64(encryptByPrivateKey(decodeFromBase64(data), decodeFromBase64(privateKey)));
        }
    
        public static String decryptByPublicKey(String data, String publicKey) throws Exception {
            return new String(decryptByPublicKey(decodeFromBase64(data), decodeFromBase64(publicKey)));
        }
    
        public static String decryptByPrivateKey(String data, String privateKey) throws Exception {
            return new String(decryptByPrivateKey(decodeFromBase64(data), decodeFromBase64(privateKey)));
        }
    
        public static String sign(String data, String privateKey) throws Exception {
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(KeyFactory.getInstance(KEY_ALGORITHM_AES)
                    .generatePrivate(new PKCS8EncodedKeySpec(decodeFromBase64(privateKey))));
            signature.update(decodeFromBase64(data));
            return encode2Base64(signature.sign());
        }
    
        public static boolean verify(String data, String publicKey, String sign) throws Exception {
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(KeyFactory.getInstance(KEY_ALGORITHM_AES)
                    .generatePublic(new X509EncodedKeySpec(decodeFromBase64(publicKey))));
            signature.update(decodeFromBase64(data));
            return signature.verify(decodeFromBase64(sign));
        }
    
        private static String encode2Base64(byte[] data) {
            return java.util.Base64.getEncoder().encodeToString(data);
        }
    
        private static byte[] decodeFromBase64(String src) {
            return java.util.Base64.getDecoder().decode(src);
        }
    }
    

      

    测试代码:

    package gj.secure;
    
    import org.junit.Test;
    
    import java.security.KeyPair;
    import java.util.Arrays;
    
    /**
     * @author areful
     * Date: 2019/2/12
     */
    public class TestRSAUtil {
        @Test
        public void testEncryptByPublicKey() throws Exception {
            KeyPair keyPair = RSAUtil.genKeyPair();
            byte[] publicKey = keyPair.getPublic().getEncoded();
            byte[] privateKey = keyPair.getPrivate().getEncoded();
    
            System.err.println("私钥加密——公钥解密");
            String src = "第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。";
            System.out.println("原文字:	" + src);
            byte[] encodedData = RSAUtil.encryptByPublicKey(src.getBytes(), publicKey);
            System.out.println("加密后:	" + Arrays.toString(encodedData));
            String plainText = new String(RSAUtil.decryptByPrivateKey(encodedData, privateKey));
            System.out.println("解密后: 	" + plainText);
    
            System.err.println("私钥签名——公钥验证签名");
            byte[] sign = RSAUtil.sign(encodedData, privateKey);
            System.err.println("签名:		" + Arrays.toString(sign));
            boolean status = RSAUtil.verify(encodedData, publicKey, sign);
            System.err.println("验证结果:	" + status);
        }
    }
    

      

    package gj.secure;
    
    import org.junit.Test;
    
    import java.util.Base64;
    
    /**
     * @author areful
     * Date: 2019/2/12
     */
    public class TestRSAWrapper {
        @Test
        public void testEncryptByPrivateKey() throws Exception {
            String pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDW7SUABMZltXXlQ0ZG2WZe6i64Jq0hb6QpC0cvA49zUyrzkfQrH2" +
                    "JYoPohmVWqKn+vYj4HKFtBHsPUI/3COLv/tQ7oOQGrf9o0JhaZwktiq+pJbTe2jlw8UZm8+xhIDGGDZ/dXQyRHKfkTyJJqwVv1" +
                    "dE1CIFenCoPp2JztsYS7iQIDAQAB";
            String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANbtJQAExmW1deVDRkbZZl7qLrgmrSFvpCkLRy8Dj3" +
                    "NTKvOR9CsfYlig+iGZVaoqf69iPgcoW0Eew9Qj/cI4u/+1Dug5Aat/2jQmFpnCS2Kr6kltN7aOXDxRmbz7GEgMYYNn91dDJEcp" +
                    "+RPIkmrBW/V0TUIgV6cKg+nYnO2xhLuJAgMBAAECgYByhAKN4v1u3ePGVzUPtPAlrHNeLUVcJmb6c4bnFueNFAgzpVXK0DsPbB" +
                    "46Xr/VHjXQVfEk0SzmIqVG2DJyFNadq0RqGmPDTPit1cO7aWQb3fZEUUpORZt1TCqIShirzoO830w1dJJW7MhyoKUAPLLsi5be" +
                    "rFj7VaagOnmnZTgXsQJBAPSt1Qg++6Pat/7rwB46GhlTQvY6HOa0O9IcFWf262ihTJHJApYpvEvuLA6TKRAdP7EJ2ItwkoFFjQ" +
                    "bbKDq6I5UCQQDg3uYGKNmoIwkfVVzgcaLg4wEaAPftmS+pp3Q8l66BonBsYhG4kiYr9NepwPa9ZiSdZtXKEkkeWM6qZ1OeMXsl" +
                    "AkEAqBsiqWa0d3BXSBLrTRk4QzwcXpWws6UTEJlw75wLQzjHJcaIO2lzUGvT4zOiW8rsrpMIL01pqt2BNjuumSK4PQJAB9K5Xe1" +
                    "95QOTBawKlyRc7kX3e9gcx/9UUSqqOJFuWMQ19Q9UXn93JIBYIGe+Lcin7XHubiFEufGM/xCpMA+4oQJBAJRp1TLVinccyGw3v3" +
                    "vB96WQH89SUnmk5tR5ydSrB+3qr2lsiJtcH0i5R5EjYdFpIgpUEBEmL+s/LLLP9Rd7I+k=";
    
            String text = "第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1," +
                    "ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。";
            String base64Text = Base64.getEncoder().encodeToString(text.getBytes());
    
            //公钥加密私钥解密
            String cipherText = RSAWrapper.encryptByPublicKey(base64Text, pubKey);
            System.out.println("公钥加密:	" + cipherText);
            String plainText = RSAWrapper.decryptByPrivateKey(cipherText, privateKey);
            System.out.println("私钥解密:	" + plainText);
    
            text = "第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1," +
                    "并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功," +
                    "Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。";
            base64Text = Base64.getEncoder().encodeToString(text.getBytes());
    
            //私钥加密公钥解密
            cipherText = RSAWrapper.encryptByPrivateKey(base64Text, privateKey);
            System.out.println("私钥加密:	" + cipherText);
            plainText = RSAWrapper.decryptByPublicKey(cipherText, pubKey);
            System.out.println("公钥解密:	" + plainText);
    
            System.err.println("私钥签名——公钥验证签名");
            String sign = RSAWrapper.sign(cipherText, privateKey);
            System.err.println("签名:		" + sign);
            boolean status = RSAWrapper.verify(cipherText, pubKey, sign);
            System.err.println("验证结果:	" + status);
        }
    }
    

      

  • 相关阅读:
    Django之Form、CSRF、cookie和session
    Django之路由、模板和模型系统
    简约而不简单的Django
    剑指offer(10)矩形覆盖
    剑指offer(9)变态跳台阶
    剑指offer(8)跳台阶
    剑指offer(7)斐波那契数列
    剑指offer(6)旋转数组中的最小数字
    剑指offer(5)用两个栈实现队列
    剑指offer(4)重建二叉树
  • 原文地址:https://www.cnblogs.com/areful/p/10367920.html
Copyright © 2011-2022 走看看