SSL issue: alert number 46 (sslv3 alert certificate unknown) - java

I am stuck with an issue of (SSL alert number 46)
140097325019584:error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate
unknown:../ssl/record/rec_layer_s3.c:1528:SSL alert number 46
Above issue comes when I give crl-file in haproxy config.
Usecase
I am using HAPROXY for ssl termination. I had self signed ca.crt,ca.pem,server.crt,server.pem and client.crt,client.key,crl.pem
Working Scenario
I had generated self signed certificate using Certificate Generate
Ha proxy config
global
log 127.0.0.1 local0 debug
tune.ssl.default-dh-param 2048
defaults
log global
listen mqtt
bind *:2883
bind *:8883 ssl crt /etc/ssl/certs/server.pem verify required ca-file /etc/ssl/certs/ca.pem crl-file /etc/ssl/certs/crl.pem
mode tcp
option tcplog
option clitcpka # For TCP keep-alive
tcp-request content capture dst len 15
timeout client 3h #By default TCP keep-alive interval is 2hours in OS kernal, 'cat /proc/sys/net/ipv4/tcp_keepalive_time'
timeout server 3h #By default TCP keep-alive interval is 2hours in OS kernal
balance leastconn
# MQTT broker 1
server broker_1 ray-mqtt:1883 check send-proxy-v2-ssl-cn
# MQTT broker 2
# server broker_2 10.255.4.102:1883 check
This above config working well with and without crl-file while I generate certificate using Certificate Generate
Non Working Scenario
I generate all certificate using Java bouncy castle library.
Client Certi Generate
public static X509Certificate generateClientCertificate(X509Certificate issuerCertificate, PrivateKey issuerPrivateKey, KeyPair keyPair, X500Name dnName, BigInteger serialNumber) throws IOException, OperatorCreationException, CertificateException {
JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(SHA_256_WITH_RSA).setProvider("BC");
JcaX509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
issuerCertificate, //here intermedCA is issuer authority
serialNumber, new Date(),
Date.from(Instant.now().plus(100, ChronoUnit.DAYS)),
dnName, keyPair.getPublic());
builder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature));
builder.addExtension(Extension.basicConstraints, false, new BasicConstraints(false));
X509Certificate x509Certificate = new JcaX509CertificateConverter()
.getCertificate(builder
.build(signerBuilder.build(issuerPrivateKey)));// private key of signing authority , here it is signed by intermedCA
return x509Certificate;
}
CRL Generate
private static X509CRL generateCrl(X509Certificate ca, PrivateKey caPrivateKey, PublicKey caPublicKey,
X509Certificate... revoked) throws Exception {
X509v2CRLBuilder builder = new X509v2CRLBuilder(
new X500Name(ca.getSubjectDN().getName()),
new Date()
);
builder.setNextUpdate(Date.from(Instant.now().plus(100000l, ChronoUnit.HOURS)));
for (X509Certificate certificate : revoked) {
builder.addCRLEntry(certificate.getSerialNumber(), new Date(), CRLReason.PRIVILEGE_WITHDRAWN.ordinal());
}
builder.addExtension(Extension.cRLNumber, false, new CRLNumber(BigInteger.valueOf(4)));
// builder.addExtension(Extension.authorityKeyIdentifier, false, new AuthorityKeyIdentifier(ca.getEncoded()));
builder.addExtension(Extension.authorityKeyIdentifier, false,
new JcaX509ExtensionUtils().createAuthorityKeyIdentifier(caPublicKey));
JcaContentSignerBuilder contentSignerBuilder =
new JcaContentSignerBuilder(SHA_256_WITH_RSA_ENCRYPTION);
contentSignerBuilder.setProvider(BC_PROVIDER_NAME);
X509CRLHolder crlHolder = builder.build(contentSignerBuilder.build(caPrivateKey));
JcaX509CRLConverter converter = new JcaX509CRLConverter();
converter.setProvider(BC_PROVIDER_NAME);
return converter.getCRL(crlHolder);
}
Here, In HAproxy config when I will not include crl-file then It works with the client certificates.
but when I include crl-file into the haproxy config then it will give alert number 46 (sslv3 alert certificate unknown) error.
I had verified using openssl
cat client3.pem | openssl verify -CAfile ca.crt
which returns OK.
Output of openssl s_client -connect haproxy:8883 -cert client3.crt -key client3.key -CAfile ca.crt
CONNECTED(00000005)
depth=1 CN = *.ray.life
verify return:1
depth=0 CN = haproxy
verify return:1
---
Certificate chain
0 s:CN = haproxy
i:CN = *.ray.life
1 s:CN = *.ray.life
i:CN = *.ray.life
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIBujCCASOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDAoqLnJh
eS5saWZlMB4XDTIwMDEwNzExMzIyOFoXDTIwMDQxNjExMzIyOFowEjEQMA4GA1UE
AwwHaGFwcm94eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0CAq/xYcCXWl
PJgs2+DeRRO5DRK813LIiRzdoMFeKrI9X5yXeNFzc6mSAS9EdFITM/HJYSvL/XhZ
p+Hu3N2f9ZR/zD2hpTq2PP0lK3Ev6gryXpWXoJU2SbtOyLsjPmw1y/+xHUjVv5B6
V+m7b0I3RYN8blcJIkjl7Gz83GMlMucCAwEAAaMdMBswDgYDVR0PAQH/BAQDAgeA
MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAnmIG9SXICU78Dz2eGbNN2znY
OGCpt7TBDkuXthStAFAyzHxZFKqexkelnJNMg19CbWzxGrPk6lxJQ+ebCGEYZwiZ
/WB9C1fQm+07/FEKVc1TCKv0odpTGRyXno4NePnFz6MCJGfVmec0huVPMD9fAbeJ
DlcWed88CL1MdgmkKoQ=
-----END CERTIFICATE-----
subject=CN = haproxy
issuer=CN = *.ray.life
---
Acceptable client certificate CA names
CN = *.ray.life
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:ECDSA+SHA1:RSA+SHA224:RSA+SHA1
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1440 bytes and written 1488 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 1024 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
139659759231424:error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown:../ssl/record/rec_layer_s3.c:1528:SSL alert number 46
Any help will be very useful for me.

You need to add the AKI and SKI extension in the CA certificate to validate the CRL by HA proxy.

Related

How do I convert a binary certificate to x509?

I have a server certificate that I want to trust. But java doesn't accept it in this code. How do I convert the certificate to x509?
return (Collection<X509Certificate>) CertificateFactory.getInstance("X.509")
.generateCertificates(new ByteArrayInputStream(cert.getBytes()));
cert:
0‚я0‚з \±
®FPљF·1ЪуAяф0
*†H†ч
0Ѓ•10 UGB10UGreater Manchester10USalford10U
Sectigo Limited1=0;U4Sectigo RSA Organization Validation Secure Server CA0
210913000000Z
221014235959Z0e10 URU10
UMoskva10U
PJSC MTS Bank10 UIT1 0Utestpayments.mtsbank.ru0‚"0
†H†ч
‚ 0‚
‚ БLR€fЁВGK}ЧІЅџ¬‡ »FйЎNлNЕї¦жШЪvДhг,Чb‘ђ‰(фњkЬ4эµoµQS¶4¦9
0bц±€ks%®xЇҐ4ўжк¦…ФnДF†Ж]b{L|Ш7’ЪmIЈvўДЉ„ym¶T\ьЛСx)Ѓ€~х’Ѓiр·юЎKЦfРћ'-ѓКђђЂ)И;\ЙБ/ФфЂ&C®¤Л
°‚M;щн_ 1~#JЅJРЯЖЈ1Ю•н)Ќµdґnы–оШ9:4њSН¬ъИЊ­ь.уЈ8чІ  ИЄФ9йѕфqj–Эао=KДњX%Р§я~A7± Ј‚x0‚t0U#0ЂЩЦ%'gщ1ВICЩ06DЊl©Oл0UзEКЁуІ‡Sґ«&›И 9 S :50Uя 0Uя0 0U%0++0JU C0A05+І10%0#+https://sectigo.com/CPS0gЃ0ZUS0Q0O M K†Ihttp://crl.sectigo.com/SectigoRSAOrganizationValidationSecureServerCA.crl0ЃЉ+~0|0U+0†Ihttp://crt.sectigo.com/SectigoRSAOrganizationValidationSecureServerCA.crt0#+0†http://ocsp.sectigo.com0?U806‚testpayments.mtsbank.ru‚www.testpayments.mtsbank.ru0‚} +Цy‚m‚ig u FҐUлuъ‘ 0µў‰iфу},AtѕэIё…«тьpюmG {Ю|ъ] F0D &я$„ѕT<ЎюЯC jД‘ћDЇ‚вЕЏWјV}д °Љ)n›мРДtщq©,mІGќеЬ–Pjп–®e v AИК±Я"FJЖЎ: B‡^N1‹ллKЗhрђb–ц {Ю|ъ" G0E! Я55eЮьэW;ыФ/µр·ћІNцw*\¤OGќ
M 50МЖіT{жМ‘П=ЧНHэД9v‚UOеСуЧ$ v )yѕрћ99!рVsџcҐwеѕW}њ шщM]&\%]З„ {Ю|щэ G0E gЫx;·ґш1шнГ*Z“ЬЄЪ2ы••vIоhЮ! чxтЁ‹Е–ќµ\©mШ= 6ўчеЧ{Ўь:кё6лЄг0
†H†ч
‚ Ћz™ЋQZп^чZVеVцOS;‰?Њ4Щї;Д8?•1ЫА:rZўПгdфИ zTдt3¦СЊҐБ™»g[R¦oаOH;¬Ъw{†хІDuљ,1Кc­ЂЂ5НAR
6СаГ ќщџэБДСЊ-ё“fќCs’ПСЫ%иаѕ‹[5с|Т~FН§b4эKйЃ39&нџЫ’Т2>Щид8”Ќtп9–-bўоbRі›]Љ9аNgцЄ7.ЁOЯ[)©Фµх. ®тмҐ{µ¦`·|оьуР¬]сЂІv9ЋWХH›xаrЁУя»zЛ_рJ.З;yS#}Ё
I tried to do so but failed:
OpenSSL> x509 -in Z:\cert.cer -out Z:\cert12.pem
unable to load certificate
10976:error:0906D06C:PEM routines:PEM_read_bio:no start line:crypto\pem\pem_lib.c:686:Expecting: TRUSTED CERTIFICATE
error in x509
Encoded in base64 through the file and the code passed
https://www.base64encode.org/

SSLHandshakeException: Received fatal alert: handshake_failure - 2Way SSL

I wrote an Http Client using Apache HttpClient 4.1.13 which call a remote HTTP service using 2way-ssl.
I configured:
keystore.jks : contains the private key and the client certificate
keystore password: the password of keystore.jks
truststore.jks: contains the certificate of CA e intermediate CA of the server
truststore password: the password of truststore.jks
the code:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File(keystore));
try {
keyStore.load(instream, keyStorePassword.toCharArray());
} finally {
instream.close();
}
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
instream = new FileInputStream(new File(trustore));
try {
trustStore.load(instream, trustorePassword.toCharArray());
} finally {
instream.close();
}
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
.build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslContext,
new String[] {"TLSv1.1","TLSv1.2"},
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
poolingConnManager = new PoolingHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", sslsf)
.build());
If I run a java main (JDK Java(TM) SE Runtime Environment (build 1.8.0_231-b11) which does the call, I got a successful connection and I see in the logs
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - Secure session established
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - negotiated protocol: TLSv1.2
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - negotiated cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - peer principal: XXXXX
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - peer alternative names: [YYYYY]
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - issuer principal: XXXXX
If I run the same code with the same keystores and passwords in Docker OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)) I got the following handshake error
http-nio-8080-exec-1, READ: TLSv1.2 Alert, length = 2
http-nio-8080-exec-1, RECV TLSv1.2 ALERT: fatal, handshake_failure
%% Invalidated: [Session-1, SSL_NULL_WITH_NULL_NULL]
%% Invalidated: [Session-2, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
http-nio-8080-exec-1, called closeSocket()
http-nio-8080-exec-1, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
[2022-01-25 16:47:45][SESSION_NOT_INITIALIZED][10.60.168.202][http-nio-8080-exec-1] [DEBUG]o.a.h.i.c.DefaultManagedHttpClientConnection - http-outgoing-0: Shutdown connection
[2022-01-25 16:47:45][SESSION_NOT_INITIALIZED][10.60.168.202][http-nio-8080-exec-1] [DEBUG]o.a.h.impl.execchain.MainClientExec - Connection discarded
What should I search ? Any hints?
UPDATE:
The keystore contains the private key and the certificate chain : certificate -> intermediate CA -> Root CA; I don't understand why the client doesn't find the right certificate to send to the server.
In the working test I got this log
*** ServerHelloDone
[read] MD5 and SHA1 hashes: len = 4
0000: 0E 00 00 00 ....
matching alias: 1
*** Certificate chain
In the failed test I got:
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
It was my mistake and the problem was in totally different point.
The above code was right.

Dropwizard Client Certificate Authentication via HttpClient Key/Trust store

I am running a dropwizard server, and a client leveraging Apache HttpClient 4.5.1.
Given a single .pfx file that contains both the public and private keys, how would I structure my key/trust stores on both the server and client to accept/trust and pass the certificate for authentication purposes?
What I'm running into is the client trusts the provided server certificate, but
after the server hello that includes the certificate request per tls spec, my client is unable to find a suitable certificate to send back.
My first thought was to run the server with the keystore and truststore as the same pfx file, but java throws a null cert chain error when loading the pfx file as a trust store in the server. So I had to go through the process of creating a trust store manually.
Here are the general steps I thought would allow this entire process to succeed:
Run the server with the .pfx file, with a PKCS12 keystore type.
Extract the cert from the pfx file, and create a java trust store using the cert.
Run the server with the above clientCerts.jks file as the trust store
Run the client with a keystore set to the clientCerts.jks file
Run the client with a truststore set to the .pfx PKCS12 keystore.
These steps didn't work, and I've tried other less obvious permutations and none of them worked. Is there something blatantly wrong with the way I'm approaching this? Does anyone have any advice on actually getting it to work?
Lots of details below (including ssl debug logs)
PFX cert info:
(its a valid corporate signed cert, but I don't have the root CA as trusted anywhere, which is why I just create a trust store so I can trust the client cert).
$ openssl pkcs12 -info -in cert.pfx
Enter Import Password:
MAC Iteration 1
MAC verified OK
PKCS7 Data
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2000
Bag Attributes
Microsoft Local Key set: <No Values>
localKeyID: 01 00 00 00
friendlyName: xxx
Microsoft CSP Name: Microsoft RSA SChannel Cryptographic Provider
Key Attributes
X509v3 Key Usage: 10
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----BEGIN ENCRYPTED PRIVATE KEY-----
xxx
-----END ENCRYPTED PRIVATE KEY-----
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2000
Certificate bag
Bag Attributes
localKeyID: 01 00 00 00
friendlyName: my.domain.com
subject=/C=US/O=My Company/OU=Web Servers/CN=my.domain.com
issuer=/C=US/O=My Company
-----BEGIN CERTIFICATE-----
xxx
-----END CERTIFICATE-----
Java Trust store Creation:
//create pem file
openssl pkcs12 -in cert.pfx -out tempCert.crt -nokeys -clcerts
//convert to x509
openssl x509 -inform pem -in tempCert.crt -outform der -out tempx509Cert.cer
//create a java trust store
keytool -import -file tempx509Cert.cer -alias firstCA -keystore newJavaTrustStore.jks
Dropwizard Config:
applicationConnectors:
- type: https
port: 443
bindHost: localhost
keyStorePath: ./cert.pfx
keyStorePassword: pw
keyStoreType: PKCS12
trustStorePath: ./clientCerts.jks
trustStorePassword: pw
trustStoreType: JKS
supportedProtocols: [TLSv1, TLSv1.1, TLSv1.2]
excludedProtocols: [SSLv2Hello, SSLv3]
validateCerts: false
needClientAuth: true
wantClientAuth: true
HttpClient Config Values:
keyStorePath: ./clientCerts.jks
keyStorePassword: pw
keyStoreType: JKS
trustStorePath: ./cert.pfx
trustStorePassword: pw
trustStoreType: PKCS12
HttpClient Config:
public static CloseableHttpClient getSecurePooledHttpClient(
final String host,
final int port,
final boolean ssl,
final String keystorePath,
final String keystorePassword,
final String keystoreType,
final String trustStorePath,
final String trustStorePassword,
final String trustStoreType
) throws Exception {
//Setup the keystore that will hold the client certificate
KeyStore ks = KeyStore.getInstance(keystoreType);
ks.load(new FileInputStream(new File(keystorePath)),
keystorePassword.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, keystorePassword.toCharArray());
//Setup the Trust Store so we know what certificates
//we can trust that are hosting the service
KeyStore ts = KeyStore.getInstance((trustStoreType));
ts.load(new FileInputStream(new File(trustStorePath)),
trustStorePassword.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
//setup our SSL context to be TLSv1.2, then setup the key and trust manager.
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
//Register the socket factory so that it uses the ssl Context and key
// manager we created above
Registry<ConnectionSocketFactory> socketFactoryRegistry =
RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", new SSLConnectionSocketFactory(sslContext,
NoopHostnameVerifier.INSTANCE))
.build();
//Define an overridden routeplanner that setups up our default host
// so all our later calls can simply be
//sub-routes.
HttpRoutePlanner routePlanner =
new DefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE)
{
#Override
public HttpRoute determineRoute(
final HttpHost target,
final HttpRequest request,
final HttpContext context) throws HttpException {
return super.determineRoute(
target != null ? target : new HttpHost(host, port, ssl ? "https" : "http"),
request, context);
}
};
return BuildClientWithRoutePlanner(socketFactoryRegistry, routePlanner);
Client SSL debug:
...
*** ServerHello, TLSv1.2
RandomCookie: Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Initialized: [Session-7, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256]
** TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: CN=my.domain.com, OU=Web Servers, O=My Company, C=US
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
.........
***
Found trusted certificate:
[
[
Version: V3
Subject: CN=my.domain.com, OU=Web Servers, O=My Company, C=US
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 2048 bits
......
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
Cert Authorities:
<CN=my.domain.com, OU=Web Servers, O=My Company, C=US>
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
***

How do I read an sha1WithRSAEncryption public DER key in Java?

openssl x509 -inform DER -text
on my DER file gives the dump on the bottom of this question.
I try to read it with:
static PublicKey getCertKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
URL keyUrl = Resources.getResource(LManager.class, "iid.der");
byte[] keyBytes = Resources.toByteArray(keyUrl);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
And I get:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:205)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
....
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Caused by: java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)
at sun.security.x509.X509Key.decode(X509Key.java:397)
at sun.security.x509.X509Key.decode(X509Key.java:403)
at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:83)
at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:298)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:201)
... 25 more
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
a9:cb:e1:41:03:30:df:c5
Signature Algorithm: sha1WithRSAEncryption
Issuer: REDACTED
Validity
Not Before: Jun 5 14:28:02 2014 GMT
Not After : Jun 5 14:28:02 2024 GMT
Subject: REDACTED
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:87:bd:18:df:ff:49:12:b6:92:76:e3:c9:21:b4:
86:8d:f2:a9:03:37:7b:64:c3:85:63:bc:0f:67:bc:
f9:76:6a:72:4e:f9:e2:01:52:a3:df:40:6d:3d:91:
99:70:a5:6a:66:c8:ef:1b:18:1d:91:5a:a5:b1:0b:
0b:81:fd:d7:27:22:86:fa:c3:8d:b4:93:d5:98:e4:
2d:08:20:6b:43:44:d6:ae:37:79:2e:bc:65:e4:c3:
71:c4:9c:5d:04:8d:8a:f4:a5:cc:96:52:f0:72:59:
8e:0a:b3:06:55:e3:65:fb:63:b5:d2:4b:5d:e1:38:
87:0b:e8:d2:c0:f8:7f:78:fd
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
25:D6:CC:08:15:CA:B6:F0:9C:59:DC:14:52:2C:EF:B5:41:76:51:38
X509v3 Authority Key Identifier:
keyid:25:D6:CC:08:15:CA:B6:F0:9C:59:DC:14:52:2C:EF:B5:41:76:51:38
DirName:/C=US/ST=Washington/L=Seattle/O=Amazon.com Inc./CN=ec2.amazonaws.com
serial:A9:CB:E1:41:03:30:DF:C5
X509v3 Basic Constraints:
CA:TRUE
First, openssl -inform DER -text is an error. The openssl program is a wrapper that runs one of a bunch of functions, identified by the first argument, which in this case must be x509, so openssl x509 -inform DER -text.
That's a clue. Your file is an X.509 certificate not (just) a public key. Certificates in general, and X.509 certificates in particular, contain a public key but that is not the same thing as being a public key.
Since your file is an X.509 certificate, use a CertificateFactory of type X.509 to read it. The pattern is similar: use a static .getInstance() method to get a factory then use .generateCertificate() to take some input, here a stream that reads the data (directly from the file, or from memory if you have it buffered), and generate a Certificate object. (Note java.security.cert.Certificate not the obsolete and deprecated java.security.Certificate -- some IDEs may not default to the good one.)
If you want to use the public key in the certificate for something like encrypting or verifying call .getPublicKey() on the Certificate. If you want to look at other information such as the subject name or extensions which are specific to X.509, cast the Certificate to X509Certificate (also in java.lang.security.cert) and use its additional methods.
Also: the certificate is signed with sha1withRSA. The publickey itself is an RSA key, and could be used for any RSA operation -- but since the cert claims this key belongs to a CA, the corresponding privatekey should be used only for signing certs and/or CRLs (controlled by KeyUsage if present, but it's not unless you've redacted it) and thus doing something with this publickey other than verifying those certs and/or CRLs is useless. And since the key is only 1024 bits, using a signing hash stronger than SHA1 would be wasted, except for the facts that RSA-1024 is already considered insecure (since early 2014) and using SHA1-RSA for certificates is considered at risk and prohibited after sometime next year.

KeyStoreException: No private keys found in keystore with not-yet-commons-ssl-0.3.11.jar

In the course of using Client certificates for authentication, I decided to use not-yet-commons-ssl-0.3.11.jar. That has resulted in another issue - the simple act of invoking the constructor on EasySSLProtocolSocketFactory or StrictSSLProtocolSocketFactory will produce an exception.
The code, as isolated in a simple cmd line app:
public class CertTest {
public static void main(String[] args) {
System.setProperty("javax.net.debug", "ssl,handshake"); // SSL DEBUG INFO
String keystore = "/usr/java/jdk1.6.0_11/jre/lib/security/cacerts";
String keystorePassword = "changeit";
System.setProperty("javax.net.ssl.keyStore", keystore);
System.setProperty("javax.net.ssl.keyStorePassword", keystorePassword);
// System.setProperty("javax.net.ssl.trustStore", keystore);
// System.setProperty("javax.net.ssl.trustStorePassword", keystorePassword);
try {
org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory factory =
new org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory();
}
catch (Exception e) {
System.out.println (e);
}
}
}
To isolate issues with older libs, I put the above code in a directory with these jars (these are the ONLY jars in the classpath):
httpclient-4.0.1.jar
not-yet-commons-ssl-0.3.11.jar
commons-httpclient-3.1.jar
httpcore-4.0.1.jar
So, with some client certificates in the cacerts keystore, I get:
org.apache.commons.ssl.ProbablyBadPasswordException: Probably bad JKS-Key password: java.security.UnrecoverableKeyException: Password must not be null
If I use keytool to delete all the client certificates that I have loaded, then the exception changes to
**Caused by: java.security.KeyStoreException: No private keys found in keystore!**
at org.apache.commons.ssl.KeyStoreBuilder.validate(KeyStoreBuilder.java:269)
at org.apache.commons.ssl.KeyStoreBuilder.build(KeyStoreBuilder.java:129)
at org.apache.commons.ssl.KeyMaterial.(KeyMaterial.java:179)
at org.apache.commons.ssl.KeyMaterial.(KeyMaterial.java:170)
at org.apache.commons.ssl.KeyMaterial.(KeyMaterial.java:160)
at org.apache.commons.ssl.KeyMaterial.(KeyMaterial.java:64)
at org.apache.commons.ssl.KeyMaterial.(KeyMaterial.java:114)
at org.apache.commons.ssl.KeyMaterial.(KeyMaterial.java:89)
at org.apache.commons.ssl.SSL.(SSL.java:142)
at org.apache.commons.ssl.SSLClient.(SSLClient.java:59)
at org.apache.commons.ssl.HttpSecureProtocol.(HttpSecureProtocol.java:55)
at org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory.(EasySSLProtocolSocketFactory.java:94)
Snippets in the output:
keyStore is : /usr/java/jdk1.6.0_11/jre/lib/security/cacerts
keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
trustStore is: /usr/java/jdk1.6.0_11/jre/lib/security/cacerts
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
Subject: CN=SwissSign Platinum CA - G2, O=SwissSign AG, C=CH
Issuer: CN=SwissSign Platinum CA - G2, O=SwissSign AG, C=CH
Algorithm: RSA; Serial number: 0x4eb200670c035d4f
whole bunch of default trusted certs snipped here...
trigger seeding of SecureRandom
done seeding SecureRandom
########## EXCEPTION
java.security.KeyStoreException: No private keys found in keystore!
Any ideas?
java.security.KeyStoreException: No private keys found in keystore!
This exception specifically complains that there are no private keys in the keystore you are trying to load.
In the case of cacerts which is Java's default truststore this is true!
But with the code you have posted (meaning you have not posted any code really) or the fact that you don't say anything about the keystore you are trying to load it is not possible to help you on this.

Categories

Resources