zoukankan      html  css  js  c++  java
  • 使用非对称算法RSA实现加解密和使用签名算法SHA1WithRSA、MD5withRSA生成签名以及验签

    不啰嗦,直接上源码

      1 package com.hudai.platform.manager.util;
      2 
      3 import java.io.ByteArrayOutputStream;
      4 import java.io.IOException;
      5 import java.io.StringWriter;
      6 import java.io.UnsupportedEncodingException;
      7 import java.security.Key;
      8 import java.security.KeyFactory;
      9 import java.security.KeyPair;
     10 import java.security.KeyPairGenerator;
     11 import java.security.NoSuchAlgorithmException;
     12 import java.security.PrivateKey;
     13 import java.security.PublicKey;
     14 import java.security.interfaces.RSAPrivateKey;
     15 import java.security.interfaces.RSAPublicKey;
     16 import java.security.spec.InvalidKeySpecException;
     17 import java.security.spec.PKCS8EncodedKeySpec;
     18 import java.security.spec.X509EncodedKeySpec;
     19 import java.util.HashMap;
     20 import java.util.Map;
     21 
     22 import javax.crypto.Cipher;
     23 
     24 import org.apache.commons.codec.binary.Base64;
     25 import org.apache.tomcat.util.http.fileupload.IOUtils;
     26 import org.bouncycastle.asn1.ASN1Encodable;
     27 import org.bouncycastle.asn1.ASN1Primitive;
     28 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
     29 import org.bouncycastle.util.io.pem.PemObject;
     30 import org.bouncycastle.util.io.pem.PemWriter;
     31 import org.slf4j.Logger;
     32 import org.slf4j.LoggerFactory;
     33 
     34 /**
     35  * @author WanHongLei
     36  * @version 创建时间:2019年2月13日 上午10:27:06 类说明
     37  */
     38 public class RSAUtils {
     39     /**
     40      * 字符串编码
     41      */
     42     public static final String CHARSET = "UTF-8";
     43     /**
     44      * 加密算法RSA
     45      */
     46     public static final String RSA_ALGORITHM = "RSA";
     47     /**
     48      * 签名算法
     49      */
     50     public static final String SIGNATURE_ALGORITHM = "SHA1WithRSA";// SHA1WithRSA MD5withRSA
     51     
     52     private static final Logger logger = LoggerFactory.getLogger(RSAUtils.class);
     53 
     54     /**
     55      * 创建公钥私钥
     56      * 
     57      * @param keySize
     58      *            1024 2048
     59      * @return
     60      */
     61     public static Map<String, String> createKeys(int keySize) {
     62         // 为RSA算法创建一个KeyPairGenerator对象
     63         KeyPairGenerator kpg;
     64         try {
     65             kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
     66         } catch (NoSuchAlgorithmException e) {
     67             throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
     68         }
     69 
     70         // 初始化KeyPairGenerator对象,密钥长度
     71         kpg.initialize(keySize);
     72         // 生成密匙对
     73         KeyPair keyPair = kpg.generateKeyPair();
     74         // 得到公钥
     75         Key publicKey = keyPair.getPublic();
     76         String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
     77         // 得到私钥
     78         Key privateKey = keyPair.getPrivate();
     79         String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
     80         
     81         
     82         Map<String, String> keyPairMap = new HashMap<String, String>();
     83         keyPairMap.put("publicKey", publicKeyStr);
     84         keyPairMap.put("privateKeyOfPKCS8", privateKeyStr);
     85         keyPairMap.put("privateKeyOfPKCS1", getPrivateKeyOfPKCS1(privateKeyStr));
     86 
     87         return keyPairMap;
     88     }
     89 
     90     /**
     91      * 得到公钥
     92      * 
     93      * @param publicKey
     94      *            密钥字符串(经过base64编码)
     95      * @throws Exception
     96      */
     97     public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
     98         // 通过X509编码的Key指令获得公钥对象
     99         KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
    100         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
    101         RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
    102         return key;
    103     }
    104 
    105     /**
    106      * 得到私钥pkcs8
    107      * 
    108      * @param privateKey
    109      *            密钥字符串(经过base64编码)
    110      * @throws Exception
    111      */
    112     public static RSAPrivateKey getPrivateKey(String privateKey)
    113             throws NoSuchAlgorithmException, InvalidKeySpecException {
    114         // 通过PKCS#8编码的Key指令获得私钥对象
    115         KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
    116         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
    117         RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
    118         return key;
    119     }
    120     
    121     
    122     public static String getPrivateKeyOfPKCS1(String privateKey){
    123         try {
    124             byte[] privBytes = Base64.decodeBase64(privateKey);
    125 
    126             PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privBytes);
    127             ASN1Encodable encodable = pkInfo.parsePrivateKey();
    128             ASN1Primitive primitive = encodable.toASN1Primitive();
    129             byte[] privateKeyPKCS1 = primitive.getEncoded();
    130 
    131             return pkcs1ToPem(privateKeyPKCS1,false);
    132         } catch (IOException e) {
    133             logger.error("PKCS8ToPKCS1 error", e);
    134             return null;
    135         } catch (Exception e) {
    136             logger.error("PKCS8ToPKCS1 error", e);
    137             return null;
    138         }
    139     }
    140 
    141     public static String pkcs1ToPem(byte[] pcks1KeyBytes,boolean isPublic) throws Exception{
    142         String type;
    143         if(isPublic){
    144             type = "RSA PUBLIC KEY";
    145         }else{
    146             type = "RSA PRIVATE KEY";
    147         }
    148 
    149         PemObject pemObject = new PemObject(type, pcks1KeyBytes);
    150         StringWriter stringWriter = new StringWriter();
    151         PemWriter pemWriter = new PemWriter(stringWriter);
    152         pemWriter.writeObject(pemObject);
    153         pemWriter.close();
    154         String pemString = stringWriter.toString();
    155 
    156         return pemString;
    157     }
    158 
    159     /**
    160      * 公钥加密
    161      * 
    162      * @param data
    163      * @param publicKey
    164      * @return
    165      */
    166     public static String publicEncrypt(String data, RSAPublicKey publicKey) {
    167         try {
    168             Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
    169             cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    170             return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET),
    171                     publicKey.getModulus().bitLength()));
    172         } catch (Exception e) {
    173             throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
    174         }
    175     }
    176 
    177     /**
    178      * 私钥解密
    179      * 
    180      * @param data
    181      * @param privateKey
    182      * @return
    183      */
    184 
    185     public static String privateDecrypt(String data, RSAPrivateKey privateKey) {
    186         try {
    187             Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
    188             cipher.init(Cipher.DECRYPT_MODE, privateKey);
    189             return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data),
    190                     privateKey.getModulus().bitLength()), CHARSET);
    191         } catch (Exception e) {
    192             throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
    193         }
    194     }
    195 
    196     /**
    197      * 私钥加密
    198      * 
    199      * @param data
    200      * @param privateKey
    201      * @return
    202      */
    203 
    204     public static String privateEncrypt(String data, RSAPrivateKey privateKey) {
    205         try {
    206             Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
    207             cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    208             return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET),
    209                     privateKey.getModulus().bitLength()));
    210         } catch (Exception e) {
    211             throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
    212         }
    213     }
    214 
    215     /**
    216      * 公钥解密
    217      * 
    218      * @param data
    219      * @param publicKey
    220      * @return
    221      */
    222 
    223     public static String publicDecrypt(String data, RSAPublicKey publicKey) {
    224         try {
    225             Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
    226             cipher.init(Cipher.DECRYPT_MODE, publicKey);
    227             return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data),
    228                     publicKey.getModulus().bitLength()), CHARSET);
    229         } catch (Exception e) {
    230             throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
    231         }
    232     }
    233 
    234     /**
    235      * 分段处理
    236      * 
    237      * @param cipher
    238      * @param opmode
    239      * @param datas
    240      * @param keySize
    241      * @return
    242      */
    243     private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
    244         int maxBlock = 0;
    245         if (opmode == Cipher.DECRYPT_MODE) {
    246             maxBlock = keySize / 8;
    247         } else {
    248             maxBlock = keySize / 8 - 11;
    249         }
    250         ByteArrayOutputStream out = new ByteArrayOutputStream();
    251         int offSet = 0;
    252         byte[] buff;
    253         int i = 0;
    254         try {
    255             while (datas.length > offSet) {
    256                 if (datas.length - offSet > maxBlock) {
    257                     buff = cipher.doFinal(datas, offSet, maxBlock);
    258                 } else {
    259                     buff = cipher.doFinal(datas, offSet, datas.length - offSet);
    260                 }
    261                 out.write(buff, 0, buff.length);
    262                 i++;
    263                 offSet = i * maxBlock;
    264             }
    265         } catch (Exception e) {
    266             throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
    267         }
    268         byte[] resultDatas = out.toByteArray();
    269         IOUtils.closeQuietly(out);
    270         return resultDatas;
    271     }
    272 
    273     /**
    274      * RSA签名
    275      * 
    276      * @param content
    277      *            待签名数据
    278      * @param privateKey
    279      *            商户私钥
    280      * @param encode
    281      *            字符集编码
    282      * @return 签名值
    283      */
    284     public static String sign(String content, String privateKey, String encode) {
    285         try {
    286             PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
    287 
    288             KeyFactory keyf = KeyFactory.getInstance(RSA_ALGORITHM);
    289             PrivateKey priKey = keyf.generatePrivate(priPKCS8);
    290 
    291             java.security.Signature signature = java.security.Signature.getInstance(SIGNATURE_ALGORITHM);
    292 
    293             signature.initSign(priKey);
    294             signature.update(content.getBytes(encode));
    295 
    296             byte[] signed = signature.sign();
    297 
    298             return Base64.encodeBase64URLSafeString(signed);
    299         } catch (Exception e) {
    300             throw new RuntimeException("签名发生异常", e);
    301         }
    302     }
    303 
    304     /**
    305      * RSA验签名检查
    306      * 
    307      * @param content  待签名数据
    308      * @param sign 签名值
    309      * @param publicKey 分配给开发商公钥
    310      * @param encode 字符集编码
    311      * @return 布尔值
    312      */
    313     public static boolean verify(String content, String sign, String publicKey, String encode) {
    314         try {
    315             KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
    316             byte[] encodedKey = Base64.decodeBase64(publicKey);
    317             PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
    318 
    319             java.security.Signature signature = java.security.Signature.getInstance(SIGNATURE_ALGORITHM);
    320 
    321             signature.initVerify(pubKey);
    322             signature.update(content.getBytes(encode));
    323 
    324             boolean bverify = signature.verify(Base64.decodeBase64(sign));
    325             return bverify;
    326 
    327         } catch (Exception e) {
    328             e.printStackTrace();
    329         }
    330 
    331         return false;
    332     }
    333 
    334     public static void main(String[] args) throws UnsupportedEncodingException, Exception {
    335         Map<String, String> keyMap = createKeys(2048);
    336         String publicKey = keyMap.get("publicKey");
    337         String privateKeyOfPKCS8 = keyMap.get("privateKeyOfPKCS8");
    338         String privateKeyOfPKCS1 = keyMap.get("privateKeyOfPKCS1");
    339         
    340         System.out.println("publicKey:
    " + publicKey);
    341         System.out.println("privateKeyOfPKCS8:
    " + privateKeyOfPKCS8);
    342         System.out.println("privateKeyOfPKCS1:
    " + privateKeyOfPKCS1);
    343         
    344         String src = "app_id=35456878542&biz_data={"order_no":"201811307810149579","order_status":100,"update_time":1543566391}&format=json&method=api.v2.order.orderfeedback&sign_type=RSA&timestamp=1543566391&version=1.0";
    345         
    346         String sign = sign(src, privateKeyOfPKCS8, CHARSET);
    347         System.out.println("sign:
    " + sign);
    348         
    349         boolean verify = verify(src, sign, publicKey, CHARSET);
    350         System.out.println("verify:" + verify);
    351         
    352         String privateEncrypt = privateEncrypt(src, getPrivateKey(privateKeyOfPKCS8));
    353         System.out.println("privateEncrypt:
    " + privateEncrypt);
    354         
    355         String publicDecrypt = publicDecrypt(privateEncrypt, getPublicKey(publicKey));
    356         System.out.println("publicDecrypt:
    " + publicDecrypt);
    357         
    358         String publicEncrypt = publicEncrypt(src, getPublicKey(publicKey));
    359         System.out.println("publicEncrypt:
    " + publicEncrypt);
    360         
    361         String privateDecrypt = privateDecrypt(publicEncrypt, getPrivateKey(privateKeyOfPKCS8));
    362         System.out.println("privateDecrypt:
    " + privateDecrypt);
    363         
    364     }
    365 }
  • 相关阅读:
    VS 2013 未找到与约束contractname Microsoft.VisualStudio.Utilities.IContentTypeRegistryService...匹配的导出[vs故障]【转】
    leetcode(一)Word Pattern
    [LeetCode]ZigZag Conversion
    C#元组示例详解
    C#使用委托进行异步编程。
    jQuery常用的元素查找方法总结
    泛型集合【转载】
    NPOI使用手册[转]
    总结Controller向View传值的方式(转)
    HttpHelper类
  • 原文地址:https://www.cnblogs.com/Mr-Rocker/p/10370147.html
Copyright © 2011-2022 走看看