我在文本文件中有证书,其内容如下:
-----BEGIN PUBLIC KEY-----
xxxx
xxxx
xxxx
-----END PUBLIC KEY-----
我相信这是一个pem编码证书?所以我现在要加载它,我尝试以下方法:
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
readFileToByteArray("keyfile"));
但是我得到了一个InvalidKeySpecException。
如果我加载文件,请切断开始/结束页眉/页脚,然后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);
这是加载密钥文件的正确方法吗?我看到那里还有一个RSAPublicKeySpec课程,基于名字,这似乎是我对此感兴趣的东西。但我相信它只是用于生成证书而不是读取现有证书?
由于
答案 0 :(得分:7)
公共密钥格式here有一个很好的总结。正如X509EncodedKeySpec的javadoc所示,此类旨在转换X.509标准中的SubjectPublicKeyInfo ASN.1结构和Java公钥格式。并且由于第一个链接指示了
形式的文件-----开始公钥-----
XXXX
XXXX
----- END PUBLIC KEY -----
确实是一个SubjectPublicKeyInfo,您正在正确解析该文件。您缺少最后一步,那就是将X509EncodedKeySpec转换为公钥。这是KeyFactory class的功能。要将您的示例扩展两行,它将是
KeyFactory kf = KeyFactory.getInstance("RSA"); // Assuming this is an RSA key
RSAPublicKey rsaPubKey = (RSAPublicKey) kf.generatePublic(publicKeySpec);
答案 1 :(得分:0)
答案并不简单。以下代码在将{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(ENCRYPTED_YOUR_STRING, Base64.DEFAULT)
该解决方案在Android API 25平台和spongycastle 1.56上进行了测试
答案 2 :(得分:-1)
使用此课程
注意:仅使用少于129字节的字符串来使用RSA。
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;
}
}