Java 何时使用X509EncodedKeySpec与RSAPublicKeySpec?
我有一个文本文件中的证书,其内容如下:Java 何时使用X509EncodedKeySpec与RSAPublicKeySpec?,java,encryption,public-key-encryption,Java,Encryption,Public Key Encryption,我有一个文本文件中的证书,其内容如下: -----BEGIN PUBLIC KEY----- xxxx xxxx xxxx -----END PUBLIC KEY----- 我相信这是pem编码的证书?因此,我想现在加载它,我正在尝试以下操作: X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec( readFileToByteArray("keyfile")); 但我得到一个InvalidKeySpec例外 如果我加载文
-----BEGIN PUBLIC KEY-----
xxxx
xxxx
xxxx
-----END PUBLIC KEY-----
我相信这是pem编码的证书?因此,我想现在加载它,我正在尝试以下操作:
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
readFileToByteArray("keyfile"));
但我得到一个InvalidKeySpec例外
如果我加载文件,切断开始/结束页眉/页脚,然后base64解码“xxxx”内容,我没有收到任何投诉:
String contents = readFileToString("keyfile");
contents = contents.replace("-----BEGIN PUBLIC KEY-----", "");
contents = contents.replace("-----END PUBLIC KEY-----", "");
byte[] prepared = Base64.decode(contents);
// ok.
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(prepared);
这是加载密钥文件的正确方法吗?我看到还有一个类,基于名称,它似乎是我在这里感兴趣的东西。但我相信这只是为了生成证书,而不是读取现有的证书
谢谢这里有一个很好的通用密钥格式摘要。正如javadocs所指出的,这个类的设计目的是在X.509标准的ASN.1结构和Java公钥格式之间进行转换。而且由于第一个链接表明,一个文件的形式 -----开始公钥------
xxxx
xxxx
-----结束公钥----- 确实是SubjectPublicKeyInfo,您正在正确解析该文件。您缺少的最后一步是将X509EncodedKeySpec转换为公钥。这就是系统的功能。将您的示例再扩展两行
KeyFactory kf = KeyFactory.getInstance("RSA"); // Assuming this is an RSA key
RSAPublicKey rsaPubKey = (RSAPublicKey) kf.generatePublic(publicKeySpec);
答案并不简单。在将RSA公钥字符串(如上所述以PEM格式编码)加载到
java.security.PublicKey
对象时,下面的代码对我很有用。注:应提前剥离集管和端部
public PublicKey convertToPublicKey(String publicKeyString) {
try {
byte[] decodedPublicKey = Base64.decode(publicKeyString, Base64.DEFAULT);
org.spongycastle.asn1.ASN1InputStream in = new org.spongycastle.asn1.ASN1InputStream(decodedPublicKey);
org.spongycastle.asn1.ASN1Primitive obj = in.readObject();
org.spongycastle.asn1.pkcs.RSAPublicKey keyStruct = org.spongycastle.asn1.pkcs.RSAPublicKey.getInstance(obj);
java.security.spec.RSAPublicKeySpec keySpec = new java.security.spec.RSAPublicKeySpec(keyStruct.getModulus(), keyStruct.getPublicExponent());
java.security.KeyFactory keyFactory = java.security.KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
然后,可以使用java.security.PublicKey
实例对字符串进行加密,如下所示:
Cipher rsaCipher = Cipher.getInstance("RSA/None/PKCS1Padding", "SC");
rsaCipher.init(Cipher.ENCRYPT_MODE, apiPublicKey);
byte[] ENCRYPTED_YOUR_STRING = rsaCipher.doFinal(YOUR_STRING);
然后可以通过以下方式将字节转换为字符串:
Base64.encodeToString(加密的字符串,Base64.DEFAULT)
该解决方案在Android API 25平台上进行测试,spongycastle 1.56使用该类
注意:仅使用小于129字节的字符串
public class RSA
{
private PublicKey internalPublicKey;
private PrivateKey internalPrivateKey;
private KeyPairGenerator kpg = null;
private int SIZE = 4096;
public RSA(int size)
{
try
{
SIZE = size;
kpg = KeyPairGenerator.getInstance("RSA");
init();
}
catch(Exception e){}
}
public RSA()
{
this(1024);
}
private void init()
{
kpg.initialize(SIZE, new SecureRandom());
KeyPair kp = kpg.genKeyPair();
internalPublicKey = kp.getPublic();
internalPrivateKey = kp.getPrivate();
}
public int getSize()
{
return SIZE;
}
public PublicKey getPublic()
{
return internalPublicKey;
}
public PrivateKey getPrivate()
{
return internalPrivateKey;
}
public String getPublicModule()
{
String s = internalPublicKey.toString();
return s.substring(s.indexOf("modulus")+8, s.indexOf(",publicExponent"));
}
public String getPublicExponent()
{
String s = internalPublicKey.toString();
return s.substring(s.indexOf("publicExponent")+15, s.lastIndexOf("}"));
}
public String getPrivateExponent()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("privateExponent")+16, s.indexOf(",primeP"));
}
public String getPrivatePrimP()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeP=")+7, s.indexOf(",primeQ"));
}
public String getPrivatePrimQ()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeQ=")+7, s.indexOf(",primeExponentP"));
}
public String getPrivatePrimExponentP()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeExponentP=")+15, s.indexOf(",primeExponentQ"));
}
public String getPrivatePrimExponentQ()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeExponentQ=")+15, s.indexOf(",crtCoefficient"));
}
public String getPrivateCrtCoefficient()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("crtCoefficient=")+15, s.lastIndexOf(","));
}
public byte[] getPublicKey()
{
return internalPublicKey.getEncoded();
}
public byte[] getPrivateKey()
{
return internalPrivateKey.getEncoded();
}
public String getPublicKeyAsString()
{
return Base64.encodeToString(internalPublicKey.getEncoded(), Base64.DEFAULT);
}
public String getPrivateKeyAsString()
{
return Base64.encodeToString(internalPrivateKey.getEncoded(), Base64.DEFAULT);
}
public byte[] getEncrypt(String plain)
{
try
{
//Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, internalPublicKey);
return cipher.doFinal(plain.getBytes("UTF-8"));
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public String getStringEncrypt(String plain)
{
return new String(getEncrypt(plain), Charset.forName("UTF-8"));
}
public byte[] getDecrypt(byte[] encryptedBytes)
{
try
{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, internalPrivateKey);
return cipher.doFinal(encryptedBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getDecrypt(byte[] x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public byte[] getDecrypt(String encrypted)
{
return getDecrypt(encrypted.getBytes());
}
public String getStringDecrypt(byte[] encryptedBytes)
{
return new String(getDecrypt(encryptedBytes), Charset.forName("UTF-8"));
}
public String getStringDecrypt(String encrypted)
{
return new String(getDecrypt(encrypted), Charset.forName("UTF-8"));
}
public static byte[] getEncrypt(String plain, String modulus, String exponent)
{
try
{
BigInteger modBigInteger = new BigInteger(modulus, 16);
BigInteger exBigInteger = new BigInteger(exponent, 16);
RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey pk = factory.generatePublic(spec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pk);
return cipher.doFinal(plain.getBytes("UTF-8"));
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt, ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String getStringEncrypt(final String plain, String modulus, String exponent)
{
return Base64.encodeToString(getEncrypt(plain, modulus, exponent), Base64.DEFAULT);
}
public static byte[] getDecrypt(byte[] encryptedBytes, String modulus, String publicExpo, String privateExpo, String primP, String primQ, String ePrimP, String ePrimQ, String cof)
{
try
{
BigInteger module = new BigInteger(modulus, 16);
BigInteger expo1 = new BigInteger(publicExpo, 16);
BigInteger expo2 = new BigInteger(privateExpo, 16);
BigInteger prim_P = new BigInteger(primP, 16);
BigInteger prim_Q = new BigInteger(primQ, 16);
BigInteger prim_EP = new BigInteger(ePrimP, 16);
BigInteger prim_EQ = new BigInteger(ePrimQ, 16);
BigInteger coefficient = new BigInteger(cof, 16);
/*BigInteger module = new BigInteger(1, Base64.encode(modulus.getBytes(), Base64.DEFAULT));
BigInteger expo1 = new BigInteger(1, Base64.encode(publicExpo.getBytes(), Base64.DEFAULT));
BigInteger expo2 = new BigInteger(1, Base64.encode(privateExpo.getBytes(), Base64.DEFAULT));
BigInteger prim_P = new BigInteger(1, Base64.encode(primP.getBytes(), Base64.DEFAULT));
BigInteger prim_Q = new BigInteger(1, Base64.encode(primQ.getBytes(), Base64.DEFAULT));
BigInteger prim_EP = new BigInteger(1, Base64.encode(ePrimP.getBytes(), Base64.DEFAULT));
BigInteger prim_EQ = new BigInteger(1, Base64.encode(ePrimQ.getBytes(), Base64.DEFAULT));
BigInteger coefficient = new BigInteger(1, Base64.encode(cof.getBytes(), Base64.DEFAULT));*/
RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(module, expo1, expo2, prim_P, prim_Q, prim_EP, prim_EQ, coefficient);
KeyFactory factory = KeyFactory.getInstance("RSA");
PrivateKey pk = factory.generatePrivate(spec);
Cipher cipher1 = Cipher.getInstance("RSA");
cipher1.init(Cipher.DECRYPT_MODE, pk);
//return cipher1.doFinal(Base64.decode(encryptedBytes, Base64.DEFAULT));
return cipher1.doFinal(encryptedBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String getStringDecrypt(byte[] encryptedBytes, String modulus, String publicExpo, String privateExpo, String primP, String primQ, String ePrimP, String ePrimQ, String cof)
{
return Converter.byteToString_UTF8(getDecrypt(encryptedBytes, modulus, publicExpo, privateExpo, primP, primQ, ePrimP, ePrimQ, cof));
}
public static byte[] getDecrypt(final byte[] encryptedBytes, byte[] privateKey)
{
try
{
KeyFactory keyFac = KeyFactory.getInstance("RSA");
KeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
PrivateKey pk = keyFac.generatePrivate(keySpec);
Cipher cipher1 = Cipher.getInstance("RSA");
cipher1.init(Cipher.DECRYPT_MODE, pk);
return cipher1.doFinal(encryptedBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String getStringDecrypt(final byte[] encryptedBytes, byte[] privateKey)
{
return Converter.byteToString_UTF8(getDecrypt(encryptedBytes, privateKey));
}
public static String sign(String plainText, PrivateKey privateKey)
{
try
{
Signature privateSignature = Signature.getInstance("SHA256withRSA");
privateSignature.initSign(privateKey);
privateSignature.update(plainText.getBytes());
byte[] signature = privateSignature.sign();
return Base64.encodeToString(signature, Base64.DEFAULT);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: sign(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static boolean verify(String plainText, String signature, PublicKey publicKey)
{
Signature publicSignature;
try
{
publicSignature = Signature.getInstance("SHA256withRSA");
publicSignature.initVerify(publicKey);
publicSignature.update(plainText.getBytes());
byte[] signatureBytes = Base64.decode(signature, Base64.DEFAULT);
return publicSignature.verify(signatureBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: verify(), ", Constants.DEFAULT_ALERT_STATE);
}
return false;
}
}“我有证书”。。。不,您有公钥,而不是证书。但是,您所做的获取关键实例的操作是正确的。