Не удается загрузить хранилище ключей JKS, содержащее
Я пытаюсь загрузить хранилище ключей JKS, содержащее промежуточный сертификат CA, полученный с существующего веб-сервера.
Сертификат Verisign показан ниже.
-----BEGIN CERTIFICATE-----
MIIF5DCCBMygAwIBAgIQW3dZxheE4V7HJ8AylSkoazANBgkqhkiG9w0BAQUFADCB
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMTYxMTA3MjM1OTU5WjCBujEL
MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2UgYXQg
aHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykwNjE0MDIGA1UEAxMrVmVy
aVNpZ24gQ2xhc3MgMyBFeHRlbmRlZCBWYWxpZGF0aW9uIFNTTCBDQTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAJjboFXrnP0XeeOabhQdsVuYI4cWbod2
nLU4O7WgerQHYwkZ5iqISKnnnbYwWgiXDOyq5BZpcmIjmvt6VCiYxQwtt9citsj5
OBfH3doxRpqUFI6e7nigtyLUSVSXTeV0W5K87Gws3+fBthsaVWtmCAN/Ra+aM/EQ
wGyZSpIkMQht3QI+YXZ4eLbtfjeubPOJ4bfh3BXMt1afgKCxBX9ONxX/ty8ejwY4
P1C3aSijtWZfNhpSSENmUt+ikk/TGGC+4+peGXEFv54cbGhyJW+ze3PJbb0S/5tB
Ml706H7FC6NMZNFOvCYIZfsZl1h44TO/7Wg+sSdFb8Di7Jdp91zT91ECAwEAAaOC
AdIwggHOMB0GA1UdDgQWBBT8ilC6nrklWntVhU+VAGOP6VhrQzASBgNVHRMBAf8E
CDAGAQH/AgEAMD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxodHRw
czovL3d3dy52ZXJpc2lnbi5jb20vY3BzMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6
Ly9FVlNlY3VyZS1jcmwudmVyaXNpZ24uY29tL3BjYTMtZzUuY3JsMA4GA1UdDwEB
/wQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZ
MFcwVRYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7
GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwKQYDVR0R
BCIwIKQeMBwxGjAYBgNVBAMTEUNsYXNzM0NBMjA0OC0xLTQ3MD0GCCsGAQUFBwEB
BDEwLzAtBggrBgEFBQcwAYYhaHR0cDovL0VWU2VjdXJlLW9jc3AudmVyaXNpZ24u
Y29tMB8GA1UdIwQYMBaAFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqGSIb3DQEB
BQUAA4IBAQCWovp/5j3t1CvOtxU/wHIDX4u6FpAl98KD2Md1NGNoElMMU4l7yVYJ
p8M2RE4O0GJis4b66KGbNGeNUyIXPv2s7mcuQ+JdfzOE8qJwwG6Cl8A0/SXGI3/t
5rDFV0OEst4t8dD2SB8UcVeyrDHhlyQjyRNddOVG7wl8nuGZMQoIeRuPcZ8XZsg4
z+6Ml7YGuXNG5NOUweVgtSV1LdlpMezNlsOjdv3odESsErlNv1HoudRETifLriDR
fip8tmNHnna6l9AW5wtsbfdDbzMLKTB3+p359U64drPNGLT5IO892+bKrZvQTtKH
qQ2mRHNQ3XBb7a1+Srwi1agm5MKFIA3Z
-----END CERTIFICATE-----
Я импортировал сертификат в хранилище ключей JKS с помощью следующей команды:
keytool -importcert -trustcacerts -alias vs -file vs.cer -keystore vs.jks -storepass changeit -storetype JKS
Я проверил, что keytool может читать детали сертификата из только что созданного хранилища ключей.
Наконец, я использую следующий код Java для загрузки хранилища ключей:
final KeyStore trustStore = KeyStore.getInstance("JKS");
trustStream = getClass().getClassLoader().getResourceAsStream("vs.jks");
trustStore.load(trustStream, "changeit".toCharArray());
В настоящее время используется JDK 1.7.0_51.
К сожалению, исключение выдается в методе load().
java.security.cert.CertificateParsingException: java.io.IOException: X500 RDN
at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:171)
at sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1788)
at sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:202)
at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:97)
at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339)
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:747)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55)
at java.security.KeyStore.load(KeyStore.java:1214)
...
Caused by: java.io.IOException: X500 RDN
at sun.security.x509.RDN.<init>(RDN.java:242)
at sun.security.x509.X500Name.parseDER(X500Name.java:804)
at sun.security.x509.X500Name.<init>(X500Name.java:307)
at sun.security.x509.CertificateIssuerName.<init>(CertificateIssuerName.java:82)
at sun.security.x509.X509CertInfo.parse(X509CertInfo.java:685)
at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:169)
... 37 more
Я делаю что-то не так?
У меня такое ощущение, что в сертификате есть что-то неожиданное, что сбивает с толку парсер. Трассировка стека предполагает, что может быть проблема с анализом имени эмитента.
Что я могу сделать, чтобы обойти это?
2 ответа
Я выяснил причину. Ничего плохого в файле сертификата или хранилище ключей!
Я использую Maven для компиляции своего проекта, который автоматически копирует файл jks в целевой каталог сборки.
Оказалось, что в процессе копирования Maven предположил, что файл представляет собой текстовый файл, и "услужливо" преобразовал любые расширенные символы ASCII (>= 0x80) в '?' (0x3F)!
Анализируя / перечисляя файл JKS, я, естественно, только заглядывал в свой исходный каталог и никогда не думал, что файл ресурсов идентичен по содержанию!
Подтверждает золотое правило, никогда не верь Maven!
Я решил это, добавив следующее в мой pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>jks</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
У меня недавно было то же самое исключение:
java.security.cert.CertificateParsingException: java.io.IOException: X500 RDN
Я немного оглянулся назад в историю нашего ртутного репо, и довольно ясно, что было произведено слияние различных хранилищ ключей, когда были внесены изменения из аналогичного репо (другого выпуска). В результате все эти хранилища ключей были "слитые" были фактически повреждены.
Ручное копирование поврежденных файлов между репозиториями решило проблему.