Got the following exception when running Android P with https:
java.lang.VerifyError: Verifier rejected class okhttp3.internal.tls.HeldCertificate$Builder: okhttp3.internal.tls.HeldCertificate okhttp3.internal.tls.HeldCertificate$Builder.build() failed to verify: okhttp3.internal.tls.HeldCertificate okhttp3.internal.tls.HeldCertificate$Builder.build(): [0x9D] register v7 has type Reference: org.bouncycastle.asn1.ASN1ObjectIdentifier but expected Reference: org.bouncycastle.asn1.DERObjectIdentifier (declaration of 'okhttp3.internal.tls.HeldCertificate$Builder' a
Here is the test code to start the MockWebServer:
MockWebServer mockWebServer = new MockWebServer();
mockWebServer.useHttps(SslClient.localhost().socketFactory, false);
mockWebServer.start();
Are you shipping an incompatible version of bouncycastle with your project? HeldCertificate depends on bouncycastle 1.50, though perhaps we should update the library to require a newer version.
... or perhaps build our own certificate encoder and avoid the bouncycastle dependency altogether!
@swankjesse does that mean that including implementation com.squareup.okhttp3:okhttp-tls:3.11.0 is enough since org.bouncycastle:bcprov-jdk15on:1.50 is a transitive dependency, right?
That's not the case in my project (testet on Android emulator with API 21 - 28) where I do the following to setup https for testing with MockWebServer:
val localhostCertificate = HeldCertificate.Builder()
.addSubjectAlternativeName(InetAddress.getByName("localhost").canonicalHostName)
.build()
If I don't add additional bouncy castle dependencies I get the following error:
java.lang.AssertionError: java.security.NoSuchAlgorithmException: no such algorithm: ECDSA for provider BC
at okhttp3.tls.HeldCertificate$Builder.generateKeyPair(HeldCertificate.java:429)
at okhttp3.tls.HeldCertificate$Builder.build(HeldCertificate.java:353)
...
Nevertheless, I can confirm that you get this error
java.lang.VerifyError: Verifier rejected class okhttp3.internal.tls.HeldCertificate$Builder:
okhttp3.internal.tls.HeldCertificate okhttp3.internal.tls.HeldCertificate$Builder.build() failed to verify:
okhttp3.internal.tls.HeldCertificate okhttp3.internal.tls.HeldCertificate$Builder.build(): [0x9D] register v7 has type Reference: org.bouncycastle.asn1.ASN1ObjectIdentifier but expected Reference:
org.bouncycastle.asn1.DERObjectIdentifier (declaration of 'okhttp3.internal.tls.HeldCertificate$Builder' a
if you use a different version of bouncy castle (like org.bouncycastle:bctls-jdk15on:1.60)
@sockeqwe gotcha. You must be pulling in yet another version somehow. If you explicitly specify 1.50 does it work?
In any case we should update our code to 1.60 for the next release.
java.lang.AssertionError: java.security.NoSuchAlgorithmException: no such algorithm: ECDSA for provider BC
at okhttp3.tls.HeldCertificate$Builder.generateKeyPair(HeldCertificate.java:429)
at okhttp3.tls.HeldCertificate$Builder.build(HeldCertificate.java:353)
implementation "com.squareup.okhttp3:okhttp-tls:3.11.0"
implementation "org.bouncycastle:bcprov-ext-jdk15on:1.50"
causes aapt2 error at compile time
AGPBI: {"kind":"error","text":"Program type already present: org.bouncycastle.LICENSE","sources":[{}],"tool":"D8"}
implementation (testLibraries.okhttpTls){
exclude group: 'org.bouncycastle'
}
implementation "org.bouncycastle:bcprov-ext-jdk15on:1.50"
causes
java.lang.AssertionError: java.security.NoSuchAlgorithmException: no such algorithm: ECDSA for provider BC
at okhttp3.tls.HeldCertificate$Builder.generateKeyPair(HeldCertificate.java:429)
at okhttp3.tls.HeldCertificate$Builder.build(HeldCertificate.java:353)
implementation "com.squareup.okhttp3:okhttp-tls:3.11.0"
implementation "org.bouncycastle:bcpkix-jdk15on:1.50"
causes
java.lang.AssertionError: java.security.NoSuchAlgorithmException: no such algorithm: ECDSA for provider BC
at okhttp3.tls.HeldCertificate$Builder.generateKeyPair(HeldCertificate.java:429)
at okhttp3.tls.HeldCertificate$Builder.build(HeldCertificate.java:353)
Is there any other bouncy castle dependency that I should use?
Btw. starting in bouncy castle 1.60 seems to have a dedicated artifact for tls: org.bouncycastle:bctls-jdk15on:1.60
Our tests pass with bcprov-jdk15on.
on my macbook during unit tests it works too, but not on an android
emulator.
Jesse Wilson notifications@github.com schrieb am So., 29. Juli 2018,
23:45:
Our tests pass with bcprov-jdk15on.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/square/okhttp/issues/4175#issuecomment-408708132, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAjnrlRbIUp3X_dmLvcdEv80MhpydJh0ks5uLizfgaJpZM4Vi8iR
.
Hm. Will investigate.
I created a new issue here: #4183
Instead of using SslClient.localhost().socketFactory, I create a cert and load to Android Keystore,
MockWebServer mockWebServer = new MockWebServer();
mockWebServer.useHttps(getSSLSocketFactory(), false);
private SSLSocketFactory getSSLSocketFactory() throws Exception {
char[] password = "password".toCharArray();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
Calendar notAfter = Calendar.getInstance();
notAfter.add(Calendar.DAY_OF_YEAR, 1);
X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
new X500Principal("CN=localhost"),
new BigInteger("1"),
new Date(),
notAfter.getTime(),
new X500Principal("CN=localhost"),
keyPair.getPublic());
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSAEncryption")
.build(keyPair.getPrivate());
builder.build(contentSigner);
X509Certificate certificate = new JcaX509CertificateConverter()
.getCertificate(builder.build(contentSigner));
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = null;
keyStore.load(in, password);
Certificate[] certificateChain = {certificate};
keyStore.setKeyEntry("private", keyPair.getPrivate(), password, certificateChain);
keyStore.setCertificateEntry("cert", certificate);
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password);
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(),
new SecureRandom());
return sslContext.getSocketFactory();
}
Running it with our current code on Android P:
Caused by: java.security.NoSuchAlgorithmException: ECDSA KeyPairGenerator not available
at java.security.KeyPairGenerator.getInstance(KeyPairGenerator.java:241)
at okhttp3.tls.HeldCertificate$Builder.generateKeyPair(HeldCertificate.java:426)
This is fixed by replacing ECDSA with RSA2048
HeldCertificate localhostCertificate = new HeldCertificate.Builder()
.addSubjectAlternativeName(localhost)
.rsa2048()
.build();
But I’d still like to figure out how to get ECDSA working on Android!
Most helpful comment
... or perhaps build our own certificate encoder and avoid the bouncycastle dependency altogether!