java.security.spec.InvalidKeySpecException: java.io.IOException: 意外的内容结束标记
java.security.spec.InvalidKeySpecException: java.io.IOException: unexpected end-of-contents marker
我正在尝试将 .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)
OpenSSH public 密钥文件(id_*.pub
也是 known_hosts
和 authorized_keys
中的条目)SSH2 使用 OpenSSH -SSH 特定格式的特定变体,请参阅 rfc4716 which is in turn based on the SSH2 wire format (as linked) 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
转换为 PEM 形式的 'X.509'(实际上是 SubjectPublicKeyInfo aka SPKI)。 (是的,他们确实使用名称 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 的 'new' 格式(自 6.5 起可选) (编辑)和 default 从 7.8 开始),并且您有 OpenSSL,使用 [=22] 之一获取 SPKI(Java-友好)格式的 public 密钥=]
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
我正在尝试将 .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)
OpenSSH public 密钥文件(id_*.pub
也是 known_hosts
和 authorized_keys
中的条目)SSH2 使用 OpenSSH -SSH 特定格式的特定变体,请参阅 rfc4716 which is in turn based on the SSH2 wire format (as linked) 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
转换为 PEM 形式的 'X.509'(实际上是 SubjectPublicKeyInfo aka SPKI)。 (是的,他们确实使用名称 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 的 'new' 格式(自 6.5 起可选) (编辑)和 default 从 7.8 开始),并且您有 OpenSSL,使用 [=22] 之一获取 SPKI(Java-友好)格式的 public 密钥=]
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