/rsa-bleichenbacher-signature

Demonstrates RSA PKCS1v1.5 signature vulnerability, known as BB'06, using Python 3

Primary LanguagePythonGNU General Public License v3.0GPL-3.0

Bleichenbacher BB'06 RSA Signature Tool

Generates a valid RSA signature without a key

Intro

This repository contains a Python 3 implementation of the Bleichenbacher signature forgery attack, described in 2006 (BB'06 attack). This is a fork from https://github.com/hoeg/BleichenbacherSignatureForger. Having seen this variant of the attack multiple times during the last year, both in CTFs and in real implementations, showed the need for a more general solution than the hacky frankenstein scripts Peter Hoeg Steffensen has lying around. Maxim Masiutin has updated this tool to solve a challenge published in 2020 on an Information Security learning platform to generate a signature for a key of 2736 bits (e=3) without having the private key. Public modulus (N) is also not needed for the BB'06 signature generation.

Attack

PKCS #1 v1.5 is defined in https://www.ietf.org/rfc/rfc3447.txt. If the verification algorithm is trying to parse the result of the public key operation instea>

Two variants of the attack are supported:

  1. The length is not checked, and the padding is on the form 0001FF...FF00 | DigestInfo | garbage
  2. The filler (PS) is not checked - 0001FF...FF | non-zero-garbage | 00 | DigestInfo

PS is defined in RFC-3447 as an octet string "consisting of k - mLen - 2hLen - 2 zero octets".

More info on variant #1 can be found at: https://www.ietf.org/mail-archive/web/openpgp/current/msg00999.html

Credit for variant #2 goes to Filippo Valsorda, who published the original version of the code in 2016 (https://blog.filippo.io/bleichenbacher-06-signature-for

Since a signature in the BB'06 attack never wraps past modulus, we do not need a modulus, i.e., a full public key, to verify a signature. We only need the exponent part of the public key. The BB'06 signatures are valid for any public key, provided that the exponent matches (usually 3).

Usage

$ python Forge.py --help

usage: Forge.py [-h] [-k KEYSIZE] [-ha {MD5,SHA-1,SHA-256,SHA-384,SHA-512}] [-va {1,2}] [-of {decimal,hex,base64,raw}] [-m MESSAGE] [-e PUBLIC_EXPONENT] [-F FFCOUNT] [-q]

Bleichenbacher Signature Forger. Version 2.2. This program demonstrates the vulnerability of the RSA PKCS1v1.5 and the attack when the public exponent is small (e.g., 3) and the verification algorithm is not implemented correctly.

optional arguments:
  -h, --help            show this help message and exit
  -k KEYSIZE, --keysize KEYSIZE
  -ha {MD5,SHA-1,SHA-256,SHA-384,SHA-512}, --hashalg {MD5,SHA-1,SHA-256,SHA-384,SHA-512}
  -va {1,2}, --variant {1,2}
                        1 - 00 01 FF ... 00 ASN.1 HASH GarbageWithZeros; 2 - 00 01 FF NonzeroGarbage 00 ASN.1 HASH
  -of {decimal,hex,base64,raw}, --outputformat {decimal,hex,base64,raw}
  -m MESSAGE, --message MESSAGE
  -e PUBLIC_EXPONENT, --public-exponent PUBLIC_EXPONENT
  -F FFCOUNT, --ffcount FFCOUNT
  -q, --quiet

Example

./Forge.py --keysize 2048 -ha SHA-256 --variant 2 --message "Test"

History

  • 1.0 (July 2nd, 2017)

    • Initial version
  • 2.0 (May 5th, 2021)

    • Ported to Python 3
    • Removed strings in favor of byte objects
    • Added support for output formats
    • Added support for the public exponent command line parameter
    • Dynamic precision adjustment for larger numbers
    • The program exits with an appropriate message if it cannot generate a signature rather than spinning in an endless loop
    • The option to specify the number of FF's
    • The "quiet" option
    • All error messages are printed to stderr
    • Appropriate exit codes returned
    • Added module docstrings
    • Proper "import" declarations that list only classes/functions which are actually imported
    • Added support for the SHA-224 hash
    • Implemented automatic unit tests
  • 2.2 (June 26th, 2024)

    • Fixed typos in the readme and the messages given by the program
    • Renamed files for meaningful names
    • Renamed functions and methods for Python naming convention
    • Added an appropriate message if the program cannot generate a signature
    • Added primality test for public exponent
    • Normalized spaces and tabs, and the long lines
    • Updated the documentation (the file comments and the readme file)