Java安全編程:RSA加密解密

安全 RSA

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

    /**
     * 測(cè)試用私鑰加密再用公鑰解密
     * 
     * @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"));
    }

    /**
     * 測(cè)試數(shù)字簽名與驗(yàn)簽
     * 
     * @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 ? "驗(yàn)簽成功" : "驗(yàn)簽失敗");
    }

    /**
     * 測(cè)試直接對(duì)主體簽名與先對(duì)主體加摘要再簽名得到的簽名是不一樣的。
     * 
     * @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));
    }

    /**
     * 生成密鑰對(duì)
     * 
     * @return
     * @throws NoSuchAlgorithmException
     */
    public Map<String, Object> initKey() throws NoSuchAlgorithmException {
        // 實(shí)例化密鑰對(duì)生成器
        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;
    }

    /**
     * 讀取文件內(nèi)容到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("讀取文件內(nèi)容到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);
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ¥開(kāi)啟¥ 【雷霆戰(zhàn)機(jī)】 〖http://pan.baidu.com/s/1kVstszX〗 《解壓源碼后直接用AI...
    小菜c閱讀 4,026評(píng)論 0 5
  • @synthesize和@dynamic分別有什么作用?@property有兩個(gè)對(duì)應(yīng)的詞,一個(gè)是 @synthes...
    筆筆請(qǐng)求閱讀 645評(píng)論 0 1
  • 轉(zhuǎn)載 http://blog.csdn.net/bbld_/article/details/38777491RSA...
    samychen閱讀 15,293評(píng)論 3 16
  • 啊今天有多么美好啊,我的兩幅圖多么的美,美呀,哈哈哈哈,今天有我非常非常的瞌睡,可是要堅(jiān)持的,做簡(jiǎn)書(shū),做完以后我就...
    又呆又萌的萌閱讀 385評(píng)論 0 0
  • https://ke.qq.com/course/87173先看相機(jī)的兩個(gè)裝置,如下圖 調(diào)焦環(huán)和設(shè)置調(diào)焦模式 調(diào)焦...
    edison0428閱讀 497評(píng)論 0 0

友情鏈接更多精彩內(nèi)容