0
\$\begingroup\$

I have this in place for an RSA Key generation class. I force the user to swipe on the screen randomly and use that as a entropy pool.

class TouchRandom extends SecureRandom {

    private final Stack<Byte> pool = new Stack<>();

    @Override
    public synchronized void nextBytes(byte[] bytes) {
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = pool.pop();
        }
    }

    void addToPool(byte b) {
        pool.push(b);
    }

}

And here is how I feed the pool:

@Override
public boolean onTouchEvent(MotionEvent event) {
    touchRandom.addToPool((byte) event.getX());
    touchRandom.addToPool((byte) event.getY());
    return false;
}

Is this better or worse than a PRNG based on a Elliptic Curve or something else?

(Idea shamelessly stolen from VeraCrypt.)

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

This is a bad idea for different reasons. I'll short-list them and then go into details.

  1. Your distribution isn't random. X and Y values are constrained to screensize, accordingly different devices have different possible randomness distributions, which is a "bad thing"™

  2. User input is not random. "Guess a random number between 1 and 10" is not random and neither is "type on the screen randomly". Humans are really bad at faking randomness.


The x and y value constraints are a bad thing in the first place. Smaller devices have less entropy to generate, larger devices have repetition when the x and y coordinates "repeat", since you truncate any value larger than 8 bits.

Luckily screen-sizes are usually a nice multiple of \$256\times256\$ "tiles". The actually useful entropy you can currently extract accordingly is in one such tile.
Unfortunately this also means that "randomly" tapping similar areas in these tiles (as probably many non-technical people would do) will produce somewhat predictable bytes.

This directly brings us to the next point. The "Blue Seven Phenomenon". There's a metric ton of academic articles about the subject, but the bottom line is: Humans are bad at pretending to be random.
The brain is trained evolutionarily (and throughout our whole lives) to recognize patterns. True randomness doesn't actually exhibit those patterns. Any patterns we see in randomness are just ... imagination. Well not quite, but there's no actual meaning behind them.

The problem is when you ask users to provide "random" input, their brain will simply not be able to provide it, and instead you'll get a more or less pseudorandom pattern.

Long story short, you'll not receive something that I'd deem cryptographically secure.

\$\endgroup\$
4
  • \$\begingroup\$ How come this method is used in VeraCrypt: github.com/veracrypt/VeraCrypt/blob/… Granted, one mouse movement there is 1 bit of entropy. \$\endgroup\$ Commented Feb 1, 2017 at 9:44
  • \$\begingroup\$ @Gala I doubt that this is their only source of entropy (GH isn't so good at following references...). Additionally they cast the long values to byte[], which gets rid of the 256x256 limitations mentioned in my answer since they do not truncate data. Lastly they are quite probably not using the random bytes the way you are (namely storing them into a stack and just taking the bytes back again directly) \$\endgroup\$
    – Vogel612
    Commented Feb 1, 2017 at 10:11
  • \$\begingroup\$ Any patterns we see in randomness are just ... random. \$\endgroup\$
    – 5gon12eder
    Commented Feb 5, 2017 at 20:39
  • \$\begingroup\$ Vogel612: But isn't that tinfoil-hatting? I mean, how random is true random, and what are the odds of someone guessing my random data pool, generating the same keys as me, and decrypting my communication? \$\endgroup\$ Commented Feb 8, 2017 at 20:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.