天天看點

RSA工具類

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.security.Key;
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.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import com.ykx.orderCenter.dubbo.security.StreamUtil;
import sun.misc.BASE64Decoder;

/**   
 * 類名稱:util   
 * 類描述:   
 * 建立人:Administrator
 * 建立時間:2019年7月23日 下午4:22:13   
 * 修改人:Administrator
 * 修改時間:2019年7月23日 下午4:22:13   
 * 修改備注:   
 * @version       
 */

public class RSASignUtil {
	/**	簽名算法 */
    private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
    
    /**	簽名類型*/
    private static final String SIGN_TYPE_RSA = "RSA";
    
    /**	算法長度,預設2048*/
    public static final int KEY_SIZE = 2048;
    
    /**
     *	 初始化RSA算法密鑰對
     *
     * @param keysize RSA1024已經不安全了,建議2048
     * @return 經過Base64編碼後的公私鑰Map, 鍵名分别為publicKey和privateKey
     */
    public static Map<String, String> initRSAKey(int keysize) {
        if (keysize != KEY_SIZE) {
            throw new IllegalArgumentException("RSA1024已經不安全了,請使用" + KEY_SIZE + "初始化RSA密鑰對");
        }
        //為RSA算法建立一個KeyPairGenerator對象
        KeyPairGenerator kpg;
        try {
            kpg = KeyPairGenerator.getInstance(SIGN_TYPE_RSA);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException("No such algorithm-->[" + SIGN_TYPE_RSA + "]");
        }
        //初始化KeyPairGenerator對象,不要被initialize()源碼表面上欺騙,其實這裡聲明的size是生效的
        kpg.initialize(KEY_SIZE);
        //生成密匙對
        KeyPair keyPair = kpg.generateKeyPair();
        //得到公鑰
        Key publicKey = keyPair.getPublic();
        String publicKeyStr = java.util.Base64.getEncoder().encodeToString(publicKey.getEncoded());
        //得到私鑰
        Key privateKey = keyPair.getPrivate();
        String privateKeyStr = java.util.Base64.getEncoder().encodeToString(privateKey.getEncoded());
        Map<String, String> keyPairMap = new HashMap<String, String>();
        keyPairMap.put("publicKey", publicKeyStr);
        keyPairMap.put("privateKey", privateKeyStr);
        return keyPairMap;
    }
   
    
   
    /**
     * 
     * @Description: 字元串轉公鑰方法1
     * @param:@param key
     * @param:@return
     * @param:@throws Exception
     * @return:PublicKey
     * @throws:
     *
     * @version: v1.0.0
     * @author: Administrator
     * @date: 2019年7月24日 上午11:06:36 
     */
    public static PublicKey getPublicKeyFromX509(String key) throws Exception {
    	InputStream ins=new ByteArrayInputStream(key.getBytes());
        KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE_RSA);
        StringWriter writer = new StringWriter();
        StreamUtil.io(new InputStreamReader(ins), writer);
        byte[] encodedKey = writer.toString().getBytes();
        encodedKey = Base64.decodeBase64(encodedKey);
        return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
    }
    
    
    /**
     * 
     * @Description: 字元串轉公鑰方法2
     * @param:@param key
     * @param:@return
     * @param:@throws Exception
     * @return:PublicKey
     * @throws:
     *
     * @version: v1.0.0
     * @author: Administrator
     * @date: 2019年7月24日 上午11:06:36 
     */
    public static PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE_RSA);
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
  }

    /**
     * 
     * @Description: 字元串轉私鑰方法1
     * @param:@param key
     * @param:@return
     * @param:@throws Exception
     * @return:PrivateKey
     * @throws:
     *
     * @version: v1.0.0
     * @author: Administrator
     * @date: 2019年7月24日 上午11:06:39 
     */
    public static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        //	通過PKCS#8編碼的Key指令獲得私鑰對象
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE_RSA);
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
  }
    
    /**
     * 
     * @Description: TODO字元串轉私鑰方法2
     * @param:@param key
     * @param:@return
     * @param:@throws Exception
     * @return:PrivateKey
     * @throws:
     * @version: v1.0.0
     * @author: Administrator
     * @date: 2019年11月12日 下午4:56:50
     */
    public static PrivateKey getPrivateKeyFromPKCS8(String key) throws Exception {
    	InputStream ins=new ByteArrayInputStream(key.getBytes());
    	if (ins == null || StringUtils.isEmpty(SIGN_TYPE_RSA)) {
            return null;
        }
        KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE_RSA);
        byte[] encodedKey = StreamUtil.readText(ins).getBytes();
        encodedKey = Base64.decodeBase64(encodedKey);
        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
    }
    /**
     * 
     * @Description: 處理待加密資料處理為URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字元串stringA。
     * 	特别注意以下重要規則:
	 *	  	◆ 參數名ASCII碼從小到大排序(字典序);
	 *  	◆ 如果參數的值為空不參與簽名; 
	 *  	◆ 參數名區分大小寫; 
     * @param:@param params
     * @param:@return
     * @return:String
     * @throws:
     * @version: v1.0.0
     * @author: Administrator
     * @date: 2019年11月12日 下午2:09:36
     */
    public static String getSignCheckContent(Map<String, String> params) {
        if (params == null) {
            return null;
        }
        StringBuffer content = new StringBuffer();
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            content.append((i == 0 ? "" : "&") + key + "=" + value);
        }
        return content.toString();
    }
    
	/**
	 * 	 私鑰簽名
     * 
     * @param data 待簽名的明文字元串
     * @param privateKey RSA私鑰字元串
     * @return RSA私鑰簽名後的經過Base64編碼的字元串
	 * @throws Exception 
     */
	@SuppressWarnings("unused")
	private static String sign(String data, String privateKey,String charset){
	    	  try {
	    		PrivateKey priKey =getPrivateKey(privateKey);
		        Signature signature = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
		        signature.initSign(priKey);
		        if (StringUtils.isEmpty(charset)) {
		            signature.update(data.getBytes());
		        } else {
		            signature.update(data.getBytes(charset));
		        }
			 return new String(Base64.encodeBase64(signature.sign()));
//			 return Base64.getEncoder().encodeToString(signature.sign());
	    } catch (Exception e) {
	    	throw new RuntimeException("簽名字元串[" + data + " ]時遇到異常", e);
	    }
    }
    
 
    
    /**
               * 公鑰 驗簽
     * @param srcData 原始字元串
     * @param publicKey 公鑰
     * @param sign 簽名
     * @return 是否驗簽通過
     */
    @SuppressWarnings("unused")
	private static boolean verify(String data, String publicKey, String sign,String charset){
	    try {
	    	PublicKey pubKey = getPublicKey(publicKey);
	        Signature signature = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
	        signature.initVerify(pubKey);
	        if (StringUtils.isEmpty(charset)) {
	            signature.update(data.getBytes());
	        } else {
	            signature.update(data.getBytes(charset));
	        }
	        return signature.verify(Base64.decodeBase64(sign.getBytes()));
	    } catch (Exception e) {
	    	 throw new RuntimeException("驗簽字元串[" + data + "	]時遇到異常", e);
	    }
    }
    
    /**
     * 
     * @Description: 公鑰驗簽
     * @param:@param params
     * @param:@param publicKey
     * @param:@param charset
     * @param:@param sign
     * @param:@return
     * @return:boolean
     * @throws:
     * @version: v1.0.0
     * @author: Administrator
     * @date: 2019年11月12日 下午2:12:38
     */
    public static boolean rsa256Check(Map<String, String> params, String publicKey, String charset,String sign) {
        String content = getSignCheckContent(params);
        return verify(content, sign, publicKey, charset);
    }
    
    
   
    
}