Java使用非对称数据加密RSA加密解密

Posted -桃之夭夭

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java使用非对称数据加密RSA加密解密相关的知识,希望对你有一定的参考价值。

  emmmmmm就是呢,我今天研究了一下非对称数据加密RSA的使用,算法什么的暂时不研究,加密算法还有很多,以后再研究吧,就酱(>人<;)。非对称加密算法需要两个密钥:公开密钥(publicKey)和私有密钥(privateKey);如果用公有密钥加密,对应的就是要私有密钥才能解密;反过来就是私钥加密,公钥解密。

  然后就来实现一下RSA加密的工具类吧

  注意:RSA加密明文最大长度是117字节,解密要求密文最大长度为128字节,所以再加密和解密的时候要分段进行,就是每117字节就加密,然后再把这一节节拼起来。

  1 public class RSAUtil {
  2 
  3     public static String KEY_PAIRGENO = "RSA";
  4     public static String PUBLIC_KEY = "PUBLIC_KEY";
  5     public static String PRIVATE_KEY = "PRIVATE_KEY";
  6     public static final String CHARSET = "UTF-8";
  7 
  8     public static HashMap<String, String> keyMap = new HashMap<>(2);
  9 
 10     public static void init() throws Exception {
 11         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_PAIRGENO);
 12         keyPairGen.initialize(1024);
 13         KeyPair keyPair = keyPairGen.generateKeyPair();
 14         String publicKey = getPublicKeyStr(keyPair.getPublic());
 15         String privateKey = getPrivateKeyStr(keyPair.getPrivate());
 16 
 17         keyMap.put(PUBLIC_KEY, publicKey);
 18         keyMap.put(PRIVATE_KEY,privateKey);
 19     }
 20 
 21 
 22     private static String getPrivateKeyStr(PrivateKey privateKey) throws Exception {
 23         return Base64.encodeBase64URLSafeString(privateKey.getEncoded());
 24     }
 25 
 26     private static String getPublicKeyStr(PublicKey publicKey) throws Exception {
 27         return Base64.encodeBase64URLSafeString(publicKey.getEncoded());
 28     }
 29 
 30     /**
 31      * 把字符串公钥转为 RSAPublicKey 公钥
 32      */
 33     public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
 34         //通过X509编码的Key指令获得公钥对象
 35         KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIRGENO);
 36         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
 37         RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
 38         return key;
 39     }
 40 
 41     /**
 42      * 把字符串私钥转为 RSAPrivateKey 私钥
 43      */
 44     public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
 45         //通过PKCS#8编码的Key指令获得私钥对象
 46         KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIRGENO);
 47         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
 48         RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
 49         return key;
 50     }
 51 
 52     /**
 53      * 公钥加密,  加密明文最大长度是117字节
 54      */
 55     public static String  encryptByPublicKey(String msg, RSAPublicKey publicKey) throws Exception{
 56         Cipher cipher = Cipher.getInstance(KEY_PAIRGENO);
 57         cipher.init(Cipher.ENCRYPT_MODE,publicKey);
 58         int keySize = publicKey.getModulus().bitLength();//1024
 59         byte[] data = msg.getBytes(CHARSET);
 60         byte[] encryptedData = rsaSplitCode(cipher, data, Cipher.ENCRYPT_MODE, keySize);
 61         String mi= Base64.encodeBase64URLSafeString(encryptedData);
 62         return mi;
 63 
 64 
 65     }
 66 
 67     /*
 68      * 私钥解密,解密要求密文最大长度为128字节
 69      * */
 70     public static String decryptByPrivateKey(String rsaMsg, RSAPrivateKey privateKey) throws Exception{
 71         Cipher cipher = Cipher.getInstance(KEY_PAIRGENO);
 72         cipher.init(Cipher.DECRYPT_MODE, privateKey);
 73         int keySize = privateKey.getModulus().bitLength();//长度是1024
 74         byte[] data = Base64.decodeBase64(rsaMsg);
 75         byte[] decryptedData = rsaSplitCode(cipher, data, Cipher.DECRYPT_MODE, keySize);
 76         String ming = new String(decryptedData, CHARSET);
 77         return ming;
 78     }
 79 
 80     /*私钥加密*/
 81     public static String encryptByPrivate(String msg, RSAPrivateKey privateKey) throws Exception{
 82         Cipher ciper = Cipher.getInstance(KEY_PAIRGENO);
 83         ciper.init(Cipher.ENCRYPT_MODE,privateKey);
 84         int keySize = privateKey.getModulus().bitLength();
 85         byte[] data = msg.getBytes(CHARSET);
 86         byte[] encryptedData = rsaSplitCode(ciper, data, Cipher.ENCRYPT_MODE,keySize);
 87         String mi = Base64.encodeBase64URLSafeString(encryptedData);
 88         return mi;
 89     }
 90 
 91     /*公钥解密*/
 92     public static String decrytByPublic(String msg, RSAPublicKey publicKey) throws Exception{
 93         Cipher ciper = Cipher.getInstance(KEY_PAIRGENO);
 94         ciper.init(Cipher.DECRYPT_MODE, publicKey);
 95         int keySize = publicKey.getModulus().bitLength();
 96         byte[] data = Base64.decodeBase64(msg);
 97         byte[] decryptedData = rsaSplitCode(ciper, data, Cipher.DECRYPT_MODE,keySize);
 98         String ming = new String(decryptedData,CHARSET);
 99         return ming;
100     }
101 
102 
103 
104     private static byte[] rsaSplitCode(Cipher cipher, byte[] data,int opmode ,int keySize){
105         int maxBlock = 0;
106         if(opmode == Cipher.DECRYPT_MODE)
107             maxBlock = keySize / 8;//解密要求最大长度是128
108         else
109             maxBlock = keySize / 8 -11; //加密要求最大长度是117
110 
111         int inputLen = data.length;
112         ByteArrayOutputStream out = new ByteArrayOutputStream();
113         int offSet = 0;
114         byte[] cache;
115         int i = 0;
116         // 对数据分段解密
117         try {
118             while (inputLen - offSet > 0) {
119                  if (inputLen - offSet > maxBlock) {
120                      cache = cipher.doFinal(data, offSet, maxBlock);
121                  } else {
122                      cache = cipher.doFinal(data, offSet, inputLen - offSet);
123                  }
124                   out.write(cache, 0, cache.length);
125                  i++;
126                  offSet = i * maxBlock;
127              }
128             byte[] bytes = out.toByteArray();
129             out.close();
130             return bytes;
131         } catch (Exception e) {
132             throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e);
133         }
134     }
135 
136 
137 
138 
139 
140     public static void main(String[] args) throws Exception {
141         init();
142         String msg = "我是冬竹";
143         System.out.println("公钥加密-私钥解密:");
144         String mi  =  encryptByPublicKey(msg, getPublicKey(keyMap.get(PUBLIC_KEY)));
145         System.out.println("密文:" + mi);
146 
147         String ming = decryptByPrivateKey(mi ,  getPrivateKey(keyMap.get(PRIVATE_KEY)));
148         System.out.println("明文:" + ming);
149 
150         System.out.println("私钥加密-公钥解密:");
151         String mi2 =  encryptByPrivate(msg, getPrivateKey(keyMap.get(PRIVATE_KEY)));
152         System.out.println("密文:" + mi2);
153 
154         String ming2 = decrytByPublic(mi2 ,  getPublicKey(keyMap.get(PUBLIC_KEY)));
155         System.out.println("明文:" + ming);
156     }
157 
158 }

  

  这这这好长啊........

  说一下这个过程: 

    1.  keyPair.getPublic() 获得的字节数组  用encodeBase64URLSafeString() 编码成字符串,也就是我们有时候用的那种很多字母的那种公钥(私钥)

    2.  用decodeBase64()  把公钥解码成字节数组,然后通过X509编码的Key指令获得公钥对象 RSAPublicKey 

 加密字符串的过程:

    1.   msg.getBytes() 获得字符数组, 然后用rsaSplitCode() 方法加密,再用encodeBase64URLSafeString编码成字符串(密文)

 解密字符串的过程:

    1.  decodeBase64() 把密文解码成字符数组,再用new String()方法转为字符串

 

然后我用的Base64类是commons-net-3.1.jar  里的,这个是我的maven仓库里(maven真的太方便了(●ˇ?ˇ●))

放上这个:https://github.com/MoisAbby/XZUtils, 以后会把我攒的好用的东西都放上来




以上是关于Java使用非对称数据加密RSA加密解密的主要内容,如果未能解决你的问题,请参考以下文章

JAVA RSA非对称加密详解

使用 Hutool 处理 RSA 等非对称加密

非对称加密及RSA加密算法

Java 非对称加密RSA理解和运用

Java对称与非对称加密解密,AES与RSA

JAVA实现RSA加密解密 非对称算法