• Java使用RSA加密解密及签名校验


    转载原文地址:http://www.cnblogs.com/linjiqin/p/6005626.html

    根据原文的Base64工具包,自己做了修改:

    1.导包:import it.sauronsoftware.base64.Base64;         自己没导这个包

    2.工具包里报错的base64   一个是byte类型,修改成:  return Base64.getDecoder().decode(base64.getBytes());

                一个是String类型,修改成:return new String(Base64.getEncoder().encodeToString(bytes));

    3.测试方法里面的 公钥加密 私钥解密   原文测试输出的加密文字是图片式的文字  传不了url里  所以自己改了下  可以去跟原文对比。

    注意:
    RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。
    RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下异常:

    1 Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
    2     at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
    3     at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
    4     at javax.crypto.Cipher.doFinal(DashoA13*..)

    RSA.java--RSA公钥/私钥/签名工具包

      1 package com.rjs.util;
      2 
      3 import java.io.ByteArrayOutputStream;
      4 import java.security.Key;
      5 import java.security.KeyFactory;
      6 import java.security.KeyPair;
      7 import java.security.KeyPairGenerator;
      8 import java.security.PrivateKey;
      9 import java.security.PublicKey;
     10 import java.security.Signature;
     11 import java.security.interfaces.RSAPrivateKey;
     12 import java.security.interfaces.RSAPublicKey;
     13 import java.security.spec.PKCS8EncodedKeySpec;
     14 import java.security.spec.X509EncodedKeySpec;
     15 import java.util.HashMap;
     16 import java.util.Map;
     17 
     18 import javax.crypto.Cipher;
     19 
     20 /**
     21  * <p>
     22  * RSA公钥/私钥/签名工具包
     23  * </p>
     24  * <p>
     25  * 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)
     26  * </p>
     27  * <p>
     28  * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
     29  * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
     30  * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
     31  * </p>
     32  * 
     33  * @author IceWee
     34  * @date 2012-4-26
     35  * @version 1.0
     36  */
     37 public class RSA {
     38 
     39     /**
     40      * 加密算法RSA
     41      */
     42     public static final String KEY_ALGORITHM = "RSA";
     43     
     44     /**
     45      * 签名算法
     46      */
     47     public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
     48 
     49     /**
     50      * 获取公钥的key
     51      */
     52     private static final String PUBLIC_KEY = "RSAPublicKey";
     53     
     54     /**
     55      * 获取私钥的key
     56      */
     57     private static final String PRIVATE_KEY = "RSAPrivateKey";
     58     
     59     /**
     60      * RSA最大加密明文大小
     61      */
     62     private static final int MAX_ENCRYPT_BLOCK = 117;
     63     
     64     /**
     65      * RSA最大解密密文大小
     66      */
     67     private static final int MAX_DECRYPT_BLOCK = 128;
     68 
     69     /**
     70      * <p>
     71      * 生成密钥对(公钥和私钥)
     72      * </p>
     73      * 
     74      * @return
     75      * @throws Exception
     76      */
     77     public static Map<String, Object> genKeyPair() throws Exception {
     78         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
     79         keyPairGen.initialize(1024);
     80         KeyPair keyPair = keyPairGen.generateKeyPair();
     81         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
     82         RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
     83         Map<String, Object> keyMap = new HashMap<String, Object>(2);
     84         keyMap.put(PUBLIC_KEY, publicKey);
     85         keyMap.put(PRIVATE_KEY, privateKey);
     86         return keyMap;
     87     }
     88     
     89     /**
     90      * <p>
     91      * 用私钥对信息生成数字签名
     92      * </p>
     93      * 
     94      * @param data 已加密数据
     95      * @param privateKey 私钥(BASE64编码)
     96      * 
     97      * @return
     98      * @throws Exception
     99      */
    100     public static String sign(byte[] data, String privateKey) throws Exception {
    101         byte[] keyBytes = Base64Utils.decode(privateKey);
    102         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
    103         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    104         PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
    105         Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
    106         signature.initSign(privateK);
    107         signature.update(data);
    108         return Base64Utils.encode(signature.sign());
    109     }
    110 
    111     /**
    112      * <p>
    113      * 校验数字签名
    114      * </p>
    115      * 
    116      * @param data 已加密数据
    117      * @param publicKey 公钥(BASE64编码)
    118      * @param sign 数字签名
    119      * 
    120      * @return
    121      * @throws Exception
    122      * 
    123      */
    124     public static boolean verify(byte[] data, String publicKey, String sign)
    125             throws Exception {
    126         byte[] keyBytes = Base64Utils.decode(publicKey);
    127         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    128         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    129         PublicKey publicK = keyFactory.generatePublic(keySpec);
    130         Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
    131         signature.initVerify(publicK);
    132         signature.update(data);
    133         return signature.verify(Base64Utils.decode(sign));
    134     }
    135 
    136     /**
    137      * <P>
    138      * 私钥解密
    139      * </p>
    140      * 
    141      * @param encryptedData 已加密数据
    142      * @param privateKey 私钥(BASE64编码)
    143      * @return
    144      * @throws Exception
    145      */
    146     public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
    147             throws Exception {
    148         byte[] keyBytes = Base64Utils.decode(privateKey);
    149         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
    150         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    151         Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
    152         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    153         cipher.init(Cipher.DECRYPT_MODE, privateK);
    154         int inputLen = encryptedData.length;
    155         ByteArrayOutputStream out = new ByteArrayOutputStream();
    156         int offSet = 0;
    157         byte[] cache;
    158         int i = 0;
    159         // 对数据分段解密
    160         while (inputLen - offSet > 0) {
    161             if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
    162                 cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
    163             } else {
    164                 cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
    165             }
    166             out.write(cache, 0, cache.length);
    167             i++;
    168             offSet = i * MAX_DECRYPT_BLOCK;
    169         }
    170         byte[] decryptedData = out.toByteArray();
    171         out.close();
    172         return decryptedData;
    173     }
    174 
    175     /**
    176      * <p>
    177      * 公钥解密
    178      * </p>
    179      * 
    180      * @param encryptedData 已加密数据
    181      * @param publicKey 公钥(BASE64编码)
    182      * @return
    183      * @throws Exception
    184      */
    185     public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
    186             throws Exception {
    187         byte[] keyBytes = Base64Utils.decode(publicKey);
    188         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
    189         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    190         Key publicK = keyFactory.generatePublic(x509KeySpec);
    191         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    192         cipher.init(Cipher.DECRYPT_MODE, publicK);
    193         int inputLen = encryptedData.length;
    194         ByteArrayOutputStream out = new ByteArrayOutputStream();
    195         int offSet = 0;
    196         byte[] cache;
    197         int i = 0;
    198         // 对数据分段解密
    199         while (inputLen - offSet > 0) {
    200             if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
    201                 cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
    202             } else {
    203                 cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
    204             }
    205             out.write(cache, 0, cache.length);
    206             i++;
    207             offSet = i * MAX_DECRYPT_BLOCK;
    208         }
    209         byte[] decryptedData = out.toByteArray();
    210         out.close();
    211         return decryptedData;
    212     }
    213 
    214     /**
    215      * <p>
    216      * 公钥加密
    217      * </p>
    218      * 
    219      * @param data 源数据
    220      * @param publicKey 公钥(BASE64编码)
    221      * @return
    222      * @throws Exception
    223      */
    224     public static byte[] encryptByPublicKey(byte[] data, String publicKey)
    225             throws Exception {
    226         byte[] keyBytes = Base64Utils.decode(publicKey);
    227         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
    228         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    229         Key publicK = keyFactory.generatePublic(x509KeySpec);
    230         // 对数据加密
    231         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    232         cipher.init(Cipher.ENCRYPT_MODE, publicK);
    233         int inputLen = data.length;
    234         ByteArrayOutputStream out = new ByteArrayOutputStream();
    235         int offSet = 0;
    236         byte[] cache;
    237         int i = 0;
    238         // 对数据分段加密
    239         while (inputLen - offSet > 0) {
    240             if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
    241                 cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
    242             } else {
    243                 cache = cipher.doFinal(data, offSet, inputLen - offSet);
    244             }
    245             out.write(cache, 0, cache.length);
    246             i++;
    247             offSet = i * MAX_ENCRYPT_BLOCK;
    248         }
    249         byte[] encryptedData = out.toByteArray();
    250         out.close();
    251         return encryptedData;
    252     }
    253 
    254     /**
    255      * <p>
    256      * 私钥加密
    257      * </p>
    258      * 
    259      * @param data 源数据
    260      * @param privateKey 私钥(BASE64编码)
    261      * @return
    262      * @throws Exception
    263      */
    264     public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
    265             throws Exception {
    266         byte[] keyBytes = Base64Utils.decode(privateKey);
    267         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
    268         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    269         Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
    270         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    271         cipher.init(Cipher.ENCRYPT_MODE, privateK);
    272         int inputLen = data.length;
    273         ByteArrayOutputStream out = new ByteArrayOutputStream();
    274         int offSet = 0;
    275         byte[] cache;
    276         int i = 0;
    277         // 对数据分段加密
    278         while (inputLen - offSet > 0) {
    279             if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
    280                 cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
    281             } else {
    282                 cache = cipher.doFinal(data, offSet, inputLen - offSet);
    283             }
    284             out.write(cache, 0, cache.length);
    285             i++;
    286             offSet = i * MAX_ENCRYPT_BLOCK;
    287         }
    288         byte[] encryptedData = out.toByteArray();
    289         out.close();
    290         return encryptedData;
    291     }
    292 
    293     /**
    294      * <p>
    295      * 获取私钥
    296      * </p>
    297      * 
    298      * @param keyMap 密钥对
    299      * @return
    300      * @throws Exception
    301      */
    302     public static String getPrivateKey(Map<String, Object> keyMap)
    303             throws Exception {
    304         Key key = (Key) keyMap.get(PRIVATE_KEY);
    305         return Base64Utils.encode(key.getEncoded());
    306     }
    307 
    308     /**
    309      * <p>
    310      * 获取公钥
    311      * </p>
    312      * 
    313      * @param keyMap 密钥对
    314      * @return
    315      * @throws Exception
    316      */
    317     public static String getPublicKey(Map<String, Object> keyMap)
    318             throws Exception {
    319         Key key = (Key) keyMap.get(PUBLIC_KEY);
    320         return Base64Utils.encode(key.getEncoded());
    321     }
    322 
    323 }

    Base64Utils.java--BASE64编码解码工具包

      1 package com.rjs.util;
      2 
      3 import java.io.ByteArrayInputStream;
      4 import java.io.ByteArrayOutputStream;
      5 import java.io.File;
      6 import java.io.FileInputStream;
      7 import java.io.FileOutputStream;
      8 import java.io.InputStream;
      9 import java.io.OutputStream;
     10 import java.util.Base64;
     11 
     12 /*import it.sauronsoftware.base64.Base64;*/
     13 
     14 /**
     15  * <p>
     16  * BASE64编码解码工具包
     17  * </p>
     18  * <p>
     19  * 依赖javabase64-1.3.1.jar
     20  * </p>
     21  * 
     22  * @author IceWee
     23  * @date 2012-5-19
     24  * @version 1.0
     25  */
     26 public class Base64Utils {
     27 
     28     /**
     29      * 文件读取缓冲区大小
     30      */
     31     private static final int CACHE_SIZE = 1024;
     32 
     33     /**
     34      * <p>
     35      * BASE64字符串解码为二进制数据
     36      * </p>
     37      * 
     38      * @param base64
     39      * @return
     40      * @throws Exception
     41      */
     42     public static byte[] decode(String base64) throws Exception {
     43         return Base64.getDecoder().decode(base64.getBytes());
     44     }
     45 
     46     /**
     47      * <p>
     48      * 二进制数据编码为BASE64字符串
     49      * </p>
     50      * 
     51      * @param bytes
     52      * @return
     53      * @throws Exception
     54      */
     55     public static String encode(byte[] bytes) throws Exception {
     56         return new String(Base64.getEncoder().encodeToString(bytes));
     57     }
     58 
     59     /**
     60      * <p>
     61      * 将文件编码为BASE64字符串
     62      * </p>
     63      * <p>
     64      * 大文件慎用,可能会导致内存溢出
     65      * </p>
     66      * 
     67      * @param filePath
     68      *            文件绝对路径
     69      * @return
     70      * @throws Exception
     71      */
     72     public static String encodeFile(String filePath) throws Exception {
     73         byte[] bytes = fileToByte(filePath);
     74         return encode(bytes);
     75     }
     76 
     77     /**
     78      * <p>
     79      * BASE64字符串转回文件
     80      * </p>
     81      * 
     82      * @param filePath
     83      *            文件绝对路径
     84      * @param base64
     85      *            编码字符串
     86      * @throws Exception
     87      */
     88     public static void decodeToFile(String filePath, String base64) throws Exception {
     89         byte[] bytes = decode(base64);
     90         byteArrayToFile(bytes, filePath);
     91     }
     92 
     93     /**
     94      * <p>
     95      * 文件转换为二进制数组
     96      * </p>
     97      * 
     98      * @param filePath
     99      *            文件路径
    100      * @return
    101      * @throws Exception
    102      */
    103     public static byte[] fileToByte(String filePath) throws Exception {
    104         byte[] data = new byte[0];
    105         File file = new File(filePath);
    106         if (file.exists()) {
    107             FileInputStream in = new FileInputStream(file);
    108             ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
    109             byte[] cache = new byte[CACHE_SIZE];
    110             int nRead = 0;
    111             while ((nRead = in.read(cache)) != -1) {
    112                 out.write(cache, 0, nRead);
    113                 out.flush();
    114             }
    115             out.close();
    116             in.close();
    117             data = out.toByteArray();
    118         }
    119         return data;
    120     }
    121 
    122     /**
    123      * <p>
    124      * 二进制数据写文件
    125      * </p>
    126      * 
    127      * @param bytes
    128      *            二进制数据
    129      * @param filePath
    130      *            文件生成目录
    131      */
    132     public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
    133         InputStream in = new ByteArrayInputStream(bytes);
    134         File destFile = new File(filePath);
    135         if (!destFile.getParentFile().exists()) {
    136             destFile.getParentFile().mkdirs();
    137         }
    138         destFile.createNewFile();
    139         OutputStream out = new FileOutputStream(destFile);
    140         byte[] cache = new byte[CACHE_SIZE];
    141         int nRead = 0;
    142         while ((nRead = in.read(cache)) != -1) {
    143             out.write(cache, 0, nRead);
    144             out.flush();
    145         }
    146         out.close();
    147         in.close();
    148     }
    149 
    150 }

    RSATeste.java--测试类

     1 package com.rjs.util;
     2 
     3 import java.util.Map;
     4 
     5 public class RSATest {
     6 
     7     static String publicKey;
     8     static String privateKey;
     9 
    10     static {
    11         try {
    12             Map<String, Object> keyMap = RSA.genKeyPair();
    13             publicKey = RSA.getPublicKey(keyMap);
    14             privateKey = RSA.getPrivateKey(keyMap);
    15             System.err.println("公钥: 
    
    " + publicKey);
    16             System.err.println("私钥: 
    
    " + privateKey);
    17         } catch (Exception e) {
    18             e.printStackTrace();
    19         }
    20     }
    21     
    22     
    23     public static void main(String[] args) throws Exception {    
    24         test();
    25         testSign();
    26         testHttpSign();
    27     }
    28 
    29     static void test() throws Exception {    
    30         String param = "id=1&name=张三";
    31         byte[] encodedData = RSA.encryptByPrivateKey(param.getBytes(), privateKey);
    32         System.out.println("加密后:" + encodedData);
    33         
    34         byte[] decodedData = RSA.decryptByPublicKey(encodedData, publicKey);
    35         System.out.println("解密后:" + new String(decodedData));
    36         
    37         String sign = RSA.sign(encodedData, privateKey);
    38         System.err.println("签名:" + sign);
    39         
    40         boolean status = RSA.verify(encodedData, publicKey, sign);
    41         System.err.println("签名验证结果:" + status);
    42     }
    43 
    44     static void testSign() throws Exception {
    45         System.err.println("私钥加密——公钥解密");
    46         String source = "这是一行测试RSA数字签名的无意义文字";
    47         System.out.println("原文字:
    " + source);
    48         byte[] data = source.getBytes();
    49         byte[] encodedData = RSA.encryptByPrivateKey(data, privateKey);
    50         System.out.println("加密后:
    " + new String(encodedData));
    51         byte[] decodedData = RSA.decryptByPublicKey(encodedData, publicKey);
    52         String target = new String(decodedData);
    53         System.out.println("解密后: 
    " + target);
    54         System.err.println("私钥签名——公钥验证签名");
    55         String sign = RSA.sign(encodedData, privateKey);
    56         System.err.println("签名:
    " + sign);
    57         boolean status = RSA.verify(encodedData, publicKey, sign);
    58         System.err.println("验证结果:
    " + status);
    59     }
    60 
        //原文的: 61 static void testHttpSign() throws Exception { 62 System.err.println("公钥加密——私钥解密"); 63 String source = "这是一行没有任何意义的文字,你看完了等于没看,不是吗?"; 64 System.out.println(" 加密前文字: " + source); 65 byte[] data = source.getBytes(); 66 byte[] encodedData = RSA.encryptByPublicKey(data, publicKey); 67 System.out.println("加密后文字: " + new String(encodedData)); 68 byte[] decodedData = RSA.decryptByPrivateKey(encodedData, privateKey); 69 String target = new String(decodedData); 70 System.out.println("解密后文字: " + target); 71 } 72 //修改后:
        

          static void testHttpSign() throws Exception {
          System.err.println("公钥加密——私钥解密");

          //自己加一个UUID,保证加密性
          UUID uuid = UUID.randomUUID();
          String id = uuid.toString().replaceAll("-", "");    //去除UUID的"-"符号

          long time = System.currentTimeMillis();
          String source = "25,18675647281,"+time;

          System.out.println(" 加密前文字: " + source);
          byte[] data = source.getBytes();
          byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);

          String target = Base64Utils.encode(encodedData);

          System.out.printf("加密后url:?id=%s&time=%s&v=%s ", id ,time,target);

          byte[] decodedData = RSAUtils.decryptByPrivateKey(Base64Utils.decode(target), privateKey);

          System.out.println("解密后文字: " + new String(decodedData));
    }

    73 }
  • 相关阅读:
    【Python】pip导出当前项目所用的包list列表
    什么叫他妈的惊喜
    自我介绍
    IDEA创建SpringBoot时无法连接https://start.spring.io
    漫话docker的衰落与kubernetes的兴起
    基于Kubernetes和OpenKruise的可变基础设施实践
    浅析
    浅析
    浅析
    浅析
  • 原文地址:https://www.cnblogs.com/yzw23333/p/7488115.html
Copyright © 2020-2023  润新知