Java非對稱加密算法--RSA加密算法

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


發佈了87 篇原創文章 · 獲贊 376 · 訪問量 50萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章