Closed emojahedi closed 8 years ago
Using the Google Play Services Security Provider is pretty necessary on older devices in order to have ALPN support and be less buggy. I'd recommend using it even on newer devices, because it contains bug fixes.
The provider is https://conscrypt.org/, which you could compile yourself and include in your app. But you will then be shipping BoringSSL with your app which will increase app size.
Netty doesn't help because it would still require a recent TLS implementation.
Thank you it was a great help.
And I should note that we are working on a cronet-based transport (as an alternative to OkHttp, mainly for QUIC support). It would always include its own copy of boringssl, so it would not depend on Google Play Services Security Provider.
I got the same error. I used Python to implement my server. And the Python client could work correctly with it. But my Android client couldn't. Who could tell me why? Thanks!
Sorry, I've located the root cause for my issue: I didn't add user permission for my android application. Just addin the following line into AndroidManifest.xml could fix my issue:
<uses-permission android:name="android.permission.INTERNET" />
@ericgribkoff I still see this exception on Android devices < 21. Is the cronet based transport is available ? Or Do I have to use the above mechanism using Google Play Services Security Provider ?
The Cronet transport is not yet available, mainly due to low prioritization. For devices < 21, you should use the Google Play Services Security Provider. If this isn't a viable solution for your target audience, let me know and I can look further into Cronet as an alternative - it's primarily a matter of investigating what it would take to get the Cronet dependencies integrated into gRPC's build system.
@ericgribkoff I will get back to you on this by the end of this week
It's also possible to ship conscrypt.org as part of your app (it's the same thing that comes with Android and Google Play Services Security Provider). This used to mean compiling it yourself, but I now see a conscrypt-android aar artifact on Maven Central, so that may be a semi-easy alternative.
@ejona86 thanks. Unfortunately it is gonna increaseo ur app size in an inefficient way. @ericgribkoff can you help us on getting cronet with smaller size ? or any alternative to get it working on <21 devices ?
Cronet should be strictly larger than conscrypt. Both include boringssl, and most of conscrypt's size is from boringssl.
I experimented with adding Cronet to our interop test app, and it actually clocks in just a little smaller than org.conscrypt:conscrypt-android:1.0.0.RC8
. But it's still an increase of ~9-10MB.
Just spoke with @ejona86 and it's probably possible to get a smaller build of Conscrypt if you explore building it yourself. For example, netty-tcnative-boringssl-static includes boringssl and is only ~2.5MB. @kraghu if that kind of size increase is acceptable to your app, that's probably the best (and only) approach I can suggest here.
I just checked, stripping the Conscrypt binaries cuts their size by ⅘ths. I filed google/conscrypt#266. So I'm seeing proper Conscrypt binaries being at most ½ the size of Cronet binaries.
(Let it be known I'm not against Cronet. But by its nature it would be very strange for it to be smaller than Conscrypt.)
@ejona86 @ericgribkoff It looks like google service's ProviderInstaller.installIfNeeded()
wont help the grpc case at all. There is a note clearly stating this in the link
Caution: Updating a device's security Provider does not update android.net.SSLCertificateSocketFactory. Rather than using this class, we encourage app developers to use high-level methods for interacting with cryptography. Most apps can use APIs like HttpsURLConnection without needing to set a custom TrustManager or create an SSLCertificateSocketFactory.
Can GRPC android provides some way to set HttpsURLConnection
using the right SSLCertificateSocketFactory
in those cases as described in the note? This will be an easier solution for android and we can avoid increasing the app size by not including any library . This is how okhttp library handled this situation before
The quote just means not to use that class directly, expecting it to be updated. gRPC Android does the correct thing and uses the preferred provider on the device; this will handle TLS properly if ProviderInstaller.installIfNeeded()
succeeds. Please see the app code for an example of this in action, although note that the test app's failure handling is not as robust as in the documentation link you provided - specifically, our test app does not try GooglePlayServicesUtil.showErrorDialogFragment
, although it probably should.
As I understand it, this is the recommended way of handling security on older devices, and it's compatible with gRPC Android without any increase in APK size. Bundling Conscrypt was the suggested solution for environments where an up-to-date Google Play Services is not available.
I will also note that gRPC already allows you to specify your instance of SSLCertificateSocketFactory. Although, honestly, I'd discourage people from using it since virtually all recent bug reports with TLS on Android turned out to be caused by bugs in the app's factory (or the app's factory triggering bugs in the underlying libraries (not gRPC)).
@ejona86 @ericgribkoff based on our last conversation I should either include io.netty:netty-tcnative-boringssl-static:2.0.5.Final or Conscrypt . You were going to strip down Conscrypt by half of its size . where can I get it ? Which one is recommended for <21 devices ? It looks like conscrypt is not on mavent yet.
There's a new RC release, 1.0.0.RC9, that doesn't include debug symbols. Consrypt is on Maven Central. Note that RC9 was very recently released and hasn't been indexed by search.maven.org yet. But it is available.
@kraghu, FYI, I just made #3301 that says how to configure Conscrypt at runtime.
@ejona86 thank you so much. will try today
@kraghu FYI I encountered some issues getting the Conscrypt jar on Maven to run with Android API level 19 and below (tested 16 and 19). I've filed https://github.com/google/conscrypt/issues/276 to track this: I believe they may need to release a new version of the library to support these lower API levels.
@ejona86 I still sees ssl error .I included Conscrpt and tried to provide it on run time . Is there any thing I am missing ?
EDITED: Oops i saw your message now @ericgribkoff .What should I do mean while . I also think it has to do with the way Android devices get manufacture upgrading. Although some upgraded devices say they are 19 but they are actually 14 or 15 and wont comply with google service upgrades and many other behaviors. This is pretty much a big problem in android with upgraded devices:(
@kraghu If you need something immediately, you'll have to compile Conscrypt yourself: there are instructions at https://github.com/google/conscrypt/blob/master/BUILDING.md
Can we provide okhttp client to OkHttpChannelBuilder? I run this problem with glide too, provide the glide with okhttp client fix the https issue.
I tried provide OkHttpChannelBuilder with sslSocketFactory using method in this url https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.Builder.html#sslSocketFactory-javax.net.ssl.SSLSocketFactory-javax.net.ssl.X509TrustManager-. But no luck.
FYI if anyone struggles with this I got it to work on API 19 (after much pain and re-reading this thread). Two problems, nothing providing the correct algorithms (conscrypt solves) and API 19 using SSL2/3 by default:
build.gradle:
compile 'org.conscrypt:conscrypt-android:1.0.0+'
Install provider, e.g. in MainActivity class:
static { Security.insertProviderAt(Conscrypt.newProvider("GmsCore_OpenSSL"), 1); }
Add class TLSSocketFactory: From https://gist.github.com/fkrauthan/ac8624466a4dee4fd02f#file-tlssocketfactory-java
Build your channel as follow:
OkHttpChannelBuilder managedChannelBuilder = OkHttpChannelBuilder.forAddress(HOST, PORT);
managedChannelBuilder.sslSocketFactory(new TLSSocketFactory());
managedChannel = managedChannelBuilder.build();
You could of course do this in 1 line.
What worked for me to solve this issue on android < 21 - when you are creating channel for SpeechGrpc try to add this line to builder: .connectionSpec(ConnectionSpec.MODERN_TLS), so full code snippet looks like:
final ManagedChannel channel = new OkHttpChannelProvider()
.builderForAddress(HOSTNAME, PORT)
.connectionSpec(ConnectionSpec.MODERN_TLS)
.nameResolverFactory(new DnsNameResolverProvider())
.intercept(new GoogleCredentialsInterceptor(new GoogleCredentials(accessToken)
.createScoped(SCOPE)))
.build();
@mrthemuradin, doing so is all-advised and unsupported when communicating with Google. It breaks certain requirements of HTTP/2. If you maintain your own servers or if the service owner explicitly permits you, then you can change those settings.
While it is possible to use the older ciphers today, this is a hold-over on non-Android from Java 7's poor cipher performance. We handled this by discouraging use of Jetty ALPN in favor of tcnative. Since that problem has been solved for a while now (giving users time to migrate), we may enable the enforcement mandated by the HTTP/2 spec. That will break you.
I have a grpc server written in go which serves through a valid https certificate, and an Android client like the examples but without the
usePlaintext(true)
part.The RPC services work fine for Android devices with sdk-version >= 21, but they fail for older devices with this exception:
Using this mechanism I was able to perform the rpc call on an older device, but the suitable Google Play Services version isn't installed on more than half of the devices in my target population. Is there another way to make grpc work on theses devices? Like switching to Netty-based transport? Is there any sample of an android app usig Netty-based transport?
Thanks in advance