<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    ice world

    There is nothing too difficult if you put your heart into it.
    posts - 104, comments - 103, trackbacks - 0, articles - 0

    java RSA加密解密

    Posted on 2012-05-19 16:54 IceWee 閱讀(42690) 評論(7)  編輯  收藏 所屬分類: Java加解密
    該工具類中用到了BASE64,需要借助第三方類庫:javabase64-1.3.1.jar

    注意:
    RSA加密明文最大長度117字節(jié),解密要求密文最大長度為128字節(jié),所以在加密和解密的過程中需要分塊進行。
    RSA加密對明文的長度是有限制的,如果加密數(shù)據(jù)過大會拋出如下
    異常:
    Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
        at com
    .sun.crypto.provider.RSACipher.a(DashoA13*..)
        at com
    .sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
        at javax
    .crypto.Cipher.doFinal(DashoA13*..)


    RSAUtils.java
    package security;

    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;

    /**
     * <p>
     * RSA公鑰/私鑰/簽名工具包
     * </p>
     * <p>
     * 羅納德·李維斯特(Ron [R]ivest)、阿迪·薩莫爾(Adi [S]hamir)和倫納德·阿德曼(Leonard [A]dleman)
     * </p>
     * <p>
     * 字符串格式的密鑰在未在特殊說明情況下都為BASE64編碼格式<br/>
     * 由于非對稱加密速度極其緩慢,一般文件不使用它來加密而是使用對稱加密,<br/>
     * 非對稱加密算法可以用來對對稱加密的密鑰加密,這樣保證密鑰的安全也就保證了數(shù)據(jù)的安全
     * </p>
     * 
     * 
    @author IceWee
     * @date 2012-4-26
     * 
    @version 1.0
     
    */

    public class RSAUtils {

        
    /**
         * 加密算法RSA
         
    */

        
    public static final String KEY_ALGORITHM = "RSA";
        
        
    /**
         * 簽名算法
         
    */

        
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

        
    /**
         * 獲取公鑰的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最大解密密文大小
         
    */

        
    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>
         * 用私鑰對信息生成數(shù)字簽名
         * </p>
         * 
         * 
    @param data 已加密數(shù)據(jù)
         * 
    @param privateKey 私鑰(BASE64編碼)
         * 
         * 
    @return
         * 
    @throws Exception
         
    */

        
    public static String sign(byte[] data, String privateKey) throws Exception {
            
    byte[] keyBytes = Base64Utils.decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec 
    = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory 
    = KeyFactory.getInstance(KEY_ALGORITHM);
            PrivateKey privateK 
    = keyFactory.generatePrivate(pkcs8KeySpec);
            Signature signature 
    = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(privateK);
            signature.update(data);
            
    return Base64Utils.encode(signature.sign());
        }


        
    /**
         * <p>
         * 校驗數(shù)字簽名
         * </p>
         * 
         * 
    @param data 已加密數(shù)據(jù)
         * 
    @param publicKey 公鑰(BASE64編碼)
         * 
    @param sign 數(shù)字簽名
         * 
         * 
    @return
         * 
    @throws Exception
         * 
         
    */

        
    public static boolean verify(byte[] data, String publicKey, String sign)
                
    throws Exception {
            
    byte[] keyBytes = Base64Utils.decode(publicKey);
            X509EncodedKeySpec keySpec 
    = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory 
    = KeyFactory.getInstance(KEY_ALGORITHM);
            PublicKey publicK 
    = keyFactory.generatePublic(keySpec);
            Signature signature 
    = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(publicK);
            signature.update(data);
            
    return signature.verify(Base64Utils.decode(sign));
        }


        
    /**
         * <P>
         * 私鑰解密
         * </p>
         * 
         * 
    @param encryptedData 已加密數(shù)據(jù)
         * 
    @param privateKey 私鑰(BASE64編碼)
         * 
    @return
         * 
    @throws Exception
         
    */

        
    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
                
    throws Exception {
            
    byte[] keyBytes = Base64Utils.decode(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;
            
    // 對數(shù)據(jù)分段解密
            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 已加密數(shù)據(jù)
         * 
    @param publicKey 公鑰(BASE64編碼)
         * 
    @return
         * 
    @throws Exception
         
    */

        
    public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
                
    throws Exception {
            
    byte[] keyBytes = Base64Utils.decode(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;
            
    // 對數(shù)據(jù)分段解密
            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 源數(shù)據(jù)
         * 
    @param publicKey 公鑰(BASE64編碼)
         * 
    @return
         * 
    @throws Exception
         
    */

        
    public static byte[] encryptByPublicKey(byte[] data, String publicKey)
                
    throws Exception {
            
    byte[] keyBytes = Base64Utils.decode(publicKey);
            X509EncodedKeySpec x509KeySpec 
    = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory 
    = KeyFactory.getInstance(KEY_ALGORITHM);
            Key publicK 
    = keyFactory.generatePublic(x509KeySpec);
            
    // 對數(shù)據(jù)加密
            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;
            
    // 對數(shù)據(jù)分段加密
            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 源數(shù)據(jù)
         * 
    @param privateKey 私鑰(BASE64編碼)
         * 
    @return
         * 
    @throws Exception
         
    */

        
    public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
                
    throws Exception {
            
    byte[] keyBytes = Base64Utils.decode(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;
            
    // 對數(shù)據(jù)分段加密
            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 Base64Utils.encode(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 Base64Utils.encode(key.getEncoded());
        }


    }



    Base64Utils.java
    package security;

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;

    import it.sauronsoftware.base64.Base64;

    /**
    * <p>
    * BASE64編碼解碼工具包
    * </p>
    * <p>
    * 依賴javabase64-1.3.1.jar
    * </p>
    *
    *
    @author IceWee
    * @date 2012-5-19
    *
    @version 1.0
    */

    public class Base64Utils {

       
    /**
         * 文件讀取緩沖區(qū)大小
        
    */

       
    private static final int CACHE_SIZE = 1024;
       
       
    /**
         * <p>
         * BASE64字符串解碼為二進制數(shù)據(jù)
         * </p>
         *
         *
    @param base64
         *
    @return
         *
    @throws Exception
        
    */

       
    public static byte[] decode(String base64) throws Exception {
           
    return Base64.decode(base64.getBytes());
        }

       
       
    /**
         * <p>
         * 二進制數(shù)據(jù)編碼為BASE64字符串
         * </p>
         *
         *
    @param bytes
         *
    @return
         *
    @throws Exception
        
    */

       
    public static String encode(byte[] bytes) throws Exception {
           
    return new String(Base64.encode(bytes));
        }

       
       
    /**
         * <p>
         * 將文件編碼為BASE64字符串
         * </p>
         * <p>
         * 大文件慎用,可能會導致內(nèi)存溢出
         * </p>
         *
         *
    @param filePath 文件絕對路徑
         *
    @return
         *
    @throws Exception
        
    */

       
    public static String encodeFile(String filePath) throws Exception {
           
    byte[] bytes = fileToByte(filePath);
           
    return encode(bytes);
        }

       
       
    /**
         * <p>
         * BASE64字符串轉(zhuǎn)回文件
         * </p>
         *
         *
    @param filePath 文件絕對路徑
         *
    @param base64 編碼字符串
         *
    @throws Exception
        
    */

       
    public static void decodeToFile(String filePath, String base64) throws Exception {
           
    byte[] bytes = decode(base64);
            byteArrayToFile(bytes, filePath);
        }

       
       
    /**
         * <p>
         * 文件轉(zhuǎn)換為二進制數(shù)組
         * </p>
         *
         *
    @param filePath 文件路徑
         *
    @return
         *
    @throws Exception
        
    */

       
    public static byte[] fileToByte(String filePath) throws Exception {
           
    byte[] data = new byte[0];
            File file
    = new File(filePath);
           
    if (file.exists()) {
                FileInputStream in
    = new FileInputStream(file);
                ByteArrayOutputStream out
    = new ByteArrayOutputStream(2048);
               
    byte[] cache = new byte[CACHE_SIZE];
               
    int nRead = 0;
               
    while ((nRead = in.read(cache)) != -1) {
                    out.write(cache,
    0, nRead);
                    out.flush();
                }

                out.close();
                in.close();
                data
    = out.toByteArray();
             }

           
    return data;
        }

       
       
    /**
         * <p>
         * 二進制數(shù)據(jù)寫文件
         * </p>
         *
         *
    @param bytes 二進制數(shù)據(jù)
         *
    @param filePath 文件生成目錄
        
    */

       
    public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
            InputStream in
    = new ByteArrayInputStream(bytes);  
            File destFile
    = new File(filePath);
           
    if (!destFile.getParentFile().exists()) {
                destFile.getParentFile().mkdirs();
            }

            destFile.createNewFile();
            OutputStream out
    = new FileOutputStream(destFile);
           
    byte[] cache = new byte[CACHE_SIZE];
           
    int nRead = 0;
           
    while ((nRead = in.read(cache)) != -1) {  
                out.write(cache,
    0, nRead);
                out.flush();
            }

            out.close();
            in.close();
        }

       
       
    }



    RSATester.java
    package security;

    import java.util.Map;

    public class RSATester {

       
    static String publicKey;
       
    static String privateKey;

       
    static {
           
    try {
                Map
    <String, Object> keyMap = RSAUtils.genKeyPair();
                publicKey
    = RSAUtils.getPublicKey(keyMap);
                privateKey
    = RSAUtils.getPrivateKey(keyMap);
                System.err.println(
    "公鑰: \n\r" + publicKey);
                System.err.println(
    "私鑰: \n\r" + privateKey);
            }
    catch (Exception e) {
                e.printStackTrace();
            }

        }

       
       
    public static void main(String[] args) throws Exception {
            test();
            testSign();
        }


       
    static void test() throws Exception {
            System.err.println(
    "公鑰加密——私鑰解密");
            String source
    = "這是一行沒有任何意義的文字,你看完了等于沒看,不是嗎?";
            System.out.println(
    "\r加密前文字:\r\n" + source);
           
    byte[] data = source.getBytes();
           
    byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);
            System.out.println(
    "加密后文字:\r\n" + new String(encodedData));
           
    byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);
            String target
    = new String(decodedData);
            System.out.println(
    "解密后文字: \r\n" + target);
        }


       
    static void testSign() throws Exception {
            System.err.println(
    "私鑰加密——公鑰解密");
            String source
    = "這是一行測試RSA數(shù)字簽名的無意義文字";
            System.out.println(
    "原文字:\r\n" + source);
           
    byte[] data = source.getBytes();
           
    byte[] encodedData = RSAUtils.encryptByPrivateKey(data, privateKey);
            System.out.println(
    "加密后:\r\n" + new String(encodedData));
           
    byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);
            String target
    = new String(decodedData);
            System.out.println(
    "解密后: \r\n" + target);
            System.err.println(
    "私鑰簽名——公鑰驗證簽名");
            String sign
    = RSAUtils.sign(encodedData, privateKey);
            System.err.println(
    "簽名:\r" + sign);
           
    boolean status = RSAUtils.verify(encodedData, publicKey, sign);
            System.err.println(
    "驗證結(jié)果:\r" + status);
        }

       
    }

    Feedback

    # re: java RSA加密解密  回復  更多評論   

    2012-11-15 12:12 by yours
    樓主不厚道,import it.sauronsoftware.base64.Base64;在哪兒?

    # re: java RSA加密解密  回復  更多評論   

    2012-11-15 21:53 by IceWee
    @yours
    自己下載一下吧!百度一下javabase64-1.3.1.jar!GCD不給力,谷歌被和諧了,詛咒一下!~

    # re: java RSA加密解密[未登錄]  回復  更多評論   

    2013-05-05 12:08 by Alan
    很不錯,不過Base64的那個其實可以直接用common-codec里面的工具,沒必要自己寫一份了,呵呵

    # re: java RSA加密解密  回復  更多評論   

    2013-07-22 20:02 by Juwend
    如果被加密的明文使用

    String ming = ((char) 134) + "";

    即使用asc碼大于127或者小于0的這種字符組成字符串
    加密之后再解密
    拿明文ming對比解密的數(shù)據(jù),使用equal方法,會得到false,意思就是加解密肯定出了問題,我目測應該是加密的時候出的問題
    這種問題如何解決,謝謝!

    # re: java RSA加密解密  回復  更多評論   

    2014-06-03 15:08 by roby
    數(shù)據(jù)量大了 如10M 那么無法加密和解密了

    # re: java RSA加密解密  回復  更多評論   

    2014-08-27 15:06 by kaifa
    我把數(shù)據(jù)加密存儲到本地,然后退出程序,再次進入程序,對讀取到保存的加密字符串,然后解密,這是后解密就會出亂碼問題。。可能是因為每次產(chǎn)生的privatekey都不同導致的,怎么解決?LZ

    # re: java RSA加密解密  回復  更多評論   

    2015-12-06 02:30 by 張翰
    沒有主函數(shù)?
    主站蜘蛛池模板: 丰满人妻一区二区三区免费视频| 精品亚洲永久免费精品| 亚洲AV午夜成人片| 亚洲国产中文在线视频| 亚洲色图国产精品| 在线免费观看亚洲| 久久精品亚洲日本波多野结衣| 亚洲日产乱码一二三区别 | 91av免费观看| 无码专区一va亚洲v专区在线| 久久综合亚洲色HEZYO社区| 边摸边吃奶边做爽免费视频99| 亚洲av成人一区二区三区在线播放| 免费人成毛片动漫在线播放| 精品国产一区二区三区免费看| 亚洲国产精品一区第二页| 亚洲精品人成在线观看| 国产精品亚洲专区无码牛牛| 免费人成在线观看69式小视频| 免费无码又爽又高潮视频 | 亚洲AV无码AV日韩AV网站| 日韩成人免费视频| 免费99精品国产自在现线| 日本黄色免费观看| 亚洲国产V高清在线观看| 亚洲av无码不卡久久| 国产99久久亚洲综合精品| 91高清免费国产自产| 亚洲色成人WWW永久网站| 国产精品亚洲精品日韩动图 | 国产精品免费小视频| 亚洲 综合 国产 欧洲 丝袜| 亚洲伊人精品综合在合线| 免费看无码特级毛片| 亚洲高清成人一区二区三区 | 一本久久免费视频| 午夜免费啪视频在线观看| 成年人免费视频观看| 最新国产AV无码专区亚洲 | 免费少妇a级毛片人成网| 亚洲国产日韩视频观看|