From: AsamK Date: Tue, 20 Nov 2018 23:07:05 +0000 (+0100) Subject: Use custom SecureRandom instance X-Git-Tag: v0.6.1~5 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/5f2190713afdcc57469384f11bfb0926f1a64b7f Use custom SecureRandom instance - Use NativePRNG algorithm instead of using SHA1PRNG if available - Register a custom security provider to use the same SecureRandom everywhere --- diff --git a/src/main/java/org/asamk/signal/Main.java b/src/main/java/org/asamk/signal/Main.java index a0820f24..df22e63b 100644 --- a/src/main/java/org/asamk/signal/Main.java +++ b/src/main/java/org/asamk/signal/Main.java @@ -24,6 +24,8 @@ import org.asamk.Signal; import org.asamk.signal.commands.*; import org.asamk.signal.manager.BaseConfig; import org.asamk.signal.manager.Manager; +import org.asamk.signal.util.SecurityProvider; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.freedesktop.dbus.DBusConnection; import org.freedesktop.dbus.exceptions.DBusException; import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; @@ -35,8 +37,9 @@ import java.util.Map; public class Main { public static void main(String[] args) { - // Workaround for BKS truststore - Security.insertProviderAt(new org.bouncycastle.jce.provider.BouncyCastleProvider(), 1); + // Register our own security provider + Security.insertProviderAt(new SecurityProvider(), 1); + Security.addProvider(new BouncyCastleProvider()); Namespace ns = parseArgs(args); if (ns == null) { diff --git a/src/main/java/org/asamk/signal/manager/KeyUtils.java b/src/main/java/org/asamk/signal/manager/KeyUtils.java index 225cf682..617893fc 100644 --- a/src/main/java/org/asamk/signal/manager/KeyUtils.java +++ b/src/main/java/org/asamk/signal/manager/KeyUtils.java @@ -1,10 +1,8 @@ package org.asamk.signal.manager; +import org.asamk.signal.util.RandomUtils; import org.whispersystems.signalservice.internal.util.Base64; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - class KeyUtils { private KeyUtils() { @@ -33,15 +31,7 @@ class KeyUtils { private static byte[] getSecretBytes(int size) { byte[] secret = new byte[size]; - getSecureRandom().nextBytes(secret); + RandomUtils.getSecureRandom().nextBytes(secret); return secret; } - - private static SecureRandom getSecureRandom() { - try { - return SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - throw new AssertionError(e); - } - } } diff --git a/src/main/java/org/asamk/signal/util/RandomUtils.java b/src/main/java/org/asamk/signal/util/RandomUtils.java new file mode 100644 index 00000000..d0463b47 --- /dev/null +++ b/src/main/java/org/asamk/signal/util/RandomUtils.java @@ -0,0 +1,37 @@ +package org.asamk.signal.util; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +public class RandomUtils { + + private static final ThreadLocal LOCAL_RANDOM = new ThreadLocal() { + @Override + protected SecureRandom initialValue() { + SecureRandom rand = getSecureRandomUnseeded(); + + // Let the SecureRandom seed it self initially + rand.nextBoolean(); + + return rand; + } + }; + + private static SecureRandom getSecureRandomUnseeded() { + try { + return SecureRandom.getInstance("NativePRNG"); + } catch (NoSuchAlgorithmException e) { + // Fallback to SHA1PRNG if NativePRNG is not available (e.g. on windows) + try { + return SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e1) { + // Fallback to default + return new SecureRandom(); + } + } + } + + public static SecureRandom getSecureRandom() { + return LOCAL_RANDOM.get(); + } +} diff --git a/src/main/java/org/asamk/signal/util/SecurityProvider.java b/src/main/java/org/asamk/signal/util/SecurityProvider.java new file mode 100644 index 00000000..9177a781 --- /dev/null +++ b/src/main/java/org/asamk/signal/util/SecurityProvider.java @@ -0,0 +1,44 @@ +package org.asamk.signal.util; + +import java.security.Provider; +import java.security.SecureRandom; +import java.security.SecureRandomSpi; + +public class SecurityProvider extends Provider { + + private static final String PROVIDER_NAME = "SSP"; + + private static final String info = "Security Provider v1.0"; + + public SecurityProvider() { + super(PROVIDER_NAME, 1.0, info); + put("SecureRandom.DEFAULT", DefaultRandom.class.getName()); + + // Workaround for BKS truststore + put("KeyStore.BKS", "org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi$Std"); + put("KeyStore.BKS-V1", "org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi$Version1"); + put("KeyStore.BouncyCastle", "org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi$BouncyCastleStore"); + put("KeyFactory.X.509", "org.bouncycastle.jcajce.provider.asymmetric.x509.KeyFactory"); + put("CertificateFactory.X.509", "org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory"); + } + + public static class DefaultRandom extends SecureRandomSpi { + + private static final SecureRandom random = RandomUtils.getSecureRandom(); + + public DefaultRandom() { + } + + protected void engineSetSeed(byte[] bytes) { + random.setSeed(bytes); + } + + protected void engineNextBytes(byte[] bytes) { + random.nextBytes(bytes); + } + + protected byte[] engineGenerateSeed(int numBytes) { + return random.generateSeed(numBytes); + } + } +}