RSA算法浅入浅出

RSA算法流程

生成公钥私钥

  1. 找出两个大质数p,q,位数最好超过1024位,质数越大破解难度越大,这两个质数不能公开
  2. n = p * q
  3. f(n) = (p - 1) * (q - 1)
  4. 公钥e,满足1 < e < f(n),且e与f(n)互质
  5. 私钥d,满足e * d % f(n) = 1

加密过程

  1. 加密方需要知道n,和公钥e。
  2. 设加密信息为m,m必须小于n,大于的话则将信息分组再传
  3. 加密过程:明文m -> m^e % n -> 密文c(注意这里的^是幂运算,不是异或,下同)

解密过程

  1. 解密方需要知道n,和私钥d
  2. 设收到的密码信息为c,解密过程:密文c -> c^d % n -> 明文m

补充

加解密过程可以互换,公钥加密的信息只有私钥才可以解密,所以可以用于给传递信息。

同理,私钥加密的内容公钥可以解密,因此可以用于验证信息。

大质数可以考虑通过Miller-Rabin素数检测算法生成,公钥似乎都选65537,私钥通过扩展欧几里得算法计算,加解密过程可使用快速幂

Java实现

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.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;
import java.util.Scanner;
import javax.crypto.Cipher;
import org.springframework.util.Base64Utils;

public class RSADemo {

	private static final int KEY_SIZE = 2048;
	private static final String KEY_ALGORITHM = "RSA";
	private static KeyFactory KEY_FACTORY;
	
	static {
		try {
			KEY_FACTORY = KeyFactory.getInstance(KEY_ALGORITHM);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 私钥加密
	 * 
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {
		PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(key);
		PrivateKey privateKey = KEY_FACTORY.generatePrivate(encodedKeySpec);
		Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		return cipher.doFinal(data);
	}

	/**
	 * 私钥解密
	 * 
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
		PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(key);
		PrivateKey privateKey = KEY_FACTORY.generatePrivate(encodedKeySpec);
		Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		return cipher.doFinal(data);
	}

	/**
	 * 公钥加密
	 * 
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {
		X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(key);
		PublicKey publicKey = KEY_FACTORY.generatePublic(encodedKeySpec);
		Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		return cipher.doFinal(data);
	}

	/**
	 * 公钥解密
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {
		X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(key);
		PublicKey publicKey = KEY_FACTORY.generatePublic(encodedKeySpec);
		Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
		cipher.init(Cipher.DECRYPT_MODE, publicKey);
		return cipher.doFinal(data);
	}

	/**
	 * 生成公钥、私钥
	 * 
	 * @return
	 * @throws NoSuchAlgorithmException
	 */
	public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
		KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
		SecureRandom random = new SecureRandom(new Date().toString().getBytes());
		generator.initialize(KEY_SIZE, random);
		KeyPair keyPair = generator.generateKeyPair();
		return keyPair;
	}
	
	public static void main(String[] args) throws Exception {
		KeyPair keyPair = generateKeyPair();
		byte[] publicKey = keyPair.getPublic().getEncoded();
		byte[] privateKey = keyPair.getPrivate().getEncoded();
		System.out.println("公钥:\n" + Base64Utils.encodeToString(publicKey));
		System.out.println("私钥:\n" + Base64Utils.encodeToString(privateKey));
		System.out.println("----------------------");
		System.out.println("开始测试");
		Scanner scanner = new Scanner(System.in);
		while (scanner.hasNext()) {
			String text = scanner.next();
			byte[] encode = encryptByPrivateKey(text.getBytes(), privateKey);
			byte[] decode = decryptByPublicKey(encode, publicKey);
			System.out.println("原文:" + text);
			System.out.println("私钥加密:" + Base64Utils.encodeToString(encode));
			System.out.println("公钥解密:" + new String(decode));
			System.out.println("-----------------------");
			encode = encryptByPublicKey(text.getBytes(), publicKey);
			decode = decryptByPrivateKey(encode, privateKey);
			System.out.println("公钥加密:" + Base64Utils.encodeToString(encode));
			System.out.println("私钥解密:" + new String(decode));
			System.out.println("-----------------------");
		}
		scanner.close();
	}
}

测试结果如下:

公钥:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqMQk9jmhovxJrPWO/3BLGmgU+v3AVNBaXA4QZJRQX86F9Yaof5tV3mpTUV4mhHoJJ16zr7m81LAgoYxaP6iQ+sLw/Z4YEtV+Ze7ghRVYnfgdgSbM0GVD26Wo/Zaz/Qn4NdC6oAigXEM6o+RffZdvkuFyzxG9PRBppVweTXvhv3fo3F/U/sc+rrJuny5DMamF7Vm4WUgKraEcEg+ijl7eSszG8Qh7waY1eum2uklSCtSKwvTiV0A+ICdobKIyNl2syX9wUWMJW9fHRBwxGAIGjwO5cJID6HF2iYm/7+ZBkurWhkvGOLxlCshX1W12VbKj0KMiBF8BMiMdCPUvMFg7qwIDAQAB
私钥:
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCoxCT2OaGi/Ems9Y7/cEsaaBT6/cBU0FpcDhBklFBfzoX1hqh/m1XealNRXiaEegknXrOvubzUsCChjFo/qJD6wvD9nhgS1X5l7uCFFVid+B2BJszQZUPbpaj9lrP9Cfg10LqgCKBcQzqj5F99l2+S4XLPEb09EGmlXB5Ne+G/d+jcX9T+xz6usm6fLkMxqYXtWbhZSAqtoRwSD6KOXt5KzMbxCHvBpjV66ba6SVIK1IrC9OJXQD4gJ2hsojI2XazJf3BRYwlb18dEHDEYAgaPA7lwkgPocXaJib/v5kGS6taGS8Y4vGUKyFfVbXZVsqPQoyIEXwEyIx0I9S8wWDurAgMBAAECggEAcrBBEhdeMf3TL7f8wriUQVDEGUGCh+DD11UzbLah3EnkHVOyhG2SsEB/eIdME7E/MUMZR20o1z0OH9rapfIu/EqoLSJX58ywRiNM7wPvogKwQkmU3HZE5CqzKgpVLLuusxuzB/h0yd5iJmiXQCk+iImvVOsQOEREFzz/1tY+NrfuuBUo3qZVZEGYLPylz2Lpv0AjNecR50OC2wEHwmPlbU28dJYksTPYLhAmk5PSXaQ8IrSTcs0IK2JTrtbQV1Bk05W9CWSmkQoZiGwqJ2nOdeQce9e7ID1Avj8QgPhdDvf66FO9wLucyhscbji2DU7Hv+5jfRKVHWwCFzfXOwg1UQKBgQD2I3VvMhskqrOMb19IP3cw0YRxkjm44q/0GUXdGhd2wYKEXpwa1K653ojYC1ZX1UsYyHk7s6HWDQzgcq9mJ/XmEQxKBgozdEmV7jRUfjPjRQaslo3TOsAmm9sjvp9aoh7dYZs9NYC6cxqSY4tkZHwJ40AEhZ6bgA7Glt3oxoYnswKBgQCvhxwRECoanCnOrisgynk7z4pI96L81zepKV2Me6rIfi8XKq9qkaCgv9j7lgd1O0aV3pboPrcQ1ZpE7LU2L+mDpCCU0RIrZZDPfs94MldGar5DJ02aqqTcsd/7PGfpsqA4TQgCHXn6TstacYC+LRR5ksNP0/W+XtX1BWD6vcSgKQKBgEdKgesREjeOka6tW2WrrDQhm0Dh34Ijdl83KrsdoYouBkWcuY4z59/CCtS4g+uwxa2J80NNhiRfZ0ljLlZiYKCgc3TFRxMcLWwVsGaAnzrGdWZrvOxfaeRE5DX4MmOn7VSlvrb91ikqyZl455jOWfbrMVGd+hCECMOQUvnm9lhtAoGAdTy77VWrmZxmfCpumfdCpEVJqtTkIxaoka8UUamj90f4sfOLuJVOATBCgD/D+XQ/AAjtKHADHBZfdNvZaTj1MjzkmiFOjnfHEiAz+Kc/DcRsEjRlLAIAHXwdCxRcn4X0Z8Zjq+3+M8Z/IoifIebAPzdchqwe/ikfpQkTrkYj14kCgYB1rBYcgzvoMkI7+OgTiU2d2SJcLMKK0Ctem4WEz/qHOZtx+K74lL5ixs/4WrRKLQzo/2junZHU4weucaW39CXHMszjh5DCjnkTwN9857mTxAy8UTGmUS6prv+HgwvxKJDuYRwsGWDV6gKvWWU+guUIwyuq5wFmzWt67mmUSaoEJw==
----------------------
开始测试
原文:沙雕网友发的什么玩意儿?
私钥加密:CJ+TXFiHP6nj7RoGVntXnaPHi0bPFTAapbhh1f3IZpNiupi1GH+fR+C7y7B25vACqfCgbRK8mV/UORhtCfcQySttKDufQZF9NnWsbNzDa+6Y1ElEsFVfk4xUThxEKHYsMdHK2NUt4LmaHyd3NMjFvwL7CHr9u0M+7DjzXtejsAH3vKUtdn/JTcfml8NDRFkGhkvqj/GdmOa8iw682nkQFot4R9HYu1/4a36TV2L++BNKU2rBis/BGgNslrgOea4nnYVdx/LjEBmr5FNpkijpLFVu8VjOjgZmCgixFsT9rD5rQCO45y/346JOOBDSkeH9DCHoKOZ3tMP6CSo84iuwPw==
公钥解密:沙雕网友发的什么玩意儿?
-----------------------
公钥加密:T4Y9iu1H199KD1GoodrUFVkY+uqP2pFlVoHauT8837et1iiv4pOGqFwXGWvCDlNqFVXHejyqLWmVghyPG1rKagG53ytW4kpw+8wVPRJFvHnpWPPgR7Cft69owbYCJwjoknTnEf4TYTHZd3EuyMSxgzb8b9hIrzdWCJ0JyDNbmnj6IgIPf0MoQ1hehzSXlXQbaRKu5EGesZLtlezH73bN5DtAhog2avjREfOVkbJmbcqt5SIUEM+DVljY2IVGVw2ibj848PRaLTL2THAgSrIEGsQoOSXUz8s9ufLPmdXiogxsxh72buRct3qRN3wEmP5kEL7SdYCSf1YIygPeZ5FrpQ==
私钥解密:沙雕网友发的什么玩意儿?

初次了解加密算法,可能理解的比较肤浅。先记录一下,日后有机会再深究。

posted @ 2019-03-04 11:36  Corvey  阅读(785)  评论(0编辑  收藏  举报