Monday, March 28, 2011

Verifying the Comodo Hacker's key

In order to prove his identity, the person claiming to have hacked Comodo published the private key of his forged certificates. I've verified that they key is valid. This post describes how.

Note that even the "Certificate Authority" who signs a key does not know the  private key. When somebody requests a certificate, they only send the "hash" to the certificate authority. Therefore, nobody, not even Comodo, should know the private key. There are ways the private key may have been lost. For example, another hacker may have broken in, or it may have been given to a friend, or it may have been left behind on a system. But, beyond a reasonable doubt, this proves the identify of the hacker.

Verification is simple: we just encrypt something with the "public" key, and then decrypt it with the "private" key, then see if things match.

Step #1: download public certificate

To get the public key, I downloaded the forged certificates from https://bugzilla.mozilla.org/attachment.cgi?id=519863. This is in the bug tracking system for Firefox. They shipped an update to make these keys invalid. I saved this in a file named "addons.mozilla.org.cer".

Step #2: download private key from hacker

To get the hacker's private key, I went to his post at http://pastebin.com/X8znzPWH, copied the key, and pasted into a file I called "private.pem". I've also included the private key below because it appears the ComodoHacker has removed it from his pastebin post.

Step #3: extract public key

A certificate contains a lot of information, but all I wanted was the public key. Therefore, I ran the command:
openssl x509 -noout -inform DER -in addons.mozilla.org.cer -pubkey > public.pem
This uses the "OpenSSL" tool, the same code used in most web servers for doing SSL. I tell it I'm working with an X.509 certificate, and that the certificate is encoded as ASN.1 DER (Distinguished Encoding Rules). I tell it I want to extract the public-key. I save it to the file public.pem.

Step #4: create test file

I then create a file called "verify.txt" whose contents are simply "verify".
echo "verify" >verify.txt

Step #5: encrypt test file with public key

I then encrypt the file from the last step:
openssl rsautl -encrypt -inkey public.pem -pubin -in verify.txt -out encrypted
Again, I'm using the OpenSSL tool. This time, I'm using the RSA crypto algorithm. (Note: the RSA algorithm has essentially nothing to do with RSA the company). I tell it I'm going to encrypt the input file using the public key in the key file. I tell it to produce a file named "encrypted".

Step #6: decrypt test file with private key

I then decrypt that file with the private key. Remember: anything encrypted with the public key can only be decrypted with the matching private key.
openssl rsautl -decrypt -inkey private.pem -in encrypted -out decrypted.txt
Again, I'm using the RSA feature of OpenSSL. This time, the encrypted file from the last step becomes the input. The output is written to the file "decrypted.txt".

Step #7: verify test files match

Lastly, I dump the contents of "decrypted.txt" and see that it matches the original file with the contents of "verify".


I created a snapshot of VMware as I did this. In this snapshot, you can see all the steps that I describe above. Click on the image in order to get the big version (the full image won't fit within the space of this blog).



Why -modulus is inadequate


As many people pointed out, I could've used the "-modulus" option for OpenSSL to see if the two keys are equal. That's because the "modulus" (the product of the two primes) makes up both the public and private keys. An example:
openssl rsa -in private.pem -noout -modulus
openssl x509 -in addons.mozilla.org.cer -inform DER -noout -modulus

This doesn't actually work (I prove it with a fake private key below). All the OpenSSL tool does at this point is extract the "modulus" field from the files -- it doesn't verify that it's correct. I could easily create a "private.pem" file that contains the correct modulus for a public-key -- but which can't be used to properly encrypt anything encrypted by that public-key.

In other words, using -modulus to verify if a private key matches a public key assumes that nobody is trying to tamper with the key. It's like the difference between a "checksum" which only detects accidental corruption vs. a "hash" that detects intentional corruption.

You would need additional steps, like the following that checks the validity of a private key:
openssl rsa -in private.pem -noout -check

Then there is the problem of making sure that the two modulus are the same. You can't visually inspect them -- they are too big. As a hacker, I could make sure that the first few bytes and last few bytes are the same, and it would trick most people. Therefore, If have to use "diff" or "uniq", or hash them, to make sure they are the same.

This would end up taking MORE steps than my original method.

Then I'd feel obligated to explain the entire RSA algorithm, what precisely the public and private keys contain, and why the modulus (the product of the two primes) is the same for both.

After all this, there's still a chance I made a mistake. The fact that many people assume comparing the modulus was adequate demonstrates how easy it is for even experts to make mistakes.

I chose the method that I felt would have the smallest chance of me making a mistake, and the biggest chance of being understood by readers. I think it's an excellent choice.


In order to prove this, I've created a fake private certificate that I put in a file called "fakeprivate.pem. It contains the modulus (and public exponent) from the certificate, but all the other fields have been filled with 0xFF (which appears as the string of //// when BASE64 encoded). I include the file here so that you can test this yourself:
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAq8ZtNvMVc3iDc850hdWu7LLw4CQfE4O4IKy7mv6Iu6uhHQsf
RQCqSbc1Nwxq70dMudG+41cSBI2Sx7bsAby22seBOCCtcoXmDvyBbAetaHY4xUTX
zMZKxZc+ZPRR5vB+suxW9yWCTUmYyxaY3SPxiZHRF5dAmSbW4qIrXt+9ifIbGlMt
zFBBetA9KgxVcBQB6VhJEHoLk4KL4R7tOoAQgs6WijTwzNfTubRQh1VUCbidQihV
AOWMNVS/3SWRRrcN5V2DqOWL+4TkPK522sRDK1t0C/i+XWjxeFu1zn3xXZlA2sru
OIFQvpihbLgkrfOvjA/XESgshBhMfbXZjzC1GwIDAQABAoIBAQD/////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
//8P////AoGBAP//////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////AoGBAP//
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
//////////////////////////////////8P////AoGAAP//////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
//////////////////////8CgYAA////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
/////wKBgA//////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////
-----END RSA PRIVATE KEY-----
I then re-run my test, and it shows decryption errors, thus proving it's a fake private key attempting to match the public key. But when, I run your -modulus test, no errors are generated, and the moduluses (sic) appear to match.

Your method can be improved by doing the "-check". It fails with the error "n does not equal p q", which is the check you are looking for. But as I said, I did't want to fix your method of checking the modulus, I wanted a method that I felt the average person reading the post could read and feel comfortable that yes, the key has been validated.

Here is a screenshot of the tests I describe above (click on the image to get a larger picture):

By the way, there are other, arguably easier, ways the key, but I didn't want easy, I wanted straight-forward, mistake-free, and verifiable.


private.pem

The private key is now gone from pastebin, so I'm including it below. Just copy/paste this block into a text file to use it.

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAq8ZtNvMVc3iDc850hdWu7LLw4CQfE4O4IKy7mv6Iu6uhHQsf
RQCqSbc1Nwxq70dMudG+41cSBI2Sx7bsAby22seBOCCtcoXmDvyBbAetaHY4xUTX
zMZKxZc+ZPRR5vB+suxW9yWCTUmYyxaY3SPxiZHRF5dAmSbW4qIrXt+9ifIbGlMt
zFBBetA9KgxVcBQB6VhJEHoLk4KL4R7tOoAQgs6WijTwzNfTubRQh1VUCbidQihV
AOWMNVS/3SWRRrcN5V2DqOWL+4TkPK522sRDK1t0C/i+XWjxeFu1zn3xXZlA2sru
OIFQvpihbLgkrfOvjA/XESgshBhMfbXZjzC1GwIDAQABAoIBAQCJoijaEXWLmvFA
thiZL7jEATCNd4PK4AyFacG8E9w8+uzR15qLcFgBTqF95R49cNSiQtP/VkGikkkc
ao25aprcu2PnNA+lpnHKajnM9G3WOHuOXHXIps08es3MmBKTxvjNph6cUlqQULrz
Zry+29DpmIN/snpY/EzLNIMptn4o6xnsjAIgJDpQfFKQztxdmZU6S6eVVn0mJ5cx
q+8TTjStaMbh+Yy73s+rcaCXzL7yqWDb1l5oQJ/DMYNfufY6lcLgZUMwFxYKjCFN
ScAPCiXFUKTzY3Hy1Z4tLndFxipyEPywDep1TB2nMb+F3OOXUs3z+kKVjGFaGnLZ
591n3x3hAoGBAOOgsb4QybjHh9+CxhUkfsqcztGGdaiI3U5R1qefXL7R47qCWfGc
FKdoJh3JwJzHEDX68ZmHz9dPhSXw6YrlLblCi6U/3g7BOMme5KRZKBTjHFo7O9II
B0laE5ISRH4OccsOC3XUf9XBkm8szzEBj95DgzB0QydPL4jp7NY0h0QrAoGBAMEv
jEFkr/JCRe2RWUSx/a1WT/DHnVLMnDb/FryN2M1fAerpMYNUc2rnndjp2cYbsGLs
cSF6Xecm3mUGqn8Y5r8QqBwxCp5OunCFCXEJvkiU3NSs8oskCsB8QJ6vk3qmauUK
jClX91heSCigwhC2t+1txnF290m/y0T46EfqOSrRAoGAUlyVk4D9jEdeCWiHBaVj
3ynnx3ZQYj/LW4hPE+2coErPjG+X3c0sx/nuOL8EW3XHjtCS1IuIj45tTfIifqg3
6B2E67D1Rv9w7br5XeIIl64pVxixp2hSQp8+D49eiwHs+JzHVsYhzxUwR9u9yCyZ
gsGI2WJn3fRP7ck+ca8l9msCgYB4B2Hec3+6RqEKBSfwvaI+44TRtkSyYDyjEwT+
bCeLGn+ng/Hmhj8b6gKx9kH/i86g+AUmZtAXQZgmLukaBM/BYMkCkxnk2EeQh6gh
Goumrw8x+K7N8rvXcpv3vGEmcGW0H0SMn4In3pR44cER/2Tx2SXV87Obl9Xk6b3w
iL+yMQKBgFjXcmiBW8lw3l2CaVckd/1SzrT80AfRpMT9vafurxe+iAhl9SDAdoZe
3RlshoItDQLW1ROlkLhM7Pdq/XZvLRm128hiIGKTDBnxtfN8TKAg+V7V+/TTfdqv
8jq7epvZsq5vjOC1FZh2gOhf50QwpqDJktjdyka1sPiBKQSoxfbZ
-----END RSA PRIVATE KEY-----


You are free to use everything in this post for whatever purpose, as long as you provide a link back to this post. If reproduced with paper, print the full URL.

15 comments:

Unknown said...

(Note: the RSA algorithm has essentially nothing to do with RSA the company).

Well, except for both the algorithm and the company being named after the same people, and the fact that the company was created to monetize their inventions. I think that's a little more than "essentially nothing".

Robert Graham said...

It's essentially nothing in this context.

People have gotten confused by this recently with the RSA SecurID hack and the Comodo guy hacking RSA keys.

Corey said...

Great read and step by step instruction. I'll plan on trying for fun on my Ubuntu box.

sep332 said...

Can't you just use the -modulus flag? I think it would simplify the verification a lot.

Anonymous said...

I've been under the impression you can run these two commands (one on the cert, one on the private key) and if the Modulus value matches, then the private and public keys are a pair:

openssl rsa -in addons.key -noout -modulus

openssl x509 -in addons.cer -inform DER -noout -modulus

(Feel free to correct me if that doesn't always work)

Robert Graham said...

No, simply doing -modulus is insufficient for a couple of reasons.

BatteRy said...

answer to the hacker!:

http://pastebin.com/R8zBtL9a

p.s.: i didn't write it
http://www.balatarin.com/permlink/2011/3/28/2431744#c-4274383

BatteRy said...

here the blog author said absolutely what i said in a Persian forum:

http://www.adminsehow.com/2011/03/a-response-to-comodohacker/

really, if you don't have any relation with Iran's government and so these things you mentioned are only useful when you have access to the internet infrastructure of Iran; otherwise there's really no use for what you done and what you have!

you lied and i told you everybody, he's a basidji working for government and he is a freak...!

for you to know: in Iran there's only ONE company provides the whole internet connection of the country! "Ertebatat Sayyar" is the name of this company. this damnet *** government doesn't let anybody else to develop internet infrastructure in this country for 3 reasons:
1- they want a full access to all the data transfers of all the people
2- they want to apply a centralized filtering and censoring system on all the country's network
3- they sell the bandwidth so damned expensive to the ISPs so they can make so much money from internet! they have all of the oil in their hands but they don't lose the money they canmake from the internet!

in Iran, one of *** Mahmud Ahmadinejad's first laws after wining the election in 2004 was limiting home internet access to maximum of 128Kbps...! you can't even imagine that most of the people don't even know there's faster internet connections than a dial-up connection and faster? how much faster? more than 128K bits per second is FORBIDDEN and this ComodoHacker really likes this *** government!

in Iran if you use satellite you will get fined! if you use satellite internet connection and only send a single piece of waves from your dish and they will find you and put you in jail...!

in Iran 90% of useful sites are already filtered and everytime there's something going on in the streets (those "a few people of green movement" as the hacker says) they're getting so much damned worried even sometimes they cut down all of the country's internet and connections to out of the country! many of the ports are blocked and now none of the vpns work (there's always another way!) and even in the past days Opera Mini servers have been blocked because they work like proxies!

ComodoHacker really likes this governemnt which fills his/their pockets with people's oil money!

and another proof that he works for the government: last week you remember the news about what he/they've done, after they saw their work is out in the news and it's all gonna blow up they did their plan as fast as they could because there were no more time and the people were updating their browser versions; for a few days after that news many of the iranians whoever installed updated browsers faced so many ca warnings on mail.google.com and mail.yahoo.com

the only purpose for them in life is to harm more people everday!

Sam Bowne said...

Thanks for the step-by-step! I will send my students here to learn how it works :)

--Sam Bowne

R/S said...

Robert: What two reasons please?

Robert Graham said...

I just updated my post to explain why I think -modulus is inadequate.

Rolf Rander Næss said...

Why did he post the private key? It would be far more elegant and convincing if he had signed his messages with the private key. (Do we really know that the person posting the messages is the same as the person posting the key? At this point, anyone can claim to be the cracker, as he gave away his only proof.)

Robert Graham said...

Rolf: the answer is because several people (including me) suggested to him as the "final" proof. You are correct, we should've suggested your strategy.

However, he's got the private keys of the other certificates to continue to prove his identity.

QaSaR said...

Again R.Graham excelent post, perfect build, and i agree with your verify method, you have a blog that reads a lot of ppl, most of them would have not understand a complex xplain of private key method, and properties.
Thx for this posts (all arround comodo's hack). Superb

Q.

Unknown said...

Excellent post.