InvalidKeyException:从Java中的PEM文件读取EC私钥时无效的密钥格式

时间:2018-06-01 15:09:36

标签: java private-key

我尝试从给定的.pem文件创建私钥对象。该文件具有以下结构:

-----BEGIN EC PRIVATE KEY-----
...............................
...............................
...............................
-----END EC PRIVATE KEY-----

我正在尝试使用以下代码创建私钥对象:

public static String getKeyFromFile(String filename) throws IOException {
    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int) f.length()];
    dis.readFully(keyBytes);
    dis.close();

    String key = new String(keyBytes);

    return key;
}

public static PrivateKey getPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, NoSuchProviderException {
    String privateKeyPEM = getKeyFromFile("MY_FILE.pem");

    privateKeyPEM = privateKeyPEM.replace("-----BEGIN EC PRIVATE KEY-----\n", "");
    privateKeyPEM = privateKeyPEM.replace("-----END EC PRIVATE KEY-----", "");
    privateKeyPEM = privateKeyPEM.replaceAll("\n", "");
    privateKeyPEM = privateKeyPEM.replaceAll(" ", "");

    byte[] privateKeyBytes = privateKeyPEM.getBytes();
    String encodedString = Base64.getEncoder().encodeToString(privateKeyBytes);
    byte[] decodedString = Base64.getDecoder().decode(encodedString);

    EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(decodedString);
    KeyFactory kf = KeyFactory.getInstance("EC");
    PrivateKey privKey = kf.generatePrivate(privKeySpec);

    return privKey;

运行此方法后,我收到此错误:

java.security.InvalidKeyException: invalid key format

我能够解析文本并删除任何不需要的字符,但我无法创建私钥对象。我能够使用非常类似的方法从类似的.crt文件生成公钥对象。我希望能够在Java中完成这项工作,而不是openssl。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

您的代码无法正确解码base64数据:

privateKeyPEM包含BEGINEND数据(base64编码)之间的字符串数据。

您的代码执行以下操作:

byte[] privateKeyBytes = privateKeyPEM.getBytes();
// privateKeyBytes now contains the base64 encoded key data

String encodedString = Base64.getEncoder().encodeToString(privateKeyBytes);
// encoded String contains now the base64 encoded data of the base64 encoded key data

byte[] decodedString = Base64.getDecoder().decode(encodedString);
// decodedString is not the base64 encoded data of your key data

为什么要编码数据库64然后在下一行解码它 - 两个步骤在一起只是没用。

您真正需要的是将base64解码一次应用到privateKeyPEM:

byte[] keyData = Base64.getDecoder().decode(privateKeyPEM);
EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(keyData);

如果base64解码失败,那么您的base64数据无效 - 很可能是因为包含空格或\r