Java安全編程:RSA加密解密

安全 RSA

  • RSA是最常用非對稱加密算法。常用于消息簽名。它的加解密的密鑰是成對出現(xiàn)的价说。使用私鑰加密只能用對應的公鑰才能解密瞎疼。這樣防止了類似DES等對稱加密算法的密鑰傳輸?shù)膯栴}。其加密效率比DES慢撇眯。
  • 詳細內容請查看:http://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95
/**
 * RSA算法加密解密例子
 * 注意:RSA加密對明文的長度是有限制的,RSA加密明文最大長度117字節(jié),解密要求密文最大長度為128字節(jié)会涎,所以在加密和解密的過程中需要分塊進行。
 * 
 */
public class RSACoder extends TestCase {

    /**
     * 測試用私鑰加密再用公鑰解密
     * 
     * @throws Exception
     */
    public void test1() throws Exception {
        byte[] arr = this.readFileIntoByteArr(new File("D:/data.txt"));
        System.out.println("加密前的明文:" + new String(arr, "GBK"));

        Map<String, Object> keyMap = this.initKey();
        PrivateKey priKey = (PrivateKey) keyMap.get("PrivateKey");
        PublicKey pubKey = (PublicKey) keyMap.get("PublicKey");

        byte[] encryptData = this.encryptByPriKey(arr, priKey.getEncoded());
        System.out.println("密文:" + Hex.encodeHexString(encryptData));

        byte[] data = this.decryptByPubKey(encryptData, pubKey.getEncoded());
        System.out.println("解密后的明文:" + new String(data, "GBK"));
    }

    /**
     * 測試數(shù)字簽名與驗簽
     * 
     * @throws Exception
     */
    public void test2() throws Exception {
        byte[] arr = this.readFileIntoByteArr(new File("D:/data.txt"));
        System.out.println("簽名主體:" + new String(arr, "GBK"));

        Map<String, Object> keyMap = this.initKey();
        PrivateKey priKey = (PrivateKey) keyMap.get("PrivateKey");
        PublicKey pubKey = (PublicKey) keyMap.get("PublicKey");

        byte[] sign = this.sign(arr, priKey.getEncoded());
        System.out.println("簽名:" + Hex.encodeHexString(sign));

        boolean b = this.verify(arr, pubKey.getEncoded(), sign);
        System.out.println(b ? "驗簽成功" : "驗簽失敗");
    }

    /**
     * 測試直接對主體簽名與先對主體加摘要再簽名得到的簽名是不一樣的瑞凑。
     * 
     * @throws Exception
     */
    public void test3() throws Exception {
        byte[] arr = this.readFileIntoByteArr(new File("D:/data.txt"));
        System.out.println("簽名主體:" + new String(arr, "GBK"));

        Map<String, Object> keyMap = this.initKey();
        PrivateKey priKey = (PrivateKey) keyMap.get("PrivateKey");
        PublicKey pubKey = (PublicKey) keyMap.get("PublicKey");
        // 直接簽名
        byte[] sign1 = this.sign(arr, priKey.getEncoded());
        System.out.println("簽名:" + Hex.encodeHexString(sign1));

        // 先得到MD5摘要再簽名
        byte[] md5 = DigestUtils.md5(arr);
        byte[] sign2 = this.sign(md5, priKey.getEncoded());
        System.out.println("簽名:" + Hex.encodeHexString(sign2));
    }

    /**
     * 生成密鑰對
     * 
     * @return
     * @throws NoSuchAlgorithmException
     */
    public Map<String, Object> initKey() throws NoSuchAlgorithmException {
        // 實例化密鑰對生成器
        KeyPairGenerator gener = KeyPairGenerator.getInstance("RSA");
        gener.initialize(1024);
        KeyPair pair = gener.generateKeyPair();
        PrivateKey priKey = pair.getPrivate();
        PublicKey pubKey = pair.getPublic();

        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put("PrivateKey", priKey);
        keyMap.put("PublicKey", pubKey);

        System.out.println("私鑰:" + Hex.encodeHexString(priKey.getEncoded()));
        System.out.println("公鑰:" + Hex.encodeHexString(pubKey.getEncoded()));

        return keyMap;
    }

    /**
     * 讀取文件內容到byte數(shù)組
     * 
     * @param file
     * @return
     * @throws IOException
     */
    public byte[] readFileIntoByteArr(File file) throws IOException {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        try {
            FileInputStream in = new FileInputStream(file);
            byte[] tmpbuf = new byte[1024];
            int count = 0;
            while ((count = in.read(tmpbuf)) != -1) {
                bout.write(tmpbuf, 0, count);
                tmpbuf = new byte[1024];
            }
            in.close();
        } catch (FileNotFoundException e) {
            throw new FileNotFoundException("文件" + file.getPath() + "不存在");
        } catch (IOException e) {
            throw new IOException("讀取文件內容到BYTE數(shù)組中出現(xiàn)IO異常", e);
        }
        return bout.toByteArray();
    }

    /**
     * 私鑰加密
     * 
     * @param data
     * @param priKeyByte
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public byte[] encryptByPriKey(byte[] data, byte[] priKeyByte) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException,
            InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // 獲取私鑰
        KeySpec spec = new PKCS8EncodedKeySpec(priKeyByte);
        // 生成私鑰
        Key priKey = keyFactory.generatePrivate(spec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, priKey);
        return cipher.doFinal(data);
    }

    /**
     * 公鑰解密
     * 
     * @param data
     * @param pubKeyByte
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public byte[] decryptByPubKey(byte[] data, byte[] pubKeyByte) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException,
            InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // 獲取公鑰
        KeySpec spec = new X509EncodedKeySpec(pubKeyByte);
        // 生成公鑰
        Key pubKey = keyFactory.generatePublic(spec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, pubKey);
        return cipher.doFinal(data);
    }

    /**
     * 使用MD5withRSA算法末秃,加簽
     * 
     * @param data
     * @param priKeyByte
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws InvalidKeyException
     * @throws SignatureException
     */
    public byte[] sign(byte[] data, byte[] priKeyByte) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // 獲取私鑰
        KeySpec spec = new PKCS8EncodedKeySpec(priKeyByte);
        // 生成私鑰
        PrivateKey priKey = keyFactory.generatePrivate(spec);

        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initSign(priKey);
        signature.update(data);

        return signature.sign();
    }

    /**
     * 使用MD5withRSA算法,解簽
     * 
     * @param data
     * @param pubKeyByte
     * @param sign
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws InvalidKeyException
     * @throws SignatureException
     */
    public boolean verify(byte[] data, byte[] pubKeyByte, byte[] sign) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException,
            SignatureException {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // 獲取公鑰
        KeySpec spec = new X509EncodedKeySpec(pubKeyByte);
        // 生成公鑰
        PublicKey pubKey = keyFactory.generatePublic(spec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(pubKey);
        signature.update(data);
        return signature.verify(sign);
    }

}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末籽御,一起剝皮案震驚了整個濱河市练慕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌技掏,老刑警劉巖铃将,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哑梳,居然都是意外死亡劲阎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門鸠真,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悯仙,“玉大人,你說我怎么就攤上這事吠卷∥ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵撤嫩,是天一觀的道長偎捎。 經常有香客問我,道長序攘,這世上最難降的妖魔是什么茴她? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮程奠,結果婚禮上丈牢,老公的妹妹穿的比我還像新娘。我一直安慰自己瞄沙,他們只是感情好己沛,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布慌核。 她就那樣靜靜地躺著,像睡著了一般申尼。 火紅的嫁衣襯著肌膚如雪垮卓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天师幕,我揣著相機與錄音粟按,去河邊找鬼。 笑死霹粥,一個胖子當著我的面吹牛灭将,可吹牛的內容都是我干的。 我是一名探鬼主播后控,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼庙曙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了浩淘?” 一聲冷哼從身側響起捌朴,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎张抄,沒想到半個月后男旗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡欣鳖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了茴厉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泽台。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖矾缓,靈堂內的尸體忽然破棺而出怀酷,到底是詐尸還是另有隱情,我是刑警寧澤嗜闻,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布蜕依,位于F島的核電站,受9級特大地震影響琉雳,放射性物質發(fā)生泄漏样眠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一翠肘、第九天 我趴在偏房一處隱蔽的房頂上張望檐束。 院中可真熱鬧,春花似錦束倍、人聲如沸被丧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甥桂。三九已至柿究,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間黄选,已是汗流浹背蝇摸。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留糕簿,地道東北人探入。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像懂诗,于是被迫代替她去往敵國和親蜂嗽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內容

  • ¥開啟¥ 【雷霆戰(zhàn)機】 〖http://pan.baidu.com/s/1kVstszX〗 《解壓源碼后直接用AI...
    小菜c閱讀 3,676評論 0 5
  • @synthesize和@dynamic分別有什么作用?@property有兩個對應的詞离唐,一個是 @synthes...
    筆筆請求閱讀 508評論 0 1
  • 轉載 http://blog.csdn.net/bbld_/article/details/38777491RSA...
    samychen閱讀 14,816評論 3 16
  • 啊今天有多么美好啊亥鬓,我的兩幅圖多么的美完沪,美呀,哈哈哈哈嵌戈,今天有我非常非常的瞌睡覆积,可是要堅持的,做簡書熟呛,做完以后我就...
    又呆又萌的萌閱讀 311評論 0 0
  • https://ke.qq.com/course/87173先看相機的兩個裝置宽档,如下圖 調焦環(huán)和設置調焦模式 調焦...
    edison0428閱讀 439評論 0 0