RSA in Java
Private Key 操作命令¶
生成 PKCS #1 格式的 RSA Private Key¶
openssl genrsa -out private-key.p1.pem 2048
PKCS #1 -> Unencrypted PKCS #8¶
openssl pkcs8 -topk8 -in private-key.p1.pem -out private-key.p8.pem -nocrypt
PKCS #1 -> Encrypted PKCS #8¶
openssl pkcs8 -topk8 -in private-key.p1.pem -out private-key.p8.pem
过程中会让你输入密码,你至少得输入 4 位,所以 PKCS #8 相比 PKCS #1 更安全。
PKCS #8 -> PKCS #1¶
openssl rsa -in private-key.p8.pem -out private-key.p1.pem
如果这个 PKCS #8 是加密的,那么你得输入密码。
Public Key 操作命令¶
从 PKCS #1/#8 提取¶
提取指的是从 Private Key 中提取 Public Key,openssl rsa 同时支持 PKCS #1 和 PKCS #8 的 RSA Private Key,唯一的区别是如果 PKCS #8 是加密的,会要求你输入密码。
提取 X.509 格式 RSA Public Key¶
openssl rsa -in private-key.p1.pem -pubout -out public-key.x509.pem
openssl rsa -in private-key.p8.pem -pubout -out public-key.x509.pem
Java 代码¶
package com.abakus.dct.business.oms;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
@Log4j2
public class RSA {
private static String RSA_ALG = "RSA";
private static String SIGN_ALG = "SHA256withRSA";
private static String CIPHER_ALG = "RSA/ECB/PKCS1Padding";
private static String getKey(String filename) throws IOException {
// Read key from file
String strKeyPEM = "";
BufferedReader br = new BufferedReader(new FileReader(filename));
String line;
while ((line = br.readLine()) != null) {
strKeyPEM += line + "\n";
}
br.close();
return strKeyPEM;
}
public static RSAPrivateKey getPrivateKey(String filename) throws IOException, GeneralSecurityException {
String privateKeyPEM = getKey(filename);
return getPrivateKeyFromString(privateKeyPEM);
}
public static RSAPrivateKey getPrivateKeyFromString(String key) throws IOException, GeneralSecurityException {
String privateKeyPEM = key;
privateKeyPEM = privateKeyPEM.replace("-----BEGIN PRIVATE KEY-----\n", "");
privateKeyPEM = privateKeyPEM.replace("-----END PRIVATE KEY-----", "");
byte[] encoded = Base64.decodeBase64(privateKeyPEM);
KeyFactory kf = KeyFactory.getInstance(RSA_ALG);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(keySpec);
return privKey;
}
public static RSAPublicKey getPublicKey(String filename) throws IOException, GeneralSecurityException {
String publicKeyPEM = getKey(filename);
return getPublicKeyFromString(publicKeyPEM);
}
public static RSAPublicKey getPublicKeyFromString(String key) throws IOException, GeneralSecurityException {
String publicKeyPEM = key;
publicKeyPEM = publicKeyPEM.replace("-----BEGIN PUBLIC KEY-----\n", "");
publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
byte[] encoded = Base64.decodeBase64(publicKeyPEM);
KeyFactory kf = KeyFactory.getInstance(RSA_ALG);
RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(new X509EncodedKeySpec(encoded));
return pubKey;
}
public static String sign(PrivateKey privateKey, String message) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, UnsupportedEncodingException {
Signature sign = Signature.getInstance(SIGN_ALG);
sign.initSign(privateKey);
sign.update(message.getBytes("UTF-8"));
return new String(Base64.encodeBase64(sign.sign()), "UTF-8");
}
public static boolean verify(PublicKey publicKey, String message, String signature) throws SignatureException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
Signature sign = Signature.getInstance(SIGN_ALG);
sign.initVerify(publicKey);
sign.update(message.getBytes("UTF-8"));
return sign.verify(Base64.decodeBase64(signature.getBytes("UTF-8")));
}
public static String encrypt(String rawText, PublicKey publicKey) throws IOException, GeneralSecurityException {
Cipher cipher = Cipher.getInstance(CIPHER_ALG);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeBase64String(cipher.doFinal(rawText.getBytes("UTF-8")));
}
public static String decrypt(String cipherText, PrivateKey privateKey) throws IOException, GeneralSecurityException {
Cipher cipher = Cipher.getInstance(CIPHER_ALG);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(cipher.doFinal(Base64.decodeBase64(cipherText)), "UTF-8");
}
}