java.security.spec.InvalidKeySpecException: java.io.IOException: unexpected end-of-contents marker

别说谁变了你拦得住时间么 提交于 2019-12-12 03:33:34

问题


I'm trying to convert a .pub file's contents to a PublicKey and then convert the PublicKey back into a String in order to determine if the conversion is working and does not change the key in the process.

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);
    }

When I run:

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

I get back:

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:


OpenSSH public key files (id_*.pub also the entries in known_hosts and authorized_keys) for SSH2 use an OpenSSH-specific variant of an SSH-specific format, see rfc4716 which is in turn based on the SSH2 wire format (as linked) rfc4253 6.6, which is not the 'X.509' format Java crypto uses. (OpenSSH file formats for SSH1 were different, but SSH1 is long broken and should not be used.)

To convert this in Java see convert openSSH rsa key to javax.crypto.Cipher compatible format .

It's easier to avoid the problem.

Bypass 1: If you have reasonably recent OpenSSH (6.0 is okay, not sure for earlier), use

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

to convert to 'X.509' (really SubjectPublicKeyInfo aka SPKI) in PEM form. (Yes they do use the name PKCS8 to mean SPKI; it's crazy.) Then read this in Java by discarding the BEGIN and END lines, decode everything in between (less the line breaks) from base64 to byte[], and put that in X509EncodedKeySpec as you have now. Or if you have OpenSSL you can convert to DER form

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

and then read the DER file with no change at all into an X509EncodedKeySpec.

Bypass 2: if you have the private key, and it is NOT OpenSSH's 'new' format (optional since 6.5 (edit) and default since 7.8), and you have OpenSSL, get the public key in SPKI (Java-friendly) format with one of

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


来源:https://stackoverflow.com/questions/39105031/java-security-spec-invalidkeyspecexception-java-io-ioexception-unexpected-end

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!