InvalidKeyException: 无效的密钥格式 java
InvalidKeyException: Invalid key format java
我正在尝试从 Vault 中检索 public 密钥。它被秘密存储。
我正在尝试将检索到的字符串转换为 PUBLIC KEY 以验证签名。
示例 public 密钥字符串如下所示
-----BEGIN PUBLIC KEY----- MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBWeqVZ8Ub/o4VQ8nnm888B
/Ydqv2IN5bObxupZ7njMKuT/WPgwlK8+Wc0Xjhy82E51XW6E4/0um8sIQ1cxvoSO
QsrfkRagD+O9OrjQbb2TqrilDDhFx9EGjXuZpR3brDUufCG6SkypqiKSaMuoVoax
c82TZ1uAIp5OSroWt1IdUkvam24X/7zDIf1l8XWCmbfCDrBb73hBYA4MgTjsSckC
5nz+GLcWTfz0wze4lwHCi1KYFv+1+WcYHWPLbqLtc8nzVqkuP5Ne/9HAFkaEAIw5
fKLccksaT/TLyIcrALcfuABlgX1yeBulVcbTAp+WiYRvo9+FKK23pbwkh+uy0tq1
AgMBAAE=
-----END PUBLIC KEY-----
我在我的秘密值中添加了相同的内容,但没有格式化。
但是使用下面的代码我在行中遇到错误 InvalidKeyException: INVALID KEY FORMAT
PublicKey publicKey = fact.generatePublic(pubKeySpec);
代码如下:
String publicKeyAsString = secretClient.getSecret("key-name").getValue();
byte[] keyContentAsBytes = publicKeyAsString.getBytes();
KeyFactory fact = KeyFactory.getInstance("RSA");
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyContentAsBytes);
PublicKey publicKey = fact.generatePublic(pubKeySpec);
使用堆栈跟踪编辑:
Caused by: java.security.InvalidKeyException: invalid key format
at sun.security.x509.X509Key.decode(X509Key.java:386) ~[?:?]
at sun.security.x509.X509Key.decode(X509Key.java:401) ~[?:?]
at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:122) ~[?:?]
at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:330) ~[?:?]
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:235) ~[?:?]
编辑:PUBLIC 测试密钥:
-----BEGIN PUBLIC KEY----- MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBWeqVZ8Ub/o4VQ8nnm888B
/Ydqv2IN5bObxupZ7njMKuT/WPgwlK8+Wc0Xjhy82E51XW6E4/0um8sIQ1cxvoSO
QsrfkRagD+O9OrjQbb2TqrilDDhFx9EGjXuZpR3brDUufCG6SkypqiKSaMuoVoax
c82TZ1uAIp5OSroWt1IdUkvam24X/7zDIf1l8XWCmbfCDrBb73hBYA4MgTjsSckC
5nz+GLcWTfz0wze4lwHCi1KYFv+1+WcYHWPLbqLtc8nzVqkuP5Ne/9HAFkaEAIw5
fKLccksaT/TLyIcrALcfuABlgX1yeBulVcbTAp+WiYRvo9+FKK23pbwkh+uy0tq1
AgMBAAE=
-----END PUBLIC KEY-----
PublicKeyAsString 的值如下所示:
-----BEGIN PUBLIC KEY----- MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBWeqVZ8Ub/o4VQ8nnm888B
/Ydqv2IN5bObxupZ7njMKuT/WPgwlK8+Wc0Xjhy82E51XW6E4/0um8sIQ1cxvoSO
QsrfkRagD+O9OrjQbb2TqrilDDhFx9EGjXuZpR3brDUufCG6SkypqiKSaMuoVoax
c82TZ1uAIp5OSroWt1IdUkvam24X/7zDIf1l8XWCmbfCDrBb73hBYA4MgTjsSckC
5nz+GLcWTfz0wze4lwHCi1KYFv+1+WcYHWPLbqLtc8nzVqkuP5Ne/9HAFkaEAIw5
fKLccksaT/TLyIcrALcfuABlgX1yeBulVcbTAp+WiYRvo9+FKK23pbwkh+uy0tq1
AgMBAAE= -----END PUBLIC KEY-----
最初我认为您的问题与 Azure KeyVault Secret API 返回的信息类型有关,通常编码为 base 64。
在那种情况下,您需要在尝试执行实际密钥 material 处理之前执行适当的 base 64 解码:
String publicKeyAsString = secretClient.getSecret("key-name").getValue();
byte[] keyContentAsBytes = Base64.getDecoder().decode(publicKeyAsString);
但 Azure 客户端似乎以纯文本形式向您提供信息。
在这种情况下,秘密是一个 pem 编码的 public 密钥。
标准 KeyFactory
不允许您开箱即用地处理返回的信息,但可以稍作修改。例如,尝试以下操作:
// Actually
// String publicKeyAsString = secretClient.getSecret("key-name").getValue();
String publicKeyAsString =
"-----BEGIN PUBLIC KEY-----\n" +
"MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBWeqVZ8Ub/o4VQ8nnm888B\n" +
"/Ydqv2IN5bObxupZ7njMKuT/WPgwlK8+Wc0Xjhy82E51XW6E4/0um8sIQ1cxvoSO\n" +
"QsrfkRagD+O9OrjQbb2TqrilDDhFx9EGjXuZpR3brDUufCG6SkypqiKSaMuoVoax\n" +
"c82TZ1uAIp5OSroWt1IdUkvam24X/7zDIf1l8XWCmbfCDrBb73hBYA4MgTjsSckC\n" +
"5nz+GLcWTfz0wze4lwHCi1KYFv+1+WcYHWPLbqLtc8nzVqkuP5Ne/9HAFkaEAIw5\n" +
"fKLccksaT/TLyIcrALcfuABlgX1yeBulVcbTAp+WiYRvo9+FKK23pbwkh+uy0tq1\n" +
"AgMBAAE=\n" +
"-----END PUBLIC KEY-----";
String publicKeyPem = publicKeyAsString
.replace("-----BEGIN PUBLIC KEY-----", "")
.replaceAll("\n", "")
.replace("-----END PUBLIC KEY-----", "");
byte[] keyContentAsBytes = Base64.getDecoder().decode(publicKeyPem);
try {
KeyFactory fact = KeyFactory.getInstance("RSA");
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyContentAsBytes);
PublicKey publicKey = fact.generatePublic(pubKeySpec);
System.out.println(publicKey);
}catch (Throwable t) {
t.printStackTrace();
}
或者更好,使用 BouncyCastle PemReader
完成此任务:
try (
Reader reader = new StringReader(publicKeyAsString);
PemReader pemReader = new PemReader(reader)
) {
KeyFactory fact = KeyFactory.getInstance("RSA");
PemObject pemObject = pemReader.readPemObject();
byte[] keyContentAsBytesFromBC = pemObject.getContent();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyContentAsBytesFromBC);
PublicKey publicKey = fact.generatePublic(pubKeySpec);
System.out.println(publicKey);
} catch (Throwable t) {
t.printStackTrace();
}
请注意,我在变量 publicKeyAsString
的定义中包含了几个回车符 returns,它们是程序处理信息所必需的。
请验证 Azure 是否以类似的方式返回 pem 编码密钥:如果不是这样,很可能是问题的原因。
此外,请注意 Azure KeyVault 会在您上传时返回秘密:也许问题就在那里。请改为尝试以下操作:
PublicKey publicKey = ...
StringWriter writer = new StringWriter();
PemWriter pemWriter = new PemWriter(writer);
pemWriter.writeObject(
new PemObject("PUBLIC KEY", publicKey.getEncoded())
);
pemWriter.flush();
pemWriter.close();
String publicKeyAsString = writer.toString();
// Upload to Azure KeyVault
我正在尝试从 Vault 中检索 public 密钥。它被秘密存储。
我正在尝试将检索到的字符串转换为 PUBLIC KEY 以验证签名。
示例 public 密钥字符串如下所示
-----BEGIN PUBLIC KEY----- MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBWeqVZ8Ub/o4VQ8nnm888B /Ydqv2IN5bObxupZ7njMKuT/WPgwlK8+Wc0Xjhy82E51XW6E4/0um8sIQ1cxvoSO QsrfkRagD+O9OrjQbb2TqrilDDhFx9EGjXuZpR3brDUufCG6SkypqiKSaMuoVoax c82TZ1uAIp5OSroWt1IdUkvam24X/7zDIf1l8XWCmbfCDrBb73hBYA4MgTjsSckC 5nz+GLcWTfz0wze4lwHCi1KYFv+1+WcYHWPLbqLtc8nzVqkuP5Ne/9HAFkaEAIw5 fKLccksaT/TLyIcrALcfuABlgX1yeBulVcbTAp+WiYRvo9+FKK23pbwkh+uy0tq1 AgMBAAE= -----END PUBLIC KEY-----
我在我的秘密值中添加了相同的内容,但没有格式化。
但是使用下面的代码我在行中遇到错误 InvalidKeyException: INVALID KEY FORMAT
PublicKey publicKey = fact.generatePublic(pubKeySpec);
代码如下:
String publicKeyAsString = secretClient.getSecret("key-name").getValue();
byte[] keyContentAsBytes = publicKeyAsString.getBytes();
KeyFactory fact = KeyFactory.getInstance("RSA");
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyContentAsBytes);
PublicKey publicKey = fact.generatePublic(pubKeySpec);
使用堆栈跟踪编辑:
Caused by: java.security.InvalidKeyException: invalid key format
at sun.security.x509.X509Key.decode(X509Key.java:386) ~[?:?]
at sun.security.x509.X509Key.decode(X509Key.java:401) ~[?:?]
at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:122) ~[?:?]
at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:330) ~[?:?]
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:235) ~[?:?]
编辑:PUBLIC 测试密钥:
-----BEGIN PUBLIC KEY----- MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBWeqVZ8Ub/o4VQ8nnm888B /Ydqv2IN5bObxupZ7njMKuT/WPgwlK8+Wc0Xjhy82E51XW6E4/0um8sIQ1cxvoSO QsrfkRagD+O9OrjQbb2TqrilDDhFx9EGjXuZpR3brDUufCG6SkypqiKSaMuoVoax c82TZ1uAIp5OSroWt1IdUkvam24X/7zDIf1l8XWCmbfCDrBb73hBYA4MgTjsSckC 5nz+GLcWTfz0wze4lwHCi1KYFv+1+WcYHWPLbqLtc8nzVqkuP5Ne/9HAFkaEAIw5 fKLccksaT/TLyIcrALcfuABlgX1yeBulVcbTAp+WiYRvo9+FKK23pbwkh+uy0tq1 AgMBAAE= -----END PUBLIC KEY-----
PublicKeyAsString 的值如下所示:
-----BEGIN PUBLIC KEY----- MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBWeqVZ8Ub/o4VQ8nnm888B /Ydqv2IN5bObxupZ7njMKuT/WPgwlK8+Wc0Xjhy82E51XW6E4/0um8sIQ1cxvoSO QsrfkRagD+O9OrjQbb2TqrilDDhFx9EGjXuZpR3brDUufCG6SkypqiKSaMuoVoax c82TZ1uAIp5OSroWt1IdUkvam24X/7zDIf1l8XWCmbfCDrBb73hBYA4MgTjsSckC 5nz+GLcWTfz0wze4lwHCi1KYFv+1+WcYHWPLbqLtc8nzVqkuP5Ne/9HAFkaEAIw5 fKLccksaT/TLyIcrALcfuABlgX1yeBulVcbTAp+WiYRvo9+FKK23pbwkh+uy0tq1 AgMBAAE= -----END PUBLIC KEY-----
最初我认为您的问题与 Azure KeyVault Secret API 返回的信息类型有关,通常编码为 base 64。
在那种情况下,您需要在尝试执行实际密钥 material 处理之前执行适当的 base 64 解码:
String publicKeyAsString = secretClient.getSecret("key-name").getValue();
byte[] keyContentAsBytes = Base64.getDecoder().decode(publicKeyAsString);
但 Azure 客户端似乎以纯文本形式向您提供信息。
在这种情况下,秘密是一个 pem 编码的 public 密钥。
标准 KeyFactory
不允许您开箱即用地处理返回的信息,但可以稍作修改。例如,尝试以下操作:
// Actually
// String publicKeyAsString = secretClient.getSecret("key-name").getValue();
String publicKeyAsString =
"-----BEGIN PUBLIC KEY-----\n" +
"MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBWeqVZ8Ub/o4VQ8nnm888B\n" +
"/Ydqv2IN5bObxupZ7njMKuT/WPgwlK8+Wc0Xjhy82E51XW6E4/0um8sIQ1cxvoSO\n" +
"QsrfkRagD+O9OrjQbb2TqrilDDhFx9EGjXuZpR3brDUufCG6SkypqiKSaMuoVoax\n" +
"c82TZ1uAIp5OSroWt1IdUkvam24X/7zDIf1l8XWCmbfCDrBb73hBYA4MgTjsSckC\n" +
"5nz+GLcWTfz0wze4lwHCi1KYFv+1+WcYHWPLbqLtc8nzVqkuP5Ne/9HAFkaEAIw5\n" +
"fKLccksaT/TLyIcrALcfuABlgX1yeBulVcbTAp+WiYRvo9+FKK23pbwkh+uy0tq1\n" +
"AgMBAAE=\n" +
"-----END PUBLIC KEY-----";
String publicKeyPem = publicKeyAsString
.replace("-----BEGIN PUBLIC KEY-----", "")
.replaceAll("\n", "")
.replace("-----END PUBLIC KEY-----", "");
byte[] keyContentAsBytes = Base64.getDecoder().decode(publicKeyPem);
try {
KeyFactory fact = KeyFactory.getInstance("RSA");
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyContentAsBytes);
PublicKey publicKey = fact.generatePublic(pubKeySpec);
System.out.println(publicKey);
}catch (Throwable t) {
t.printStackTrace();
}
或者更好,使用 BouncyCastle PemReader
完成此任务:
try (
Reader reader = new StringReader(publicKeyAsString);
PemReader pemReader = new PemReader(reader)
) {
KeyFactory fact = KeyFactory.getInstance("RSA");
PemObject pemObject = pemReader.readPemObject();
byte[] keyContentAsBytesFromBC = pemObject.getContent();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyContentAsBytesFromBC);
PublicKey publicKey = fact.generatePublic(pubKeySpec);
System.out.println(publicKey);
} catch (Throwable t) {
t.printStackTrace();
}
请注意,我在变量 publicKeyAsString
的定义中包含了几个回车符 returns,它们是程序处理信息所必需的。
请验证 Azure 是否以类似的方式返回 pem 编码密钥:如果不是这样,很可能是问题的原因。
此外,请注意 Azure KeyVault 会在您上传时返回秘密:也许问题就在那里。请改为尝试以下操作:
PublicKey publicKey = ...
StringWriter writer = new StringWriter();
PemWriter pemWriter = new PemWriter(writer);
pemWriter.writeObject(
new PemObject("PUBLIC KEY", publicKey.getEncoded())
);
pemWriter.flush();
pemWriter.close();
String publicKeyAsString = writer.toString();
// Upload to Azure KeyVault