非對稱加密RSA算法Java實現

jopen 11年前發布 | 55K 次閱讀 RSA 算法

package com.test.rsa;

import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom;

import javax.crypto.Cipher;

public class RSAUtil {

/**
 * 加密
 */
public static byte[] encrypt(PublicKey pk, byte[] data) throws Exception {
    try {
        Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
        cipher.init(Cipher.ENCRYPT_MODE, pk);
        int blockSize = cipher.getBlockSize();// 獲得加密塊大小,如:加密前數據為128個byte,而key_size=1024
        // 加密塊大小為127
        // byte,加密后為128個byte;因此共有2個加密塊,第一個127
        // byte第二個為1個byte
        int outputSize = cipher.getOutputSize(data.length);// 獲得加密塊加密后塊大小
        int leavedSize = data.length % blockSize;
        int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
        byte[] raw = new byte[outputSize * blocksSize];
        int i = 0;
        while (data.length - i * blockSize > 0) {
            if (data.length - i * blockSize > blockSize)
                cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
            else
                cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
            // 這里面doUpdate方法不可用,查看源代碼后發現每次doUpdate后并沒有什么實際動作除了把byte[]放到
            // ByteArrayOutputStream中,而最后doFinal的時候才將所有的byte[]進行加密,可是到了此時加密塊大小很可能已經超出了
            // OutputSize所以只好用dofinal方法。

            i++;
        }
        return raw;
    } catch (Exception e) {
        throw new Exception(e.getMessage());
    }
}

/**
 * 解密
 */
public static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception {
    try {
        Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
        cipher.init(cipher.DECRYPT_MODE, pk);
        int blockSize = cipher.getBlockSize();
        ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
        int j = 0;

        while (raw.length - j * blockSize > 0) {
            bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
            j++;
        }
        return bout.toByteArray();
    } catch (Exception e) {
        throw new Exception(e.getMessage());
    }
}

/**
 * 
 * 根據本地的RSAKey文件獲取KeyPair
 * 
 * @throws Exception
 */
public static KeyPair getKeyPair(String rsaKeyStore) throws Exception {
    FileInputStream fis = new FileInputStream(rsaKeyStore);
    ObjectInputStream oos = new ObjectInputStream(fis);
    KeyPair kp = (KeyPair) oos.readObject();
    oos.close();
    fis.close();
    return kp;
}

/**
 * 
 * 存儲KeyPair到本地
 * 
 * @throws Exception
 */
public static void saveKeyPair(KeyPair kp, String path) throws Exception {
    FileOutputStream fos = new FileOutputStream(path);
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    // 生成密鑰
    oos.writeObject(kp);
    oos.close();
    fos.close();
}

/**
 * 
 * 用于生成公匙或私匙
 * 
 * @throws NoSuchAlgorithmException
 * 
 */
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {

    SecureRandom sr = new SecureRandom();
    KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
    // 注意密鑰大小最好為1024,否則解密會有亂碼情況.
    kg.initialize(1024, sr);
    KeyPair genKeyPair = kg.genKeyPair();
    return genKeyPair;

}

/**
 * 
 * 測試
 * 
 */
public static void main(String[] args) throws Exception {

    // 獲取公匙及私匙
    KeyPair generateKeyPair = getKeyPair("E:\\code\\key");
    //生成公鑰及私鑰
    //KeyPair generateKeyPair = generateKeyPair();

    // 公匙 用于前臺加密
    PublicKey publicKey = generateKeyPair.getPublic();
    System.out.println(publicKey);

    // 私匙 存儲在后臺用于解密
    PrivateKey privateKey = generateKeyPair.getPrivate();
    System.out.println(privateKey);

    // 存儲KeyPair到本地用于后期解密 注意修改前臺RSAKeyPair
    //saveKeyPair(generateKeyPair,"E:\\code\\key");

    // 測試加密解密
    String test = "saaaa";
    // test = "阿斯頓發送對發生地發送盜伐水電費圣達菲sadfsadf愛上對方愛上對方";


    byte[] en_test = encrypt(publicKey, test.getBytes());
    System.out.println("加密后字符:" + new String(en_test));

    byte[] de_test = decrypt(privateKey, en_test);
    System.out.println("解密后字符:" + new String(de_test));

}

} </pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!