Java非對稱加密算法--RSA加密算法
RSA加密算法是一種非對稱加密算法。在公開密鑰加密和電子商業中RSA被廣泛使用。RSA是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當時他們三人都在麻省理工學院工作。RSA就是他們三人姓氏開頭字母拼在一起組成的。
1973年,在英國政府通訊總部工作的數學家克利福德·柯克斯(Clifford Cocks)在一個內部文件中提出了一個相同的算法,但他的發現被列入機密,一直到1997年才被髮表。
對極大整數做因數分解的難度決定了RSA算法的可靠性。換言之,對一極大整數做因數分解愈困難,RSA算法愈可靠。假如有人找到一種快速因數分解的算法的話,那麼用RSA加密的信息的可靠性就肯定會極度下降。但找到這樣的算法的可能性是非常小的。今天只有短的RSA鑰匙纔可能被強力方式解破。到2013年爲止,世界上還沒有任何可靠的攻擊RSA算法的方式。只要其鑰匙的長度足夠長,用RSA加密的信息實際上是不能被解破的。
下面我是採用Bouncy Castle實現的RSA加密算法。Bouncy Castle 是一種用於 Java 平臺的開放源碼的輕量級密碼術包。它支持大量的密碼術算法,並提供 JCE 1.2.1 的實現。因爲 Bouncy Castle 被設計成輕量級的,所以從 J2SE 1.4 到 J2ME(包括 MIDP)平臺,它都可以運行。它是在 MIDP 上運行的唯一完整的密碼術包。
<span style="font-size:14px;">package com.qiuzhping.rsa;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.ByteArrayOutputStream;
import java.io.File;
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;
/**
* 非對稱加密是公鑰加密,私鑰來解密.使用的是Bouncy Castle 是一種用於 Java 平臺的開放源碼的輕量級密碼術包.
* 1、此Demo使用的是bcprov-ext-jdk15on-152.jar
* 2、把jar文件複製到 $JAVA_HOME$\jre\lib\ext目錄下面
* 3、修改配置文件\jre\lib\security\java.security
* security.provider.1=sun.security.provider.Sun
* security.provider.2=sun.security.rsa.SunRsaSign
* security.provider.3=com.sun.net.ssl.internal.ssl.Provider
* security.provider.4=com.sun.crypto.provider.SunJCE
* security.provider.5=sun.security.jgss.SunProvider
* security.provider.6=com.sun.security.sasl.Provider
* security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
* security.provider.8=sun.security.smartcardio.SunPCSC 上述8個是JDK已經實現了的加密方式. 將
* security.provider.9=org.bouncycastle.jce.provider.BouncyCastleProvider 添加到後面.
* 非對稱加密稱爲公鑰加密,算法更加複雜,速度慢,加密和解密鑰匙不相同,任何人都可以知道公鑰,只有一個人持有私鑰可以解密。
*
* @author Peter.Qiu
*
*/
public class RsaUtil {
/**
* 根據publicKey 對data進行加密.
*
* @param publicKey
* @param data
* @throws Exception
* @author Peter.Qiu
*/
public static byte[] encryptMode(PublicKey publicKey, byte[] data)
throws Exception {
try {
Cipher cipher = Cipher.getInstance("RSA",
new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);// ENCRYPT_MODE 加密
int blockSize = cipher.getBlockSize();
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);
}
i++;
}
return raw;
} catch (Exception e) {
throw e;
}
}
/**
* 根據privateKey 對data進行解密.
*
* @param privateKey
* @param data
* @throws Exception
* @author Peter.Qiu
*/
public static byte[] decryptMode(PrivateKey privateKey, byte[] data)
throws Exception {
Cipher cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());
cipher.init(Cipher.DECRYPT_MODE, privateKey);// DECRYPT_MODE 解密
int blockSize = cipher.getBlockSize();
ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
int j = 0;
while (data.length - j * blockSize > 0) {
bout.write(cipher.doFinal(data, j * blockSize, blockSize));
j++;
}
return bout.toByteArray();
}
/**
* 獲取密鑰.
*
* @param rsaKeyStore
* @return
* @throws Exception
* @author Peter.Qiu
*/
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;
}
/**
* 將密鑰寫入文件.
*
* @param kp
* @param path
* @throws Exception
* @author Peter.Qiu
*/
public static void saveKeyPair(KeyPair kp, String path) throws Exception {
File file = new File(path);
if (!file.exists() || file.isDirectory()) {
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(path);
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 生成密鑰
oos.writeObject(kp);
oos.close();
fos.close();
}
/**
* 用於生成公匙或私匙.
*
* @return
* @throws NoSuchAlgorithmException
* @author Peter.Qiu
*/
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
SecureRandom sr = new SecureRandom();
KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA",
new BouncyCastleProvider());
// 注意密鑰大小最好爲1024,否則解密會有亂碼情況.
kg.initialize(1024, sr);
KeyPair genKeyPair = kg.genKeyPair();
return genKeyPair;
}
/**
* 將公密或私密寫入文件.
*
* @param obj
* @param path
* @throws Exception
* @author Peter.Qiu
*/
public static void saveFile(Object obj, String path) throws Exception {
File file = new File(path);
if (!file.exists() || file.isDirectory()) {
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(path);
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 生成密鑰
oos.writeObject(obj);
oos.close();
fos.close();
}
/**
* 獲取公密.
*
* @param publicKeyPath
* @return
* @throws Exception
* @author Peter.Qiu
*/
public static PublicKey getPublicKey(String publicKeyPath) throws Exception {
FileInputStream fis = new FileInputStream(publicKeyPath);
ObjectInputStream oos = new ObjectInputStream(fis);
PublicKey kp = (PublicKey) oos.readObject();
oos.close();
fis.close();
return kp;
}
/**
* 獲取私密.
*
* @param privateKeyPath
* @return
* @throws Exception
* @author Peter.Qiu
*/
public static PrivateKey getPrivateKey(String privateKeyPath)
throws Exception {
FileInputStream fis = new FileInputStream(privateKeyPath);
ObjectInputStream oos = new ObjectInputStream(fis);
PrivateKey kp = (PrivateKey) oos.readObject();
oos.close();
fis.close();
return kp;
}
public static void main(String[] args) throws Exception {
File dir = new File("./key/");
if (!dir.exists()) {
dir.mkdir();
}
// 獲取公匙及私匙
KeyPair generateKeyPair = getKeyPair("./key/key");
// 生成公鑰及私鑰
// generateKeyPair = generateKeyPair();
// 存儲KeyPair到本地用於後期解密 注意修改前臺RSAKeyPair
// saveKeyPair(generateKeyPair,"./key/key");
System.out.println("generateKeyPair : " + generateKeyPair);
// 公匙 用於前臺加密
PublicKey publicKey = null;// generateKeyPair.getPublic();
publicKey = getPublicKey("./key/publicKey.key");
System.out.println("publicKey:" + publicKey);
// saveFile(publicKey,"./key/publicKey.key");
// 私匙 存儲在後臺用於解密
PrivateKey privateKey = null;// generateKeyPair.getPrivate(); //
privateKey = getPrivateKey("./key/privateKey.key");//
System.out.println("privateKey:" + privateKey);
// saveFile(privateKey,"./key/privateKey.key");
// 測試加密解密
String test = "saaaa";
test = "Peter.Qiu丘丘丘邱";
System.out.println("加密前字符:" + test);
byte[] en_test = encryptMode(publicKey, test.getBytes("UTF-8"));
System.out.println("加密後字符:" + new String(en_test));
byte[] de_test = decryptMode(privateKey, en_test);
System.out.println("解密後字符:" + new String(de_test, "UTF-8"));
}
}</span>
轉摘請註明:http://blog.csdn.net/qiuzhping/article/details/44344373
對應完整的項目:http://download.csdn.net/detail/qiu_11/8509319