何时使用X509EncodedKeySpec vs RSAPublicKeySpec?

时间:2014-06-14 19:04:15

标签: java encryption public-key-encryption

我在文本文件中有证书,其内容如下:

-----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课程,基于名字,这似乎是我对此感兴趣的东西。但我相信它只是用于生成证书而不是读取现有证书?

由于

3 个答案:

答案 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;
}

}