1. 程式人生 > >非對稱加密演算法(2):RSA

非對稱加密演算法(2):RSA

一.RSA:RSA公鑰加密演算法是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。1987年7月首次在美國公佈,當時他們三人都在麻省理工學院工作實習。RSA就是他們三人姓氏開頭字母拼在一起組成的。

RSA演算法基於一個十分簡單的數論事實:將兩個大質數相乘十分容易,但是想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密金鑰。

二.優缺點:

1)產生金鑰很麻煩,受到素數產生技術的限制,因而難以做到一次一密。 2)安全性,RSA的安全性依賴於大數的因子分解,但並沒有從理論上證明破譯RSA的難度與大數分解難度等價,而且密碼學界多數人士傾向於因子分解不是NP問題。 3)速度太慢,由於RSA 的分組長度太大,為保證安全性,n 至少也要 600 bits以上,使運算代價很高,尤其是速度較慢,較對稱密碼演算法慢幾個數量級;且隨著大數分解技術的發展,這個長度還在增加,不利於資料格式的標準化。SET(Secure Electronic Transaction)協議中要求CA採用2048位元長的金鑰,其他實體使用1024位元的金鑰。為了速度問題,人們廣泛使用單,
公鑰
密碼結合使用的方法,優缺點互補:單鑰密碼加密速度快,人們用它來加密較長的檔案,然後用RSA來給檔案金鑰加密,極好的解決了單鑰密碼的金鑰分發問題。

三.實現過程:


四.具體的實現程式碼(java):

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.apache.commons.codec.binary.Base64;

/**
 * 使用 RSA 演算法對資料進行加解密  
 * @author wsy 
 */
public class RSA {
	static String src = "歐陽草帽";
	public static void main(String[] args) throws Exception {
		//初始化祕鑰
		KeyPair keyPair = getKeyPair();
		RSAPublicKey rsaPublicKey = getPublicKey(keyPair);
		RSAPrivateKey rsaPrivateKey = getPrivateKey(keyPair);
		
		//私鑰加密,公鑰解密  ---- 加密 
		byte[] result = encryptedByPublic(rsaPrivateKey,src);
		System.out.println("加密結果:"+Base64.encodeBase64String(result));
		
		//私鑰加密,公鑰解密  ---- 解密 
		result = decryptByPrivate(rsaPublicKey, result);
		System.out.println("解密結果:"+new String(result));
		
		//公鑰加密,公私鑰解密  ---- 加密 
		result = encryptByPrivate(rsaPublicKey, src);
		System.out.println("加密結果 :"+Base64.encodeBase64String(result));
		
		//公鑰加密,公私鑰解密  ---- 解密 
		result = decryptByPublic(rsaPrivateKey, result);
		System.out.println("解密結果:"+new String(result));
	}

	/**
	 * 私鑰加密,公鑰解密    ---  解密
	 * @param rsaPrivateKey
	 * @param encryptBytes
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 * @throws NoSuchPaddingException
	 * @throws InvalidKeyException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 */
	public static byte[] decryptByPublic(RSAPrivateKey rsaPrivateKey,
			byte[] encryptBytes) throws NoSuchAlgorithmException,
			InvalidKeySpecException, NoSuchPaddingException,
			InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		byte[] result = cipher.doFinal(encryptBytes);  // 解密結果 
		return result;
	}

	/**
	 * 私鑰加密,公鑰解密    ---  加密
	 * @param rsaPublicKey
	 * @param src
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 * @throws NoSuchPaddingException
	 * @throws InvalidKeyException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 */
	public static byte [] encryptByPrivate(RSAPublicKey rsaPublicKey, String src)
			throws NoSuchAlgorithmException, InvalidKeySpecException,
			NoSuchPaddingException, InvalidKeyException,
			IllegalBlockSizeException, BadPaddingException {
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		byte [] result = cipher.doFinal(src.getBytes()); //加密結果 
		return result;
	}

	/**
	 * 公鑰加密,私鑰解密    ---  解密
	 * @param rsaPublicKey
	 * @param encryptBytes
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 * @throws NoSuchPaddingException
	 * @throws InvalidKeyException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 */
	public static byte[] decryptByPrivate(RSAPublicKey rsaPublicKey,
			byte[] encryptBytes) throws NoSuchAlgorithmException,
			InvalidKeySpecException, NoSuchPaddingException,
			InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, publicKey);
		byte[] result = cipher.doFinal(encryptBytes); //解密結果 
		return result;
	}
	
	/**
	 * 公鑰加密,私鑰解密    ---  加密 
	 * @param rsaPrivateKey
	 * @param src
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 * @throws NoSuchPaddingException
	 * @throws InvalidKeyException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 */
	public static byte[] encryptedByPublic(RSAPrivateKey rsaPrivateKey,String src)
			throws NoSuchAlgorithmException, InvalidKeySpecException,
			NoSuchPaddingException, InvalidKeyException,
			IllegalBlockSizeException, BadPaddingException {
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		byte [] result = cipher.doFinal(src.getBytes());  // 加密結果 
		return result;
	}

	/**
	 * 獲取私鑰
	 * @param keyPair
	 * @return
	 */
	public static RSAPrivateKey getPrivateKey(KeyPair keyPair) {
		RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
		return rsaPrivateKey;
	}

	/**
	 * 獲取公鑰
	 * @param keyPair
	 * @return
	 */
	public static RSAPublicKey getPublicKey(KeyPair keyPair) {
		RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
		return rsaPublicKey;
	}

	private static KeyPair getKeyPair() throws NoSuchAlgorithmException {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(512);
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		return keyPair;
	}
}