plasma-umass / doppio

Breaks the browser language barrier (includes a plugin-free JVM).
http://plasma-umass.github.io/doppio-demo
MIT License
2.16k stars 174 forks source link

No strong SecureRandom implementation present #454

Closed ianopolous closed 8 years ago

ianopolous commented 8 years ago

Running code that calls java.security.SecureRandom.getInstanceStrong() throws "No strong SecureRandom impls available: NativePRNGBlocking:SUN"

jvilk commented 8 years ago

I'm guessing there's either a native method we are missing for SecureRNG, or we need to set a magic system property pointing to a class that implements secure RNG.

jvilk commented 8 years ago

@ianopolous Can you submit a minimal Java class with a public static void main that exhibits this issue?

ianopolous commented 8 years ago

The system property is "securerandom.strongAlgorithms" It's of the following format: / * Entries are alg:prov separated by , * Allow for prepended/appended whitespace between entries. * Capture groups: * 1 - alg * 2 - :prov (optional) * 3 - prov (optional) * 4 - ,nextEntry (optional) * 5 - nextEntry (optional) / private static Pattern pattern = Pattern.compile( "\s([\S&&[^:,]])(\:([\S&&[^,]]))?\s(\,(.))?");

ianopolous commented 8 years ago

This should be sufficient. My code calls it deep in Peergos, but this is equivalent:

import java.security.*;

class test {
  public static void main(String[] args) {
    java.security.SecureRandom.getInstanceStrong();
  }
}
jvilk commented 8 years ago

Interesting. This code works under Node on my Mac because it simply reads /dev/urandom. :)

The system property contains the following data:

#
# A list of known strong SecureRandom implementations.
#
# To help guide applications in selecting a suitable strong
# java.security.SecureRandom implementation, Java distributions should
# indicate a list of known strong implementations using the property.
#
# This is a comma-separated list of algorithm and/or algorithm:provider
# entries.
#
securerandom.strongAlgorithms=NativePRNGBlocking:SUN

It looks like to do this the "proper way", we'd have to have a DoppioSecurityProvider that provides RNG for the browser, and register that with the JVM.

I'm making a small change right now to move doppio.jar generation and classes from the doppio_jcl repository into this repository, which will make it easy to add custom Doppio classes like these in the future.

ianopolous commented 8 years ago

The best cross browser (and node) code I'm aware of for finding a secure random source is from the end of: https://github.com/dchest/tweetnacl-js/blob/master/nacl.js (public domain)

  // Initialize PRNG if environment provides CSPRNG.
  // If not, methods calling randombytes will throw.
  var crypto;
  if (typeof window !== 'undefined') {
    // Browser.
    if (window.crypto && window.crypto.getRandomValues) {
      crypto = window.crypto; // Standard
    } else if (window.msCrypto && window.msCrypto.getRandomValues) {
      crypto = window.msCrypto; // Internet Explorer 11+
    }
    if (crypto) {
      nacl.setPRNG(function(x, n) {
        var i, v = new Uint8Array(n);
        crypto.getRandomValues(v);
        for (i = 0; i < n; i++) x[i] = v[i];
        cleanup(v);
      });
    }
  } else if (typeof require !== 'undefined') {
    // Node.js.
    crypto = require('crypto');
    if (crypto) {
      nacl.setPRNG(function(x, n) {
        var i, v = crypto.randomBytes(n);
        for (i = 0; i < n; i++) x[i] = v[i];
        cleanup(v);
      });
    }
  }
jvilk commented 8 years ago

Committed in https://github.com/plasma-umass/doppio/commit/f23922ab733cc831943bd6b3808ab3afc0982a46, but the CI build is broken for some unknown reason (it stalls on running Java to generate unit test data).

Keeping this open until that gets cleared up...

jvilk commented 8 years ago

Alright, my change works!

Small note: crypto is not available in WebWorkers in Firefox until Firefox 48 hits, causing Travis-CI failures in that browser. This is outside of our control, so I am marking this as "closed".