react-native-tcp-socket icon indicating copy to clipboard operation
react-native-tcp-socket copied to clipboard

PKCS#12 Keystore Format Support Question

Open Telos-dev opened this issue 9 months ago • 2 comments

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.

Telos-dev avatar Mar 06 '25 06:03 Telos-dev

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;
}

}

Telos-dev avatar Mar 06 '25 08:03 Telos-dev

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

vricosti avatar Mar 06 '25 21:03 vricosti