react-native-tcp-socket
react-native-tcp-socket copied to clipboard
PKCS#12 Keystore Format Support Question
Description: I've been experiencing issues implementing SSL in my React Native application using react-native-tcp-socket. I discovered that the only keystore file that works with the library uses RC2-40-CBC encryption (as shown by openssl pkcs12 -info -in keystore.p12):
MAC: sha1, Iteration 2048 MAC length: 20, salt length: 8 PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2048
This is considered insecure by modern standards.
Question: Does react-native-tcp-socket support modern encryption standards for PKCS#12 keystores, or is it limited to legacy formats like RC2-40-CBC? If modern standards are supported, could you provide guidance on generating compatible certificates with current OpenSSL versions that don't compromise security? Environment:
React Native version: [0.78.0] react-native-tcp-socket version: [6.2.0] Platform: Android
Steps to reproduce:
Generated a keystore using modern OpenSSL defaults Implemented SSL socket connection following documentation Received errors about invalid keystore format:
ReactNativeJS: 'Server Error - Full details:', '"exception decrypting data - java.lang.IllegalArgumentException: password empty"'
Only succeeded when using a legacy-formatted keystore with RC2-40-CBC encryption
Any guidance on creating secure, compatible certificates would be greatly appreciated, as the current solution doesn't seem appropriate for production use.
I worked around it:
static SSLServerSocketFactory createServerSocketFactory(Context context, @NonNull final String keyStoreResourceUri) throws GeneralSecurityException, IOException {
Here instead of char[] password = "".toCharArray() use a "\0" null terminator
char[] password = "\0".toCharArray();
Log.d("TCPSocket", "Using empty password");
try {
InputStream keyStoreInput = getRawResourceStream(context, keyStoreResourceUri);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(keyStoreInput, password);
keyStoreInput.close();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
keyManagerFactory.init(keyStore, password);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[]{new BlindTrustManager()}, null);
return sslContext.getServerSocketFactory();
} catch (Exception e) {
throw e;
}
}
I am not really answering to your question but in my PR request I have implemented the possibility to give a certificate/private key through PEM strings or files.. Maybe we can join our forces in that battle: https://github.com/Rapsssito/react-native-tcp-socket/pull/208