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;
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) {
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() {
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);
- }
- }
}
--- /dev/null
+package org.asamk.signal.util;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+public class RandomUtils {
+
+ private static final ThreadLocal<SecureRandom> LOCAL_RANDOM = new ThreadLocal<SecureRandom>() {
+ @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();
+ }
+}
--- /dev/null
+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);
+ }
+ }
+}