Java RSA加密類(RSAFromPkcs8)

 

package com.ctrip.arch.cscmws.cscmws2.util;

import java.util.List;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;

/**
 * Extract valid key content
 * 
 *    Raw Input Sample:
 -----BEGIN RSA PRIVATE KEY-----\r\nabc\r\ndef\r\n-----END RSA PRIVATE KEY-----\r\n
 
 ==>
 
 abcdef
 */
public class RsaKeyExtractor {
    private static final String COMMENT_BEGIN_FLAG = "-----";
    private static final String RETURN_FLAG_R = "\r";
    private static final String RETURN_FLAG_N = "\n";
    
    //extract valid content from rawKey(PEM format)
    public static String extractFromPem(String rawKey){
        String result = null;
        try {
            if(!Strings.isNullOrEmpty(rawKey)){
                String tmp = rawKey.replaceAll(RETURN_FLAG_R, "");
                
                
                List<String> validItemList = Lists.newArrayList();
                Iterable<String> splitIter = Splitter.on(RETURN_FLAG_N).trimResults().omitEmptyStrings().split(tmp);
                for(String str : splitIter) {
                    if(str != null && !str.startsWith(COMMENT_BEGIN_FLAG)){
                        validItemList.add(str);
                    }
                }
                Joiner joiner = Joiner.on("").skipNulls();
                result = joiner.join(validItemList);
                
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    
    
    //=== Testing ===
    public static void main(String[] args) {
        String rawKey = "-----BEGIN RSA PRIVATE KEY-----\r\nabc\r\ndef\r\n-----END RSA PRIVATE KEY-----\r\n";
        String validKey = RsaKeyExtractor.extractFromPem(rawKey);
        System.out.println(validKey);    //expect: abcdef
    }
    
    
}
RsaKeyExtractor.java

 

 

package com.ctrip.arch.cscmws.cscmws2.util;

import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;



/**
 * RSA cipher util
 *
 */
public class RsaCipherUtil {

    /**
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";
    
    /**
     * 簽名算法
     */
//    public static final String SIGNATURE_ALGORITHM_MD5 = "MD5withRSA";
    public static final String SIGNATURE_ALGORITHM_SHA1 = "SHA1withRSA";
    
    /**
     * 獲取公鑰的key
     */
    private static final String PUBLIC_KEY = "RSAPublicKey";
    
    /**
     * 獲取私鑰的key
     */
    private static final String PRIVATE_KEY = "RSAPrivateKey";
    
    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    
    /**
     * RSA最大解密密文大小
     *     注意:這個和密鑰長度有關係, 公式= 密鑰長度 / 8
     */
    private static final int MAX_DECRYPT_BLOCK = 128;

    /**
     * <p>
     * 生成密鑰對(公鑰和私鑰)
     * </p>
     * 
     * @return
     * @throws Exception
     */
    public static Map<String, Object> genKeyPair() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }
    
    /**
     * <p>
     * 用私鑰對信息生成數字簽名
     * </p>
     * 
     * @param data 已加密數據
     * @param privateKey 私鑰(BASE64編碼)
     * 
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM_SHA1);    //SIGNATURE_ALGORITHM
        signature.initSign(privateK);
        signature.update(data);
        return Base64.encodeBase64String(signature.sign());
    }

    /**
     * <p>
     * 校驗數字簽名
     * </p>
     * 
     * @param data 已加密數據
     * @param publicKey 公鑰(BASE64編碼)
     * @param sign 數字簽名
     * 
     * @return
     * @throws Exception
     * 
     */
    public static boolean verify(byte[] data, String publicKey, String sign)
            throws Exception {
        byte[] keyBytes = Base64.decodeBase64(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM_SHA1);    //SIGNATURE_ALGORITHM
        signature.initVerify(publicK);
        signature.update(data);
        return signature.verify(Base64.decodeBase64(sign));
    }

    /**
     * <P>
     * 私鑰解密
     * </p>
     * 
     * @param encryptedData 已加密數據
     * @param privateKey 私鑰(BASE64編碼)
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
            throws Exception {
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 對數據分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;
    }

    /**
     * <p>
     * 公鑰解密
     * </p>
     * 
     * @param encryptedData 已加密數據
     * @param publicKey 公鑰(BASE64編碼)
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
            throws Exception {
        byte[] keyBytes = Base64.decodeBase64(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicK);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 對數據分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;
    }

    /**
     * <p>
     * 公鑰加密
     * </p>
     * 
     * @param data 源數據
     * @param publicKey 公鑰(BASE64編碼)
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data, String publicKey)
            throws Exception {
        byte[] keyBytes = Base64.decodeBase64(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        // 對數據加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 對數據分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }

    /**
     * <p>
     * 私鑰加密
     * </p>
     * 
     * @param data 源數據
     * @param privateKey 私鑰(BASE64編碼)
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
            throws Exception {
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 對數據分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }

    /**
     * <p>
     * 獲取私鑰
     * </p>
     * 
     * @param keyMap 密鑰對
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return Base64.encodeBase64String(key.getEncoded());
    }

    /**
     * <p>
     * 獲取公鑰
     * </p>
     * 
     * @param keyMap 密鑰對
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return Base64.encodeBase64String(key.getEncoded());
    }
    
    
    //=== Testing ===
    public static void main(String[] args) {
        try {
            String input = "abc";
            String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnOi3RwVTiB0LTCV0nPfigVqyROPbBA/Qkz21DExN3rnlziQ7vjwc1EJ9n+xH/o/BNc/j6yslYMdVPDLBOZqBUiaHH2w0+DWStAZVN51ZsYdceLYh1xc9WwNgwFk7Y1ME0uVjgOiKq1nhnPOPe3GvDvsS3E+2SqNN8+NfcaCeY8QIDAQAB";
            String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKc6LdHBVOIHQtMJXSc9+KBWrJE49sED9CTPbUMTE3eueXOJDu+PBzUQn2f7Ef+j8E1z+PrKyVgx1U8MsE5moFSJocfbDT4NZK0BlU3nVmxh1x4tiHXFz1bA2DAWTtjUwTS5WOA6IqrWeGc8497ca8O+xLcT7ZKo03z419xoJ5jxAgMBAAECgYAIMPjDmIiNSQIqwjLc7dOUgj2SIEv99ZdrVWAqjYmoYbrmc0ujy/0nY6wOdNiGp11PyryvoQIVBUPhZMnrqgOnOOxPlWMDHMd6aFMfmDPqSQL5IEK982x56OCl8Z8fRe3wRZn3sT2DR1FvEJvlAFatLOzoQsLOz/ot26bjJyD8vQJBANyyjb0MZqHfuSKUT2t5VxHPsf5Xs7DleMmERqz5X4Iaj5HBUGl9Rv051Ta3oiADUM45MYkvDiOeyjhY9X6m6AcCQQDB+gxJl7qFU2pjnFhpPf/RqLzF0yri6SeXVUgcrUxj08f5+WsZdB0UaCa2+PW6R9Ln1IWl7ptD2MvekHIZYwlHAkBN0Dq/VBb/rgT1lzslVqQHaKaGWd/GWDItQxE0PbyZ/8ltB67VctFLyU9OupJUHTcpburzRn8CuiLsmRj9rdWTAkAgEov9jwzUBprMpYkovYuSyueLfgLVSd+18e/ebfj3eIjUGB1RNBWqzh24mylmB4IjusvuR6l8algrEI8NC4b5AkAlvT4xJhAASeFVxLEMWUm4uDkif9g1ruUs0J7EUHsFxffXIdAR8WXK9Nf3DdLsRLVvYka4z7VtOcucddiu1Xy/";
            
            
            byte[] cipherBytes = encryptByPublicKey(input.getBytes(), publicKey);
            String cipherText = Base64.encodeBase64String(cipherBytes);
            System.out.println("cipherText=" + cipherText);
            System.out.println("---------------------");
            
            byte[] rawBytes = decryptByPrivateKey(cipherBytes, privateKey);
            String rawText = new String(rawBytes, "UTF-8");
            System.out.println("rawText=" + rawText);
            System.out.println("---------------------");
            
            System.out.println("match ? " + (input.equals(rawText)));
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

     
}
RsaCipherUtil.java

注:若是是密鑰長度是2048,修改MAX_DECRYPT_BLOCK=256java

 

測試類:算法

package com.ctrip.arch.cscmws.cscmws2.lzyan;

import java.nio.charset.StandardCharsets;

import org.apache.commons.codec.binary.Base64;

import com.ctrip.arch.cscmws.cscmws2.util.CscmUtil;
import com.ctrip.arch.cscmws.cscmws2.util.RsaCipherUtil;
import com.ctrip.arch.cscmws.cscmws2.util.RsaKeyExtractor;


/**
 * Notice:
 *     AX00000000001436    -    公鑰
 *     SO00000000001437    -    私鑰(pkcs#1)    [bad]
 *    LP00000000003504    -    私鑰(pkcs#8)    [ok]
 *
 *        publicKey            privateKey                Length                GenByJava
 *    ------------------    ------------------        ------------------    ------------------
 *    OH00000000000119        JY00000000000120        1024                No
 *    AX00000000001436        LP00000000003504        1024                No
 *    KI00000000001530        UL00000000001531        1024                Yes
 *    UE00000000001532        ZT00000000001533        2048                Yes
 *
 */
public class lzyanTester {
    public static final String rsaPublicKeySslCode = "OH00000000000119";    //OH00000000000119         AX00000000001436    KI00000000001530
    public static final String rsaPrivateKeySslCode = "JY00000000000120";    //JY00000000000120        LP00000000003504    UL00000000001531
    
    public static void main(String[] args) throws Exception {
        String inputString = "abc";
//        String rasPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCm6TT29R9r2XF7gJu70wsKcnnRJvJTrptipOrfdQj3h3HKMPfi88iobaHWxigKC/1GsM2hMp1W4l4eEabSDn5D6KL5dUUlAWoDNIKudGHX853HQBFl0lwNE45V20zwNCj7ePI0WXyiVCycj1ojVreYG9BISA+EcELbLEmNUth+LwIDAQAB";
//        String rasPrivateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKbpNPb1H2vZcXuAm7vTCwpyedEm8lOum2Kk6t91CPeHccow9+LzyKhtodbGKAoL/UawzaEynVbiXh4RptIOfkPoovl1RSUBagM0gq50YdfzncdAEWXSXA0TjlXbTPA0KPt48jRZfKJULJyPWiNWt5gb0EhID4RwQtssSY1S2H4vAgMBAAECgYA7x2pgyInoZohuYzFjo8Jgi391mS1RK0gbnFVCkvgTLz9h2wftEMLdD+bWtUHB12lu2APNqAMSCyEKQ+grc2Vk+K2dul3f1kmpLLUJQB3UgfxX/X2Iz93wrG3gCFjN1TVLvlJ6QRk0ooD5uEluzd1J/s6+XqcfKF/KwN7B0UlRAQJBANrZ+2r44kNh2G3tPbEEZxzAo/xjBJJyAvwpoba6hygRFhORVBQ+AhXuUlSJSj6Jnhw3WVVXjs5+oDwosABXETcCQQDDPjC7/iU0l53hTXqnXenyxoSIBvXITdnQj1JaDH87LQA6/i/OXlLPMkpNoMgWeiZdj4p2D8KB1+pPIVvWqNbJAkBXKtFX9w9v1S32ArM6qU1Eh3oJUYsFpUGJHC/b7wlcLQoE+zJo6ZW9FHJYV2Jp7Dg8dtMvCbPIjWjW7UHEsOkbAkAgwiqDIF01ucqvpsRRmJxMM6rA+An9FbLaH3H90eL3FtHXFBcJVSInyZRV+ggYXV5ajF76+CH2jzetFzfFiIahAkEAioiQL7ancrccQYL1SNpRzx/mZWyXieQexpj7nW1ORNoOwPtxWyD0pVQdLihwkAed1wURQg3sHIZmK18S8/O2jw==";

        System.out.println("\n------- Phase[1] get raw key -------");
        CscmUtil cscmUtilInstance = CscmUtil.getInstance();        
        String rasPublicKey = cscmUtilInstance.getSignature(rsaPublicKeySslCode);
        String rasPrivateKey = cscmUtilInstance.getSignature(rsaPrivateKeySslCode);
        System.out.println("rasPublicKey=" + rasPublicKey);
        System.out.println("rasPrivateKey=" + rasPrivateKey);
        

        System.out.println("\n------- Phase[2] extract key -------");
        rasPublicKey = RsaKeyExtractor.extractFromPem(rasPublicKey);
        rasPrivateKey = RsaKeyExtractor.extractFromPem(rasPrivateKey);
        System.out.println("rasPublicKey=" + rasPublicKey);
        System.out.println("rasPrivateKey=" + rasPrivateKey);
        
        
        System.out.println("\n------- Phase[3] encrypt -------");
        byte[] cipherBytes = RsaCipherUtil.encryptByPublicKey(inputString.getBytes(), rasPublicKey);
        String cipherText = Base64.encodeBase64String(cipherBytes);
        System.out.println("cipherText=" + cipherText);
        
        
        System.out.println("\n------- Phase[4] decrypt -------");
        byte[] rawBytes = RsaCipherUtil.decryptByPrivateKey(cipherBytes, rasPrivateKey);
        String decryptText = new String(rawBytes, StandardCharsets.UTF_8);    //"UTF-8"
        System.out.println("inputString=" + inputString + ", decryptText=" + decryptText);
        
        
        System.out.println("\n------- Phase[5] sign -------");
        String sign = RsaCipherUtil.sign(inputString.getBytes(), rasPrivateKey);
        System.out.println("sign=" + sign);
        
        
        System.out.println("\n------- Phase[6] verify -------");
        boolean verifyResult = RsaCipherUtil.verify(inputString.getBytes(), rasPublicKey, sign);
        System.out.println("verifyResult=" + verifyResult);
        
        System.out.println("========================== over ==========================");
        
        
    }

}
lzyanTester.java
相關文章
相關標籤/搜索