CIS 700, Fall 2014
Homework 5: RSA Signature Forgery

Your next homework is protected using an authentication mechanism based on RSA digital signatures and SHA1 hashing. In order to access the homework, you must log into this web site using your Pennkey and a signature of your Pennkey that validates with the following RSA public key, which was generated using OpenSSL and has a 2048-bit modulus and public exponent 3:

-----BEGIN PUBLIC KEY-----
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA8ghRU0PHSrsL3zZ+GXnG
DqtCnwlssEmP+tZuOa5qSuVM0pTsCEKnwYIVVBdn7oKFurG++oNj0BA6YtJ5GrPt
P6H9FAjlZ4kX9dMCsOQDw27qO/ulrUn/WuRO8W6sVy/OhSWmzrfRfY3KiKlTGtYa
ug+Y81WNgXAyvd+15SCnbqkaP90D3HC8B9M7XUOhL1Bk1Ukjxa1orzJT2tkc9wYp
umAOzSdKH63fVssFT1nx8saMw1cGaSzYUpxmcNCIh+OF13R/nvsjYA27gMXfX/n3
3prsZCH+7UAGpdndWD/D/XlGg586vOviLeg6pjrD6SmWnRtFeQKdzr57H6Ta+NaY
CQIBAw==
-----END PUBLIC KEY-----

Valid signatures can be generated as follows using the sign() function, which takes in an RSA private key:

#!/usr/bin/python

import re
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA

signature_header = '-----BEGIN PRETTY BAD SIGNATURE-----\n'
signature_footer = '-----END PRETTY BAD SIGNATURE-----\n'

def sign(keyfile,message):
    key = RSA.importKey(open(keyfile).read())
    h = SHA.new(message)
    return signature_header + PKCS1_v1_5.new(key).sign(h).encode('base64') + signature_footer

Fortunately for you, I wrote my own signature verification code, which takes some parsing shortcuts with the PKCS padding.

# Verify that signature^e mod N has format
# 0x0001ffffff... fff ASN.1 SHA(message)
def verify(signature,keyfile,message):
    key = RSA.importKey(open(keyfile).read())
    data = re.search(signature_header+"(.*)"+signature_footer,signature,flags=re.DOTALL).group(1).decode('base64')

    h = SHA.new(message).digest().encode('hex')
    asn1_magic = "003021300906052b0e03021a05000414"

    s = int(data.encode('hex'),16)
    m = "%0512x"%pow(s,key.e,key.n)
    return re.match('0001f*'+asn1_magic+h,m)

In this mailing list posting Hal Finney outlines Bleichenbacher's attack that will generate a forged signature that validates against the above code.

For testing purposes, there is a non-functional account which uses the login test and this test signature:

-----BEGIN PRETTY BAD SIGNATURE-----
Snvh+XoRoL3RUkoPrSlEm2zYBMnYx7OwGn8+HQXAnyL/iZ8zx9pbNWa6ncBijDuRLTo/KS1Kx6ce
1pyGSUF7BRoBjCLOOzzmQ3N8/UBhYx06OZdxmLGEiuw/0B8WQCpKblsjoyiMm2upTgRwIehZAlhw
A0ELIjdswNmx8/7AO3Eiav1ZLMqI7HKiKmG0YnvgidG/9vQ+EcuENBdejFOrg+PevPCSB/rzz8zO
oTKuaZz3isG2+jpc3NHnO1FYi7wQvh3jGTn5i6eQXhTwDWWf3Xf8R2Puktd2niAjjjGTBNXgakoH
9Sm97iXAj/5wsq0wJzaRvSctIt11MKo0h3v0LQ==
-----END PRETTY BAD SIGNATURE-----

You may use any programming language you like. Please submit your code and a short description of how you solved the problem along with a PDF of your LaTeXed solutions to the other problems to Canvas before class on November 10. You may discuss this assignment in small groups with classmates, but please code and write up your solutions yourself. Please credit any collaborators you discussed with and any references you used.

For reference, the PKCS#1v1.5 RFC is here.

This homework inspired by this recent Mozilla security advisory.