openssl 操作RSA公私钥
//生成1024长度私钥
openssl genrsa -out key.pem 1024
//根据私钥生成公钥,公钥比较短,它只包括了数字n 和 常数 e
openssl rsa -in key.pem -pubout -out pubkey.pem
//公钥对文件进行加密
openssl rsautl -encrypt -in file1.txt -inkey pubkey.pem -pubin -out file2.txt
xxd file2.txt
//私钥解密
openssl rsautl -decrypt -in file2.txt -inkey key.pem
RSA加解密相关API
image.png最常用的是 PKICSIPADDING
有 生成和导入 没有就使用生成
导入 公钥一般用 X509EncodeKeySpec方式
私钥一般使用PKCS8EncodeKeySpec方式 导入
导入之后 交给 keyFactory 才可以转化为 pubKey 和 privKey
package com.deepway.cryptology.rsa;
import cn.hutool.core.io.FileUtil;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.security.*;
import java.security.spec.EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* RSA源码 RSAKeyPairGenerator
*
* @author huyanbing
* @create 2022/12/19 12:27 上午
*/
public class RsaCipher {
//sun.security.rsa.RSAPadding.padV15
String algo = "RSA/ECB/PKCS1Padding";
int keyLen = 1024;
KeyPair keyPair;
/**
* 生成密钥对
*
* @return
*/
public KeyPair generateKeyPair() throws NoSuchAlgorithmException {
String algo = StringUtils.substringBefore(this.algo, "/");
KeyPairGenerator generator = KeyPairGenerator.getInstance(algo);
//1024,2048。。。
generator.initialize(keyLen);
KeyPair pair = generator.generateKeyPair();
System.out.println("generateKeyPair:");
System.out.println(pair);
return pair;
}
/**
* 导入密钥
*
* @return
*/
public KeyPair importKeyPair() throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] pub = FileUtil.readBytes(new File("pub.key"));
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(pub);
PublicKey pubKey = keyFactory.generatePublic(publicKeySpec);
byte[] priv = FileUtil.readBytes(new File("priv.key"));
//私钥用的是PKCS8EncodedKeySpec
EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(priv);
PrivateKey privateKey = keyFactory.generatePrivate(privKeySpec);
System.out.println("importKeyPair");
System.out.println(pubKey);
System.out.println(privateKey);
return new KeyPair(pubKey, privateKey);
}
/**
* 导出密钥到文件
*/
public void exportKey() {
FileUtil.writeBytes(keyPair.getPublic().getEncoded(), new File("pub.key"));
FileUtil.writeBytes(keyPair.getPrivate().getEncoded(), new File("priv.key"));
}
/**
* 加密方法
*
* @param plainText
* @return
*/
public byte[] encrypt(byte[] plainText) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(algo);
//使用加密模式 公钥
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
return cipher.doFinal(plainText);
}
/**
* 解密方法
*
* @param cipherText
* @return
* @throws GeneralSecurityException
*/
public byte[] decrypt(byte[] cipherText) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(algo);
//使用解密模式 私钥
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
return cipher.doFinal(cipherText);
}
public static void main(String[] args) throws Exception {
RsaCipher bob = new RsaCipher();
//bob.keyPair = bob.importKeyPair();
bob.keyPair = bob.generateKeyPair();
bob.exportKey();
//Alice:
RsaCipher alice = new RsaCipher();
alice.keyPair = new KeyPair(bob.keyPair.getPublic(), null);
byte[] y = alice.encrypt("Deepway is no 1".getBytes());
//Bob:
byte[] x = bob.decrypt(y);
//解密为
System.out.println(new String(x));
}
}
源码解读 RSAKeyPairGenerator
image.png image.png image.png计算 phi=(p-1)*(q-1)
image.pnge 和 phi的最大公约数是1
image.png确保 e 和 phi 是互质的
计算私钥d 是e 关于phi_n的模反元素
image.png优化rsa
// private exponent d is the inverse of e mod phi
BigInteger d = e.modInverse(phi);
// 性能优化 提前计算
// 1st prime exponent pe = d mod (p - 1)
BigInteger pe = d.mod(p1);
// 2nd prime exponent qe = d mod (q - 1)
BigInteger qe = d.mod(q1);
// crt coefficient coeff is the inverse of q mod p
BigInteger coeff = q.modInverse(p);
使用 n 、e 生成公钥
image.png使用了CRT中国剩余定理来优化rsa 计算性能
使用 n 、e 、d ,p ,q ,加上优化的pe,qe,coeff 生成私钥
网友评论