
Android RNG Weakness Renders Bitcoin Wallets Insecure - VMG
http://bitcoin.org/en/alert/2013-08-11-android
======
tptacek
Iä! Digital Signature Algorithm! The Black Goat of the Woods with a Thousand
Crypto Bugs!

I don't know the Bitcoin software involved at all, but I can sketch out an
attack that might shed some light on it, and, more importantly, instill an
appropriate fear of DSA into you:

To generate a DSA key, you come up with primes p and q and a generator g,
which process is a paralytic non-Euclidian brain injury I will not attempt to
describe. Then you do like Diffie Hellman: generate a random private key x and
from it a public value y = g^x % p. The pubkey that validates signatures is
the tuple (p, q, g, y).

To sign, you generate a random k value, which must never be reused, Iä! Iä!
never, and:

    
    
        r = g^k % p % q
        s = k^-1 (H(m) + x•r) % q
    

The signature is (r, s).

If ever you should fail to heed these words and generate two signatures with
the same k value, Iä Cthulhu Ftaghn! then simple high school algebra can be
used to beat DSA. The attacker doesn't even need to know what the k was, and
the attack is so fast you can just try it to see if k was repeated (I skipped
the algebra and just dumped the formulas for the attack here):

    
    
            H(m1) - H(m2)
        k = -------------
               S1 - S2
    
        x = ((S1•k) – H(m1))• r^-1 % q
    

This bug (also in an ECDSA implementation) is what broke the Playstation 3,
too.

You see that comment on the Bitcoin thread about the repeated r-values; a
repeated r-value (r as in the r parameter of a DSA signature) just tells you
that someone repeated a k. Iä! Iä!

~~~
fixxer
On a side note, what are the current stats for the Matasano crypto challenge?
How many have finished all 6?

~~~
rwg
Whenever I see tptacek tweet the current stats, I try to update this
spreadsheet:

[https://docs.google.com/spreadsheet/ccc?key=0AscYGzcM4zJNdHR...](https://docs.google.com/spreadsheet/ccc?key=0AscYGzcM4zJNdHRmVEN2SDlpbGxXT2s5WU1VYmFybFE#gid=0)

I've probably missed a few tweets and typo'd a few numbers along the way, but
it should be mostly accurate. Note the tabs (at bottom left) for a derived
speadsheet (percent of participants at each level) and a chart.

~~~
tptacek
For those watching from the stands, 'rwg also sent us a spreadsheet that does
AES. Entirely in cell formulas. He also sent us a Postscript file that
appeared to be a visualization of AES state but was in fact a pure-Postscript
implementation of AES that rendered itself into the Postscript document.

~~~
rwg
To be fair, I've only tweeted screenshots of the AES spreadsheet -- you'll be
getting the actual .xlsx file with my set 6 answers. AES128.applescript is
waiting in the responses@ and cryptopals@ mailboxes right now, along with my
set 5 answers.

I don't know what I'll do for set 7 yet. Maybe Excel implementations of the
SHA-3 finalists...

------
acqq
Seems that some invocations of SecureRandom were able to always get the same
result.

[http://blog.kchandrahasa.com/blog/2013/08/09/android-4-dot-2...](http://blog.kchandrahasa.com/blog/2013/08/09/android-4-dot-2-and-
javax-dot-crypto-dot-badpaddingexception-pad-block-corrupted/)

However I've read somewhere that now apparently even Android 4.2 is affected
which would mean there's something more? Whoever knows more, please write more
technical details.

~~~
tjohns
To be specific, since I spent a lot of time on that bug...

Older versions of Android's SecureRandom could return the same value if (a)
you were manually seeding SecureRandom and (b) no prior crypto operations were
performed on that SecureRandom instance before seeding,

There was some (very) bad advice circulating on blogs which advised using this
technique to generate local encryption keys from a seed, in order to obfuscate
the key.

This was fixed in Android 4.2 when we switched from BouncyCastle to OpenSSL as
the underlying crypto provider. I don't know why you'd still be seeing this on
Android 4.2, but you shouldn't be doing this anyway. SecureRandom is seeded by
the system. Manually seeding it is a bad idea. (And trying to force
deterministic output from is a _very_ bad idea.)

There's a blog post I wrote which goes into a bit more detail:
[http://android-developers.blogspot.com/2013/02/using-
cryptog...](http://android-developers.blogspot.com/2013/02/using-cryptography-
to-store-credentials.html)

The linked article is a bit light on details, so I don't know if this is what
they were doing or not. I doubt it though, since that would have meant they
were seeding SR with the same value, and I'd like to believe the Bitcoin devs
wouldn't make that mistake.

~~~
andrewcooke
the linked article was using deterministic output from an explicitly seeded
PRNG as a key. it broke with openSSL which uses setSeed only to augment, not
replace, state (as you know, just being complete).

so i don't think the parent link explains the current issue.

------
filipmaertens
At blog post [https://cryptocow.com/?p=201](https://cryptocow.com/?p=201)
we've been experimenting with using sensors to upgrade PRNG's, and we frankly
can't understand why this isn't been used natively in Android RNG
implementations... It's trivial, easy and tremendously increases the RNG
quality.

~~~
tptacek
Because a sensor provides an entropy source, not a whole CSPRNG. Most modern
CSPRNGs have interfaces to feed entropy into the system, but CSPRNG designs do
more than simply route entropy from one place to another.

This is a really common misconception people seem to have about cryptographic
random number generation, and a topic Ferguson and Schneier do an extremely
good job breaking down in _Cryptography Engineering_.

------
kllrnohj
Android's SecureRandom uses BouncyCastle prior to 4.2 and OpenSSL in 4.2+ (
[http://android-
developers.blogspot.com.au/2013/02/security-e...](http://android-
developers.blogspot.com.au/2013/02/security-enhancements-in-jelly-bean.html) )

It'd be interesting to know what the bug is and if that bug affects Bouncy
Castle and/or OpenSSL as well, or if Google screwed up the glue code somehow

~~~
sirk390
This is the paper referenced in the bitcointalk thread:
[http://www.scribd.com/doc/131955288/Randomly-Failed-The-
Stat...](http://www.scribd.com/doc/131955288/Randomly-Failed-The-State-of-
Randomness-in-Current-Java-Implementations). See section 5.4 for Bouncy
Castle: Weaknesses/Quality of Entropy Collectors.

------
VMG
discussion on bitcointalk.org:
[https://bitcointalk.org/index.php?topic=271486.0](https://bitcointalk.org/index.php?topic=271486.0)

blogpost about weakness in java.security.SecureRandom:
[http://armoredbarista.blogspot.com.au/2013/03/randomly-
faile...](http://armoredbarista.blogspot.com.au/2013/03/randomly-failed-
weaknesses-in-java.html)

~~~
Buge
That second link doesn't seem to be the current problem. The current problem
is that the same random number is being returned more than once.

~~~
VMG
On the other hand, the author of the Bitcoin Wallet Android app thinks it's a
SecureRandom problem: [https://code.google.com/p/bitcoin-
wallet/source/detail?name=...](https://code.google.com/p/bitcoin-
wallet/source/detail?name=bitcoinj-0.10&r=04d2044880d88107ee4a939a516fb4be4cedeaf9#)

~~~
lwf
That commit series doesn't actually appear to __use __the new class, besides
initialising it.

Simply initialising it is insufficient, because you need to call addProvider()
(cf.
[https://developer.android.com/reference/java/security/Securi...](https://developer.android.com/reference/java/security/Security.html)
) to actually have any effect.

~~~
gojomo
The LinuxSecureRandom class has a 'static initializer' block, which will run
as soon as the class is loaded. (That is, triggered by the reference and
initialization call, but just before.)

It purports to install LinuxSecureRandom as a new systemwide default
(LinuxSecureRandom, lines 56-57).

------
lcedp
Does it concerns only Bitcoin wallets? What about other encryption under
Android - like files, etc?

~~~
tptacek
This is a Bitcoin software implementation bug, and an illustration of why you
should use your OS's CSPRNG (here, /dev/random) to the exclusion of any other
RNG.

~~~
gwillen
As far as I know that is NOT correct. The wallets in question were all -- to
my knowledge -- using the Android platform-provided Java SecureRandom
generator.

~~~
tptacek
If the story here is that Java SecureRandom on Android is bad enough to break
DSA, the headline on this story is wrong; it should be something more like
"Android Doomed".

Can you provide a link to something corroborating this?

~~~
gwillen
I have done a bit of source diving in response to your question, and the
answer is that all I can provide is the bitcoiners' announcement:

[https://bitcointalk.org/index.php?topic=271831.0](https://bitcointalk.org/index.php?topic=271831.0)

They claim the problem lies with 'a component of Android'. One of them told me
that the solution was to switch from using SecureRandom to reading
/dev/urandom directly. The actual source changes appear not to be public, and
he wouldn't tell me details about the issue.

I tried to find the usages of SecureRandom in a couple of the apps that are
supposed to be affected, but a cursory search didn't turn up much. I suspect
it's inside some library that I don't know to look inside. The question, I
guess, is whether all the affected apps share the same library or not -- I
don't _think_ so, but if they do it would dramatically reduce my confidence
that the issue lies with the Android platform, as claimed.

~~~
glurgh
That's the lib, if you're bored enough to keep diving

[https://code.google.com/p/bitcoinj/](https://code.google.com/p/bitcoinj/)

~~~
gwillen
OK, I dove a little more. The actual signing happens in
org.spongycastle.crypto.signers.ECDSASigner . I haven't dug into _that_ yet.

But one thing I'm wondering is: would any setSeed on any SecureRandom instance
cause a potential problem? Or just on the same instance being used for
signing? In other words, do I only need to check that spongycastle -- which I
presume is a fork of bouncycastle -- handles things reasonably? Or could any
other messing about with SecureRandom mess it up?

~~~
benmmurphy
the only other thing i see is the openssl securerandom code doesn't properly
check the return value. it is possible for RAND_bytes to fail and for the
securerandom code to not throw an exception. i think this is quite unlikely to
happen. so basically:

1) reading from /dev/urandom takes more than 10ms causing an entropy error

2) a malloc fails causing the error to be saved to the fallback ERR_STATE
instead of the thread local ERR_STATE

3) java sees failing code and tries to read the last error but now malloc
succeeds so it reads it from its local thread ERR_STATE which succeeds or some
other thread has clobbered the fallback ERR_STATE

4) java doesn't throw an exception because it sees no error

the other possibility is the openssl random state is shared between processes
due to forking. i hear there is a process called the zygote that warms up the
vm and forks to create apps. if it initialises openssl then it is possible
child processes could get the same random state.

------
mikeash
Looks like a terrifyingly buggy SecureRandom implementation that results in
only 31 bits of entropy when seeding:

[http://armoredbarista.blogspot.com.au/2013/03/randomly-
faile...](http://armoredbarista.blogspot.com.au/2013/03/randomly-failed-
weaknesses-in-java.html)

~~~
tptacek
As I understand it, Android doesn't use Harmony's CSPRNG. But maybe it did in
an earlier version? Maybe that's the problem?

------
swayvil
Why don't we have a real rng in our computing devices? It appears to be a
trivial bit of electronickry. I'm talking about one of those little quantum
event listener thingies.

[http://en.wikipedia.org/wiki/Hardware_random_number_generato...](http://en.wikipedia.org/wiki/Hardware_random_number_generator)

------
mydpy
Can anyone reference me to an article that explores a technical analysis of
how their random number generator was exploited? Did it not have full coverage
(read: RANDU style error) or otherwise?

[http://www.pnas.org/content/61/1/25.full.pdf+html](http://www.pnas.org/content/61/1/25.full.pdf+html)

~~~
mydpy
Actually, I found it here. Pretty interesting issue, I recommend the read.
I'll summarize the paper here:

Java implementations primarily used on lightweight mobile platforms have a
method called SecureRandom which generates pseudo random numbers for
cryptographic operations. The integrated seed generator on some platforms
provides a systematic means of determining the seed value and predicting
seemingly secure outputs.

[http://www.scribd.com/doc/131955288/Randomly-Failed-The-
Stat...](http://www.scribd.com/doc/131955288/Randomly-Failed-The-State-of-
Randomness-in-Current-Java-Implementations)

~~~
glurgh
Yes but that's not the problem being reported.

------
0x0
Could this affect stuff like ssh key generation or HTTPS traffic on Android,
as well?

------
oakwhiz
Would it be possible to design Android Bitcoin wallets to consume their
entropy from a file on your SD card? You could just periodically refill the
entropy from another device that you trust.

------
DanBC
I always wonder if some people are watching announcements to try to grab
unsecured bitcoins before other people implement fixes?

~~~
runeks
The reason it was discovered in the first place was that coins were suddenly
disappearing from wallets. So it's very likely that someone has already set up
a bot that scans new transactions from the same address for repeating _r_
values.

------
dobbsbob
I use the feudal security of blockchain.info wallets w/2FA on android since
phones tend to get lost, stolen or fubard

------
LAMike
this could be a big blow to Bitcoin adoption... Is this a part of Android that
can't be touched by anyone but Gooogle? Or is it a piece of software that can
be improved upon by open source devs?

~~~
javert
I don't think it's a very big deal.

For the most part, people who use bitcoin now are still very early adopters
and are techies.

Also, IMHO, it would be idiotic to have significant bitcoin value stored on an
Android phone, and very few people (if anyone) would do that.

~~~
Buge
People are saying it's a problem with Android's SecureRandom implementation.
That would be a pretty big problem if it returns repeated random numbers.

But it seems strange that such a large obvious problem would make it into
Android. The other explanation is that Android bitcoin developers are all
implementing it incorrectly and either don't realize it or are trying to push
the blame somewhere else.

~~~
jadeddrag
It is very likely that the bitcoin community would be the first to stumble
onto a crypto bug in SecureRandom. Google should thank that community for
their discovery.

~~~
makomk
Extremely likely, in this case. It looks like the way it was discovered is
that various people have set up bots to take Bitcoins from transactions with
repeated r values, and they took coins from Android Bitcoin clients that on
paper were doing everything right.

