I am trying to make gRPC over TLS working on Android using a self-signed
cert. The code is as following:
InputStream testCA = new ByteArrayInputStream(CA.getBytes("UTF8"));
> mChannel = ZnzGrpcChannelBuilder.build(mHost, mPort, null, true, testCA,
> "alpn");
> GRPCDummyServerGrpc.GRPCDummyServerBlockingStub stub = GRPCDummyServerGrpc.
> newBlockingStub(mChannel);
> SumRequest sumRequest = SumRequest.newBuilder().setStart(start).setCount(
> 20).build();
> SumResponse sumResponse = stub.sum(sumRequest);
ZnzGrpcChannelBuilder is a customized channel builder to enable self-signed
cert. As can be seen from Wireshark, the TLS negotiation has completed and the
server starts
to send SETTINGS to the Android client. But the client did not send any
SETTINGS frames.
What I am missing here? Thank you very much.
public class ZnzGrpcChannelBuilder {
public static ManagedChannel build(String host, int port, @Nullable String
serverHostOverride,
boolean useTls, @Nullable InputStream testCa, @Nullable String
androidSocketFactoryTls) {
ManagedChannelBuilder<?> channelBuilder =
ManagedChannelBuilder.forAddress(host,
port);
if (serverHostOverride != null) {
// Force the hostname to match the cert the server uses.
channelBuilder.overrideAuthority(serverHostOverride);
}
if (useTls) {
try {
SSLSocketFactory factory;
if (androidSocketFactoryTls != null) {
factory = getSslCertificateSocketFactory(testCa, androidSocketFactoryTls);
} else {
factory = getSslSocketFactory(testCa);
}
((OkHttpChannelBuilder) channelBuilder).negotiationType(NegotiationType.TLS
);
((OkHttpChannelBuilder) channelBuilder).sslSocketFactory(factory);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
channelBuilder.usePlaintext(true);
}
return channelBuilder.build();
}
private static SSLSocketFactory getSslSocketFactory(@Nullable InputStream
testCa)
throws Exception {
if (testCa == null) {
return (SSLSocketFactory) SSLSocketFactory.getDefault();
}
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, getTrustManagers(testCa), null);
return context.getSocketFactory();
}
@TargetApi(14)
private static SSLCertificateSocketFactory getSslCertificateSocketFactory(
@Nullable InputStream testCa, String androidSocketFatoryTls) throws Exception
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH /* API
level 14 */) {
throw new RuntimeException(
"android_socket_factory_tls doesn't work with API level less than 14.");
}
SSLCertificateSocketFactory factory = (SSLCertificateSocketFactory)
SSLCertificateSocketFactory.getDefault(5000 /* Timeout in ms*/);
// Use HTTP/2.0
byte[] h2 = "h2".getBytes();
byte[][] protocols = new byte[][]{h2};
if (androidSocketFatoryTls.equals("alpn")) {
Method setAlpnProtocols =
factory.getClass().getDeclaredMethod("setAlpnProtocols", byte[][].class);
setAlpnProtocols.invoke(factory, new Object[]{protocols});
} else if (androidSocketFatoryTls.equals("npn")) {
Method setNpnProtocols =
factory.getClass().getDeclaredMethod("setNpnProtocols", byte[][].class);
setNpnProtocols.invoke(factory, new Object[]{protocols});
} else {
throw new RuntimeException("Unknown protocol: " + androidSocketFatoryTls);
}
if (testCa != null) {
factory.setTrustManagers(getTrustManagers(testCa));
}
return factory;
}
private static TrustManager[] getTrustManagers(InputStream testCa) throws
Exception
{
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(testCa);
X500Principal principal = cert.getSubjectX500Principal();
ks.setCertificateEntry(principal.getName("RFC2253"), cert);
// Set up trust manager factory to use our key store.
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(ks);
return trustManagerFactory.getTrustManagers();
}
}
--
*Grab is hiring. Learn more at **https://grab.careers
<https://grab.careers/>*
By communicating with Grab Inc and/or its subsidiaries, associate companies
and jointly controlled entities (“Grab Group”), you are deemed to have
consented to processing of your personal data as set out in the Privacy
Notice which can be viewed at https://grab.com/privacy/
This email contains confidential information and is only for the intended
recipient(s). If you are not the intended recipient(s), please do not
disseminate, distribute or copy this email and notify Grab Group
immediately if you have received this by mistake and delete this email from
your system. Email transmission cannot be guaranteed to be secure or
error-free as any information therein could be intercepted, corrupted,
lost, destroyed, delayed or incomplete, or contain viruses. Grab Group do
not accept liability for any errors or omissions in the contents of this
email arises as a result of email transmission. All intellectual property
rights in this email and attachments therein shall remain vested in Grab
Group, unless otherwise provided by law.
--
You received this message because you are subscribed to the Google Groups
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/grpc-io.
To view this discussion on the web visit
https://groups.google.com/d/msgid/grpc-io/eb277548-5dc2-4bd9-895b-282a2f3d822a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.