我在Java android上使用grpc,使用双向SSL(tls),我的服务器为我生成了2个证书(server.ca和client.ca)和一个私钥(key.key),我更改了密钥我知道了(对PKCS8进行基本密钥加密) 来自
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
收件人:
-----END PRIVATE KEY-----
并使用此代码通过grpc用okhttp生成了我的sslcontext。
private static byte[] getBytesFromInputStream(InputStream is) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[0xFFFF];
for (int len = is.read(buffer); len != -1; len = is.read(buffer)) {
os.write(buffer, 0, len);
}
return os.toByteArray();
}
// build a key store from a set of raw certificates
private static KeyStore createKeyStore(Resources resources, int certsId, boolean ca) {
KeyStore ks = null;
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
if (ca) {
ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
InputStream certIS = resources.openRawResource(R.raw.server);
X509Certificate cert = (X509Certificate) cf.generateCertificate(certIS);
ks.setCertificateEntry("ca", cert);
} else {
ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null, null);
InputStream certIS = resources.openRawResource(R.raw.client);
Certificate cert = cf.generateCertificate(certIS);
InputStream privateKeyIS = resources.openRawResource(R.raw.key);
byte[] privateKeyBytes = getBytesFromInputStream(privateKeyIS);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(privateKeyBytes)));
Certificate[] certChain = new Certificate[1];
certChain[0] = cert;
ks.setKeyEntry("client", privateKey, null, certChain);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return ks;
}
public static ManagedChannel build(String host, int port, Resources resources,
@Nullable String serverHostOverride) {
KeyStore ca = createKeyStore(resources, R.array.certs, true);
KeyStore client = createKeyStore(resources, R.array.certs, false);
OkHttpChannelBuilder channelBuilder =
OkHttpChannelBuilder.forAddress(host, port);
if (serverHostOverride != null) {
// Force the hostname to match the cert the server uses.
channelBuilder.overrideAuthority(serverHostOverride);
}
try {
channelBuilder.negotiationType(io.grpc.okhttp.NegotiationType.TLS);
channelBuilder.useTransportSecurity();
channelBuilder.sslSocketFactory(getSslSocketFactory(ca, client));
} catch (Exception e) {
throw new RuntimeException(e);
}
return channelBuilder.build();
}
private static SSLSocketFactory getSslSocketFactory(KeyStore ca, KeyStore client)
throws Exception {
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
String password = "";
kmf.init(client, password.toCharArray());
// initialize trust manager factor from certs keystore
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ca);
// initialize SSL context from trust manager factory
SSLContext context = SSLContext.getInstance("TLS");
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
// return socket factory from the SSL context
return context.getSocketFactory();
}
public void connectGrpc() throws Exception {
ManagedChannel c = build("MyPc", 5051, this.getResources(), null);
TabletServiceGrpc.TabletServiceBlockingStub bs = TabletServiceGrpc.newBlockingStub(c);
GetName g= GetName.newBuilder().setField(1).build();
GetNameResponse res=bs.getNameByField(g);
Log.e(TAG,res.getCategoryName());
}
我收到以下错误:
Read error: ssl=0x7890e89c88: Failure in SSL library, usually a protocol error
error:100000d7:SSL routines:OPENSSL_internal:SSL_HANDSHAKE_FAILURE
(third_party/openssl/boringssl/src/ssl/ssl_lib.cc:1017 0x787007e1bb:0x00000000)
io.grpc.StatusRuntimeException: UNAVAILABLE: End of stream or IOException
我的密钥从PKCS#1转换为PKCS#8是否有问题?还是还有其他东西? 我尝试根据android docs更改代码,但它与之匹配,并且可以正常工作。