java.security.spec.InvalidKeySpecException:java.io.IOException:意外的内容结束标记

时间:2016-08-23 15:18:35

标签: java security bouncycastle public-key key-pair

我尝试将.pub个文件的内容转换为PublicKey,然后将PublicKey转换回String以便确定转换是否正常,并且不会更改流程中的密钥。

id_rsa.pub

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0zszKhcZTC8xJidUszmRn4Tr/FxPs04wpCzEstebfTW7Bvqgtt+OdvxoNyYM0LAEnxEF4XhAWcsX7VJJqstZLpDqlKDXFr2d0aVIjksCpZt+ftVRwYHRoERhEOP/UmPFb5rKIkhQbED2kTWg11mW9soc6BhwB3THn/Cyo3t1u2vWjEySgPhKeA3Xzh+5eqV7CUD8V6S7OAT7T9ijf7sRV0R8rwHgTLWJ8+dETnY3L3N0fEaNuaayeNblHqrL53/1+tsBBUF3bAS+1GE6oniSeM/yhtfzf2x+O5MDlVVMbOCC/v+FnfIIEKLA+v1xDSAha7C5cHh82TxToWXsbjqGD me@mail

Converter.java

public static final synchronized PublicKey base64ToPublicKey(final String algorithm, final String base64) throws GeneralSecurityException, IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] sigBytes2 = decoder.decodeBuffer(base64);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(sigBytes2);
        KeyFactory keyFact = KeyFactory.getInstance(algorithm, "BC");
        return keyFact.generatePublic(x509KeySpec);
    }

    public static final synchronized String publicKeyToBase64(final PublicKey publicKey) throws GeneralSecurityException, IOException {
        byte[] publicKeyBytes = publicKey.getEncoded();
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(publicKeyBytes);
    }

当我跑步时:

PublicKey test1 = base64ToPublicKey("RSA", "AAAAB3NzaC1yc2EAAAADAQABAAABAQC0zszKhcZTC8xJidUszmRn4Tr/FxPs04wpCzEstebfTW7Bvqgtt+OdvxoNyYM0LAEnxEF4XhAWcsX7VJJqstZLpDqlKDXFr2d0aVIjksCpZt+ftVRwYHRoERhEOP/UmPFb5rKIkhQbED2kTWg11mW9soc6BhwB3THn/Cyo3t1u2vWjEySgPhKeA3Xzh+5eqV7CUD8V6S7OAT7T9ijf7sRV0R8rwHgTLWJ8+dETnY3L3N0fEaNuaayeNblHqrL53/1+tsBBUF3bAS+1GE6oniSeM/yhtfzf2x+O5MDlVVMbOCC/v+FnfIIEKLA+v1xDSAha7C5cHh82TxToWXsbjqGD");

我回来了:

java.security.spec.InvalidKeySpecException: java.io.IOException: unexpected end-of-contents marker
    at org.bouncycastle.jce.provider.JDKKeyFactory.engineGeneratePublic(Unknown Source)
    at org.bouncycastle.jce.provider.JDKKeyFactory$RSA.engineGeneratePublic(Unknown Source)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:328)
    at base64ToPublicKey(Converter.java:216)
    at main(Converter.java:283)

1 个答案:

答案 0 :(得分:0)

用于SSH2的

OpenSSH公钥文件id_*.pub以及known_hostsauthorized_keys中的条目)使用特定于SSH的特定格式的OpenSSH变体,请参阅基于SSH2有线格式(已链接)rfc4716rfc4253 6.6,其中不是' X.509'格式Java加密使用。 (SSH1的OpenSSH文件格式不同,但SSH1很长时间不能使用。)

要在Java中进行转换,请参阅convert openSSH rsa key to javax.crypto.Cipher compatible format

更容易避免这个问题。

绕过1:如果您有合理的近期OpenSSH(6.0可以,之前不确定),请使用

ssh-keygen -e -m PKCS8 -f id_rsa.pub >pub.pem # change filename as needed

转换为' X.509' (真正的SubjectPublicKeyInfo又称SPKI)以PEM形式。 (是的,他们确实使用名称PKCS8来表示SPKI; it's crazy。)然后通过丢弃BEGIN和END行在Java中读取它,解码从base64到byte[]之间的所有内容(减少换行符) ,并将其放在X509EncodedKeySpec中,就像现在一样。或者如果你有OpenSSL,你可以转换为DER表格

openssl rsa -pubin -in pub.pem -out pub.der -outform der # any version
openssl pkey -pubin -in pub.pem -out pub.der -outform der # 1.0.0 up

然后读取DER文件,完全没有变化X509EncodedKeySpec

绕过2:,如果您拥有私钥,并且它不是OpenSSH'新的'格式(自6.5(编辑)以来可选,自7.8开始默认),并且您有OpenSSL,使用其中一个获取SPKI(Java友好)格式的公钥

openssl rsa -in id_rsa -pubout -out pub.pem # default PEM
openssl rsa -in id_rsa -pubout -out pub.der -outform der # DER
openssl pkey -in id_rsa -pubout -out pub.pem # default PEM, 1.0.0 up
openssl pkey -in id_rsa -pubout -out pub.der -outform der # DER, 1.0.0