Java Bug : Mutual HTTPS authentication not possible with a non-extractable private key with Apple/KeychainStore
Wei-Jun Wang
weijun.wang at oracle.com
Mon May 3 14:03:38 UTC 2021
Hi Jean-Yves,
On macOS there’s only native key/certificate management but no signature signing/verification. If you look at https://docs.oracle.com/javase/9/security/oracleproviders.htm, the Apple provider only implements KeyStore. If you need to use a key in client auth, it needs to extract that key and use another provider (SunRsaSign or SunEC) to use it.
On the other hand, SunMSCAPI has implemented both KeyStore and Signature, therefore it can do both things inside the provider and the key does not need to be extracted.
I’ve filed https://bugs.openjdk.java.net/browse/JDK-8266439.
Thanks,
Weijun
> On May 1, 2021, at 8:19 AM, Jean-Yves Cronier <cronier.jy at gmail.com> wrote:
>
> Description
> I have imported my personal certificate in macOS keychain with "non-extractable" option (cf. https://ss64.com/osx/security-export.html <https://ss64.com/osx/security-export.html>).
> Private key is now protected, and we can't export private key from macOS KeyChain
> But I am unable to establish connexion with a web-API which require client certificate for mutual authentication with Java
> It work perfectly well with curl/git, and browsers (safari/chrome)
> <>System / OS / Java Runtime Information
> openjdk 11.0.11
> macOS 11.3
> <>Reproducing the Issue
> <>Steps to Reproduce
> 1. Add personal certificate with "non-extractable" option. Example with a personal certificate sent to me in a P12 file named "my-certificate.p12", with following command-line:
> security import my-certificate.p12 -x -P « my-strong-password"
> 2. Connect a site require mutual authentication (for example : https://server.cryptomix.com/secure/ <https://server.cryptomix.com/secure/> )
> <>Expected Result
> Display content detail of selected client certificate
> <>Actual Result
> Error: No TLS client certificate presented
> <>Source code for an executable test case
> import javax.net.ssl.HttpsURLConnection;
> import java.io.IOException;
> import java.net.URL;
> import java.security.cert.X509Certificate;
>
> public class MutualAuthenticationTest {
> public static void main(String[] args) throws IOException {
> System.setProperty("javax.net.ssl.keyStoreType", "KeychainStore");
> System.setProperty("javax.net.ssl.keyStore", "NONE");
> System.setProperty("javax.net.ssl.keyStorePassword", "-");
> testUrl(new URL("https://server.cryptomix.com/secure/"));
> }
>
> public static void testUrl(URL targetUrl) throws IOException {
> HttpsURLConnection con = (HttpsURLConnection) targetUrl.openConnection();
> // Open the connection
> con.getResponseCode();
>
> assert con.getLocalCertificates() != null && con.getLocalCertificates().length > 0 : "Must use a personnel certificate for mutual authentication";
> X509Certificate personalCertificate = (X509Certificate) con.getLocalCertificates()[0];
> assert personalCertificate.getSubjectDN() != null;
> }
> }
> <>Workaround
> No possible workaround on MacOS which Apple/KeychainStore
> NB : Perfectly work on Windows/MSCAPI with personnel certificate (with non-exportable private key option)
More information about the jdk-dev
mailing list