RSA算法流程
生成公钥私钥
- 找出两个大质数p,q,位数最好超过1024位,质数越大破解难度越大,这两个质数不能公开
n = p * q
f(n) = (p - 1) * (q - 1)
- 公钥e,满足
1 < e < f(n)
,且e与f(n)互质 - 私钥d,满足
e * d % f(n) = 1
加密过程
- 加密方需要知道n,和公钥e。
- 设加密信息为m,m必须小于n,大于的话则将信息分组再传
- 加密过程:
明文m -> m^e % n -> 密文c
(注意这里的^是幂运算,不是异或,下同)
解密过程
- 解密方需要知道n,和私钥d
- 设收到的密码信息为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==
私钥解密:沙雕网友发的什么玩意儿?
初次了解加密算法,可能理解的比较肤浅。先记录一下,日后有机会再深究。