0

I hope this question makes sense. But let's say I create a Certificate with MAKECERT.EXE like this:

makecert -r -sr LocalMachine -ss my -a sha256 -sky exchange -n "CN=Hello World"

Now let's say I run this on two different (Windows) machines. Statistically what are the chances the certificates on the two different machines will have the same Public Key?

If this question does not make sense, I'd appreciate an explanation as to why it doesn't.

Thanks.

Neil Weicher
  • 2,370
  • 6
  • 34
  • 56

1 Answers1

2
  • makecert defaults to a 1024-bit RSA key.
  • It defaults to a fixed e=65537.
  • A 1024-bit RSA key has two primes, each 512 bits long.
  • The Prime Number Theorem says that there are more than 2^511/ln(2^511) primes of that size, and if we subtract all the 511-and-smaller bit primes we're left with about 10^151.
  • So across two runs, the odds of the smaller of the two primes being the same is about 1 in 1e151.
  • Running that through the formula for the birthday problem we see that all the magic really happens around the 1e75 mark.
    • 1% chance of collision: 4.5e74
    • 10%: 1.5e75
    • 25%: 2.4e75
    • 50%: 3.7e75
    • 75%: 5.3e75
    • 99%: 9.6e75
  • All of that was for one of the two primes. If we factor in the other (and, without-loss-of-generality, assume that we always declare that p < q) then we get:
    • 5e150 * 1e151 ~= 5e301 different 1024-bit values of RSA n.
    • 1% collision chance after 1e150 runs.
    • 10% collision chance after 3e150
    • 25% collision chance after 5e150
    • 50% collision chance after 8e150
    • 75% collision chance after 1e151
    • 99% collision chance after 2e151

At 1 million keys per second (1e6) for all ~86000 seconds per day you get 8.6e10 keys per day. To have a "millionth of a percent" chance (1/1e8) of a collision you'll need over 1e136 days of computation. That's 3e133 years. The universe, currently, is believed to be 1.4e10 years old. So, you need about 2.3e123 universes to have even that high of a chance (give or take a couple universes).

BTW, my computer can only do ~100 1024-bit keys per core-second (right around 10ms per), so I'm assuming you have about 10,000 of them chugging away at this problem.

Unless we model in CSPRNG state collision and VM rollback (to cause CSPRNG state collision), the answer is: effectively impossible.

bartonjs
  • 30,352
  • 2
  • 71
  • 111
  • Thanks for the comprehensive analysis. Interestingly I did run the same command line twice on the same machine. I ended up with two certificates. They had different Serial Numbers and different Thumbprints. However they both had the same Public Key! Is that expected? – Neil Weicher Mar 07 '18 at 17:08
  • 1
    @NeilWeicher Did you use the `-sk` option? That loads (or creates and loads) a named key, so it would be the same key on the second run (on the same machine). – bartonjs Mar 07 '18 at 17:11
  • I put the command line in the question above. Not using the `-sk` option, but I am using the `-sky` option which appears to be different. When would there be a reason to create a named key? – Neil Weicher Mar 07 '18 at 17:29
  • @NeilWeicher Learn something new every day. If you don't specify `-pe` (exportable private key) then makecert has a default value for `-sk` of "JoeSoft", so you loaded the same key on the second run (if you do specify `-pe` and not `-sk` then it uses a UUID). No wonder makecert [is deprecated](https://msdn.microsoft.com/en-us/library/windows/desktop/aa386968(v=vs.85).aspx). (You'd use a named key, primarily, when it's an existing hardware key. Or you'd specify `-sk` when leaving off `-pe` to avoid using the "JoeSoft" key :)) – bartonjs Mar 07 '18 at 18:11
  • (Oh, and, for completeness: the cert store doesn't save a key with the cert, just the name of the key (see also: hardware keys); so the private key needs a name so that you can "use the cert" to decrypt/sign) – bartonjs Mar 07 '18 at 18:44