2016-08-23 82 views
0

我试图将.pub文件的内容转换为PublicKey,然后将PublicKey转换回String以确定如果转换正在运行并且不会更改进程中的密钥。java.security.spec.InvalidKeySpecException:java.io.IOException:意外的内容结束标记

id_rsa.pub

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0zszKhcZTC8xJidUszmRn4Tr/FxPs04wpCzEstebfTW7Bvqgtt+OdvxoNyYM0LAEnxEF4XhAWcsX7VJJqstZLpDqlKDXFr2d0aVIjksCpZt+ftVRwYHRoERhEOP/UmPFb5rKIkhQbED2kTWg11mW9soc6BhwB3THn/Cyo3t1u2vWjEySgPhKeA3Xzh+5eqV7CUD8V6S7OAT7T9ijf7sRV0R8rwHgTLWJ8+dETnY3L3N0fEaNuaayeNblHqrL53/1+tsBBUF3bAS+1GE6oniSeM/yhtfzf2x+O5MDlVVMbOCC/v+FnfIIEKLA+v1xDSAha7C5cHh82TxToWXsbjqGD [email protected] 

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) 

回答

0

的OpenSSH公共密钥文件用于SSH2使用特定SSH-格式的特定的OpenSSH变的,见其又基于所述SSH2线格式rfc4716((id_*.pub也是在known_hosts条目和authorized_keys)作为链接)rfc4253 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;这太疯狂了)。然后通过丢弃BEGIN和END行来读取它,将base64之间的所有内容(少于换行符)解码为byte[],并将其作为X509EncodedKeySpec你现在有。或者,如果你有OpenSSL的,您可以转换为DER形式

openssl rsa -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 IINM可选),你有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 -pubput -out pub.der -outform der # DER, 1.0.0