美文网首页
Android数据Rsa加密

Android数据Rsa加密

作者: 1024猿 | 来源:发表于2020-05-28 13:34 被阅读0次

    ———————RSA非对称可逆加密———————
    RSA加密原理概述:
    RSA的安全性依赖于大数的分解,公钥和私钥都是两个大素数(大于100的十进制位)的函数。从一个密钥和密文推断出明文的难度等同于分解两个大素数的积

    • 1.选择两个大素数 p,q ,计算 n=p*q;
    • 2.随机选择加密密钥 e ,要求 e 和 (p-1)*(q-1)互质
    • 3.利用 Euclid算法计算解密密钥 d , 使其满足 ed = 1(mod(p-1)(q-1)) (其中 n,d 也要互质)
    • 4:至此得出公钥为 (n,e) 私钥为 * (n,d) 加解密方法:
      • 1.首先将要加密的信息 m(二进制表示) 分成等长的
        数据块 m1,m2,…,mi 块长 s(尽可能大) ,其中2^s< n
      • 2:对应的密文是: ci = mi^e(mod n)
      • 3:解密时作如下计算: mi = ci^d(mod n)

    RSA速度:
    由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论 是软件还是硬件实现。 速度一直是RSA的缺陷。一般来说只用于少量数据 加密。

    RSAUtils工具类:

    package com.example.rsa;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    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.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.RSAPublicKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    
    import javax.crypto.Cipher;
    
    
    public final class RSAUtils
    {
        private static String RSA = "RSA";
        private static final String TransForMation = "RSA/None/PKCS1Padding";
    
        /**
         * 随机生成RSA密钥对(默认密钥长度为1024)
         * 
         * @return
         */
        public static KeyPair generateRSAKeyPair()
        {
            return generateRSAKeyPair(1024);
        }
    
        /**
         * 随机生成RSA密钥对
         * 
         * @param keyLength
         *            密钥长度,范围:512~2048<br>
         *            一般1024
         * @return
         */
        public static KeyPair generateRSAKeyPair(int keyLength)
        {
            try
            {
                KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
                kpg.initialize(keyLength);
                return kpg.genKeyPair();
            } catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 用公钥加密 <br>
         * 每次加密的字节数,不能超过密钥的长度值减去11
         * 
         * @param data
         *            需加密数据的byte数据
         * @param pubKey
         *            公钥
         * @return 加密后的byte型数据
         */
        public static byte[] encryptData(byte[] data, PublicKey publicKey)
        {
            try
            {
                Cipher cipher = Cipher.getInstance(TransForMation);
                // 编码前设定编码方式及密钥
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
                // 传入编码数据并返回编码结果
                return cipher.doFinal(data);
            } catch (Exception e)
            {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 用私钥解密
         * 
         * @param encryptedData
         *            经过encryptedData()加密返回的byte数据
         * @param privateKey
         *            私钥
         * @return
         */
        public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey)
        {
            try
            {
                Cipher cipher = Cipher.getInstance(TransForMation);
                cipher.init(Cipher.DECRYPT_MODE, privateKey);
                return cipher.doFinal(encryptedData);
            } catch (Exception e)
            {
                return null;
            }
        }
    
        /**
         * 通过公钥byte[](publicKey.getEncoded())将公钥还原,适用于RSA算法
         * 
         * @param keyBytes
         * @return
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeySpecException
         */
        public static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException,
                InvalidKeySpecException
        {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PublicKey publicKey = keyFactory.generatePublic(keySpec);
            return publicKey;
        }
    
        /**
         * 通过私钥byte[]将公钥还原,适用于RSA算法
         * 
         * @param keyBytes
         * @return
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeySpecException
         */
        public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException,
                InvalidKeySpecException
        {
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey;
        }
    
        /**
         * 使用N、e值还原公钥
         * 
         * @param modulus
         * @param publicExponent
         * @return
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeySpecException
         */
        public static PublicKey getPublicKey(String modulus, String publicExponent)
                throws NoSuchAlgorithmException, InvalidKeySpecException
        {
            BigInteger bigIntModulus = new BigInteger(modulus);
            BigInteger bigIntPrivateExponent = new BigInteger(publicExponent);
            RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PublicKey publicKey = keyFactory.generatePublic(keySpec);
            return publicKey;
        }
    
        /**
         * 使用N、d值还原私钥
         * 
         * @param modulus
         * @param privateExponent
         * @return
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeySpecException
         */
        public static PrivateKey getPrivateKey(String modulus, String privateExponent)
                throws NoSuchAlgorithmException, InvalidKeySpecException
        {
            BigInteger bigIntModulus = new BigInteger(modulus);
            BigInteger bigIntPrivateExponent = new BigInteger(privateExponent);
            RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey;
        }
    
        /**
         * 从字符串中加载公钥
         * 
         * @param publicKeyStr
         *            公钥数据字符串
         * @throws Exception
         *             加载公钥时产生的异常
         */
        public static PublicKey loadPublicKey(String publicKeyStr) throws Exception
        {
            try
            {
                byte[] buffer = Base64Utils.decode(publicKeyStr);
                KeyFactory keyFactory = KeyFactory.getInstance(RSA);
                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
                return (RSAPublicKey) keyFactory.generatePublic(keySpec);
            } catch (NoSuchAlgorithmException e)
            {
                throw new Exception("无此算法");
            } catch (InvalidKeySpecException e)
            {
                throw new Exception("公钥非法");
            } catch (NullPointerException e)
            {
                throw new Exception("公钥数据为空");
            }
        }
    
        /**
         * 从字符串中加载私钥<br>
         * 加载时使用的是PKCS8EncodedKeySpec(PKCS#8编码的Key指令)。
         * 
         * @param privateKeyStr
         * @return
         * @throws Exception
         */
        public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception
        {
            try
            {
                byte[] buffer = Base64Utils.decode(privateKeyStr);
                // X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
                KeyFactory keyFactory = KeyFactory.getInstance(RSA);
                return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
            } catch (NoSuchAlgorithmException e)
            {
                throw new Exception("无此算法");
            } catch (InvalidKeySpecException e)
            {
                throw new Exception("私钥非法");
            } catch (NullPointerException e)
            {
                throw new Exception("私钥数据为空");
            }
        }
    
        /**
         * 从文件中输入流中加载公钥
         * 
         * @param in
         *            公钥输入流
         * @throws Exception
         *             加载公钥时产生的异常
         */
        public static PublicKey loadPublicKey(InputStream in) throws Exception
        {
            try
            {
                return loadPublicKey(readKey(in));
            } catch (IOException e)
            {
                throw new Exception("公钥数据流读取错误");
            } catch (NullPointerException e)
            {
                throw new Exception("公钥输入流为空");
            }
        }
    
        /**
         * 从文件中加载私钥
         * 
         * @param keyFileName
         *            私钥文件名
         * @return 是否成功
         * @throws Exception
         */
        public static PrivateKey loadPrivateKey(InputStream in) throws Exception
        {
            try
            {
                return loadPrivateKey(readKey(in));
            } catch (IOException e)
            {
                throw new Exception("私钥数据读取错误");
            } catch (NullPointerException e)
            {
                throw new Exception("私钥输入流为空");
            }
        }
    
        /**
         * 读取密钥信息
         * 
         * @param in
         * @return
         * @throws IOException
         */
        private static String readKey(InputStream in) throws IOException
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String readLine = null;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null)
            {
                if (readLine.charAt(0) == '-')
                {
                    continue;
                } else
                {
                    sb.append(readLine);
                    sb.append('\r');
                }
            }
    
            return sb.toString();
        }
    
        /**
         * 打印公钥信息
         * 
         * @param publicKey
         */
        public static void printPublicKeyInfo(PublicKey publicKey)
        {
            RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
            System.out.println("----------RSAPublicKey----------");
            System.out.println("Modulus.length=" + rsaPublicKey.getModulus().bitLength());
            System.out.println("Modulus=" + rsaPublicKey.getModulus().toString());
            System.out.println("PublicExponent.length=" + rsaPublicKey.getPublicExponent().bitLength());
            System.out.println("PublicExponent=" + rsaPublicKey.getPublicExponent().toString());
        }
    
        public static void printPrivateKeyInfo(PrivateKey privateKey)
        {
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
            System.out.println("----------RSAPrivateKey ----------");
            System.out.println("Modulus.length=" + rsaPrivateKey.getModulus().bitLength());
            System.out.println("Modulus=" + rsaPrivateKey.getModulus().toString());
            System.out.println("PrivateExponent.length=" + rsaPrivateKey.getPrivateExponent().bitLength());
            System.out.println("PrivatecExponent=" + rsaPrivateKey.getPrivateExponent().toString());
        }
    }
    

    特别说明:
    1.以上的加解密只是针对单个Block块的,如果需要支持N个块,则需要自己单独对数据进行切分。
    比如1024位加解密,单个block的size是128个字节。
    2.注意密钥填充方式,这里用的是PKCS1。

    更多详情可以参考:
    Android传输数据时加密详解
    Android使用RSA加密和解密

    相关文章

      网友评论

          本文标题:Android数据Rsa加密

          本文链接:https://www.haomeiwen.com/subject/kwooahtx.html