来自android,java上的PEM文件的PublicKey

时间:2017-08-02 15:25:44

标签: java android openssl public-key pem

基本上我试图验证使用openssl的签名如下:

openssl dgst -sha256 -verify prime192v1-pub-v1.pem -signature signatureFile.bin < dataFile.bin

...为了在android上做到这一点,我需要创建PublicKey对象。我使用的方法在第java.security.spec.InvalidKeySpecException: Unexpected key type行抛出kf.generatePublic(new X509EncodedKeySpec(encoded))

import org.spongycastle.util.encoders.Base64;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;

public class SO {

    public static PublicKey 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.decode(publicKeyPEM);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(new X509EncodedKeySpec(encoded));
    }

}

这就是我调用方法的方法:

    SO.getPublicKeyFromString(
            "-----BEGIN PUBLIC KEY-----\n" +
            "MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEXMHnQfWiM4oCaLfx296llgz7iaVv\n" +
            "avMPppkzVNZAxtlNLhFlXnNWD0Mw9yzP8/Go\n" +
            "-----END PUBLIC KEY-----"
    );

任何人都知道我做错了什么?

2 个答案:

答案 0 :(得分:1)

我得到了它的工作。公钥是椭圆曲线(p192)公钥,应加载不同。拥有PublicKey我能够像使用openssl命令一样验证签名。

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.Reader;
import java.io.StringReader;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;

public class SO {

    public PublicKey getPublicKey() throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        Reader rdr = new StringReader(
                "-----BEGIN PUBLIC KEY-----\n" +
                        "MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEXMHnQfWiM4oCaLfx296llgz7iaVv\n" +
                        "avMPppkzVNZAxtlNLhFlXnNWD0Mw9yzP8/Go\n" +
                        "-----END PUBLIC KEY-----\n"
        ); // or from file etc.

        org.bouncycastle.util.io.pem.PemObject spki = new org.bouncycastle.util.io.pem.PemReader(rdr).readPemObject();
        PublicKey key = KeyFactory.getInstance("EC", "BC").generatePublic(new X509EncodedKeySpec(spki.getContent()));
        return key;
    }

    public static boolean verify(byte[] data, byte[] signatureBytes, PublicKey publicKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(signatureBytes);
    }

}

答案 1 :(得分:0)

我正在与此争吵一段时间,并提出了这个解决方案。我决定不要重载安全系统,因为我在我的应用程序的其他区域使用了android的加密系统的其他元素。

public class EncryptionInterface {

    private static final int bufferSize_ = 32;
    private static final String headerTag = "-----BEGIN PUBLIC KEY-----";
    private static final String footerTag = "-----END PUBLIC KEY-----";

    /**
     *
     * @param ctx
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(Context ctx) throws Exception {

        PublicKey generatedPublic;

        Security.addProvider(new BouncyCastleProvider());
        String publicKeyString = getKeyFromFile(ctx);

        byte[] decoded = Base64.decode(publicKeyString, Base64.DEFAULT);
        org.spongycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey = org.spongycastle.asn1.pkcs.RSAPublicKey.getInstance(decoded);
        BigInteger modulus = pkcs1PublicKey.getModulus();
        BigInteger publicExponent = pkcs1PublicKey.getPublicExponent();
        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExponent);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        generatedPublic = kf.generatePublic(keySpec);

        return generatedPublic;

    }

    /**
     * Load the key/PEM from a file and strip the header/footer.
     * @param ctx
     * @throws Exception
     */
    public static String getKeyFromFile(Context ctx) throws Exception
    {
        String certPath = "publickey.pem";

        InputStream input = ctx.getAssets().open(certPath);
        byte[] buffer = new byte[bufferSize_];
        int len = 0;
        ByteArrayOutputStream keyBuffer = new ByteArrayOutputStream();
        while ((len = input.read(buffer)) != -1) {
            keyBuffer.write(buffer, 0, len);
        }

        String str = new String(keyBuffer.toByteArray());

        str = str.replace(headerTag, "");
        str = str.replace(footerTag, "");
        return str;
    }
}