-
Notifications
You must be signed in to change notification settings - Fork 130
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
37 changed files
with
1,457 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# Crypto attacks | ||
Python implementations of cryptographic attacks and utilities. | ||
|
||
## Requirements | ||
* PyCryptodome | ||
* SageMath | ||
|
||
## Implementations | ||
### CBC | ||
* [x] [Bit flipping attack](cbc/bit_flipping.py) | ||
* [x] [IV recovery attack](cbc/iv_recovery.py) | ||
* [x] [Padding oracle attack](cbc/padding_oracle.py) | ||
|
||
### CBC + CBC-MAC | ||
* [x] [Key reuse attack (encrypt-and-MAC)](cbc_and_cbc_mac/eam_key_reuse.py) | ||
* [x] [Key reuse attack (encrypt-then-MAC)](cbc_and_cbc_mac/eam_key_reuse.py) | ||
* [x] [Key reuse attack (MAC-then-encrypt)](cbc_and_cbc_mac/eam_key_reuse.py) | ||
|
||
### CBC-MAC | ||
* [x] [Length extension attack](cbc_mac/length_extension.py) | ||
|
||
### CTR | ||
* [x] [CRIME attack](ctr/crime.py) | ||
|
||
### ECB | ||
* [x] [Plaintext recovery attack](ecb/plaintext_recovery.py) | ||
|
||
### ElGamal Encryption | ||
* [x] [Nonce reuse attack](elgamal_encryption/nonce_reuse.py) | ||
|
||
### ElgGamal Signature | ||
* [ ] Bleichenbacher's attack | ||
* [ ] Khadir's attack | ||
* [x] [Nonce reuse attack](elgamal_signature/nonce_reuse.py) | ||
|
||
### Factorization | ||
* [x] [Coppersmith factorization](factorization/coppersmith.py) | ||
* [x] [Fermat factorization](factorization/fermat.py) | ||
* [x] [Pollard's Rho factorization](factorization/pollard_rho.py) | ||
* [x] [ROCA](factorization/roca.py) [More information: Nemec M. et al., "The Return of Coppersmith’s Attack: Practical Factorization of Widely Used RSA Moduli"] | ||
* [x] [Twin primes factorization](factorization/twin_primes.py) | ||
|
||
### GCM | ||
* [x] [Forbidden attack](gcm/forbidden_attack.py) [More information: Joux A., "Authentication Failures in NIST version of GCM"] | ||
|
||
##### OFB | ||
* [x] [CRIME attack](ofb/crime.py) | ||
|
||
### Pseudoprimes | ||
* [x] [Generating Miller-Rabin pseudoprimes](pseudoprimes/miller_rabin.py) | ||
|
||
### RSA | ||
* [ ] Bleichenbacher's CCA attack | ||
* [x] [Bleichenbacher's signature forgery attack](rsa/bleichenbacher_signature_forgery.py) | ||
* [x] [Boneh-Durfee attack](rsa/boneh_durfee.py) [More information: Boneh D., Durfee G., "Cryptanalysis of RSA with Private Key d Less than N^0.292"] | ||
* [x] [Common modulus attack](rsa/common_modulus.py) | ||
* [x] [Common prime factor attack](rsa/common_prime_factor.py) | ||
* [x] [CRT fault attack](rsa/crt_fault_attack.py) | ||
* [x] [Extended Wiener's attack](rsa/extended_wiener_attack.py) [More information: Dujella A., "Continued fractions and RSA with small secret exponent"] | ||
* [x] [Hastad's broadcast attack](rsa/hastad_attack.py) | ||
* [x] [Low public exponent attack](rsa/low_exponent.py) | ||
* [ ] LSB oracle attack | ||
* [ ] Manger's attack | ||
* [x] [Partial key exposure attack for low public exponents](rsa/partial_key_exposure.py) [More information: Boneh D., Durfee G., Frankel Y., "An Attack on RSA Given a Small Fraction of the Private Key Bits"] | ||
* [x] [Related message attack](rsa/related_message.py) | ||
* [x] [Stereotyped message attack](rsa/stereotyped_message.py) | ||
* [x] [Wiener's attack](rsa/wiener_attack.py) | ||
|
||
### Shamir's Secret Sharing | ||
* [x] [Deterministic coefficients](shamir_secret_sharing/deterministic_coefficients.py) | ||
* [x] [Share forgery](shamir_secret_sharing/share_forgery.py) | ||
|
||
### Small roots | ||
* [x] [Boneh-Durfee method](small_roots/boneh_durfee.py) [More information: Boneh D., Durfee G., "Cryptanalysis of RSA with Private Key d Less than N^0.292"] | ||
* [x] [Coron method](small_roots/coron.py) [More information: Coron J., "Finding Small Roots of Bivariate Integer Polynomial Equations: a Direct Approach"] | ||
* [x] [Howgrave-Graham method](small_roots/howgrave_graham.py) [More information: May A., "New RSA Vulnerabilities Using Lattice Reduction Methods"] | ||
* [ ] Jochemsz-May method [More information: Jochemsz E., May A., "A Strategy for Finding Roots of Multivariate Polynomials with New Applications in Attacking RSA Variants"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
def attack(iv, c, pos, p, p_): | ||
""" | ||
Replaces the original plaintext with a new plaintext at a position in the ciphertext | ||
:param iv: the initialization vector | ||
:param c: the ciphertext | ||
:param pos: the position to modify at | ||
:param p: the original plaintext | ||
:param p_: the new plaintext | ||
:return: a tuple containing the modified initialization vector and the modified ciphertext | ||
""" | ||
iv_ = bytearray(iv) | ||
c_ = bytearray(c) | ||
for i in range(len(p)): | ||
if pos + i < 16: | ||
iv_[pos + i] = iv[pos + i] ^ p[i] ^ p_[i] | ||
else: | ||
c_[pos + i - 16] = c[pos + i - 16] ^ p[i] ^ p_[i] | ||
|
||
return bytes(iv_), bytes(c_) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from Crypto.Cipher import AES | ||
from Crypto.Random import get_random_bytes | ||
from Crypto.Util.strxor import strxor | ||
|
||
key = get_random_bytes(16) | ||
|
||
|
||
def _encrypt(p): | ||
return AES.new(key, AES.MODE_CBC, key).encrypt(p) | ||
|
||
|
||
def _decrypt(c): | ||
return AES.new(key, AES.MODE_CBC, key).decrypt(c) | ||
|
||
|
||
def attack(): | ||
""" | ||
Recovers the initialization vector using a chosen-ciphertext attack. | ||
:return: the initialization vector | ||
""" | ||
p = _decrypt(bytes(32)) | ||
return strxor(p[:16], p[16:]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
from Crypto.Cipher import AES | ||
from Crypto.Random import get_random_bytes | ||
from Crypto.Util.Padding import pad | ||
from Crypto.Util.Padding import unpad | ||
|
||
key = get_random_bytes(16) | ||
|
||
|
||
def _encrypt(p): | ||
iv = get_random_bytes(16) | ||
return iv, AES.new(key, AES.MODE_CBC, iv).encrypt(pad(p, 16)) | ||
|
||
|
||
def _valid_padding(iv, c): | ||
try: | ||
unpad(AES.new(key, AES.MODE_CBC, iv).decrypt(c), 16) | ||
return True | ||
except ValueError: | ||
return False | ||
|
||
|
||
def _correct_padding(iv, c, i): | ||
if not _valid_padding(iv, c): | ||
return False | ||
|
||
# Special handling for last byte of last block | ||
if i == 15: | ||
iv[14] ^= 1 | ||
return _valid_padding(iv, c) | ||
|
||
return True | ||
|
||
|
||
def _attack_block(iv, c): | ||
dc = bytearray(16) | ||
p = bytearray(16) | ||
iv_ = bytearray(iv) | ||
for i in reversed(range(16)): | ||
# The padding byte for this position. | ||
pb = 16 - i | ||
# Apply padding byte to iv. | ||
for j in reversed(range(i + 1, 16)): | ||
iv_[j] = dc[j] ^ pb | ||
|
||
# Try every byte until padding is correct. | ||
for b in range(256): | ||
iv_[i] = b | ||
if _correct_padding(iv_, c, i): | ||
dc[i] = b ^ pb | ||
p[i] = dc[i] ^ iv[i] | ||
|
||
return p | ||
|
||
|
||
def attack(iv, c): | ||
""" | ||
Recovers the plaintext using the padding oracle attack. | ||
:param iv: the initialization vector | ||
:param c: the ciphertext | ||
:return: the plaintext | ||
""" | ||
p = _attack_block(iv, c) | ||
for i in range(16, len(c), 16): | ||
p += _attack_block(c[i - 16:i], c[i:i + 16]) | ||
|
||
return unpad(p, 16) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from Crypto.Cipher import AES | ||
from Crypto.Random import get_random_bytes | ||
from Crypto.Util.Padding import pad | ||
from Crypto.Util.Padding import unpad | ||
|
||
zero_iv = bytes(16) | ||
key = get_random_bytes(16) | ||
|
||
|
||
# Notice how the key is used for encryption and authentication... | ||
def _encrypt(p): | ||
p = pad(p, 16) | ||
iv = get_random_bytes(16) | ||
c = AES.new(key, AES.MODE_CBC, iv).encrypt(p) | ||
# Encrypt-and-MAC using CBC-MAC to prevent chosen-ciphertext attacks. | ||
t = AES.new(key, AES.MODE_CBC, zero_iv).encrypt(p)[-16:] | ||
return iv, c, t | ||
|
||
|
||
def _decrypt(iv, c, t): | ||
p = AES.new(key, AES.MODE_CBC, iv).decrypt(c) | ||
t_ = AES.new(key, AES.MODE_CBC, zero_iv).encrypt(p)[-16:] | ||
# Check the MAC to be sure the message isn't forged. | ||
if t != t_: | ||
return None | ||
|
||
return unpad(p, 16) | ||
|
||
|
||
def attack(iv, c, t): | ||
""" | ||
Uses a chosen-ciphertext attack to decrypt the ciphertext. | ||
:param iv: the initialization vector | ||
:param c: the ciphertext | ||
:param t: the tag corresponding to the ciphertext | ||
:return: the plaintext | ||
""" | ||
c_ = iv + c | ||
p_ = _decrypt(bytes(16), c_, c[-16:]) | ||
return p_[16:] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from Crypto.Cipher import AES | ||
from Crypto.Random import get_random_bytes | ||
from Crypto.Util.Padding import pad | ||
from Crypto.Util.Padding import unpad | ||
|
||
zero_iv = bytes(16) | ||
key = get_random_bytes(16) | ||
|
||
|
||
# Notice how the key is used for encryption and authentication... | ||
def _encrypt(p): | ||
p = pad(p, 16) | ||
iv = get_random_bytes(16) | ||
c = AES.new(key, AES.MODE_CBC, iv).encrypt(p) | ||
# Encrypt-then-MAC using CBC-MAC to prevent chosen-ciphertext attacks. | ||
t = AES.new(key, AES.MODE_CBC, zero_iv).encrypt(iv + c)[-16:] | ||
return iv, c, t | ||
|
||
|
||
def _decrypt(iv, c, t): | ||
t_ = AES.new(key, AES.MODE_CBC, zero_iv).encrypt(iv + c)[-16:] | ||
# Check the MAC to be sure the message isn't forged. | ||
if t != t_: | ||
return None | ||
|
||
return unpad(AES.new(key, AES.MODE_CBC, iv).decrypt(c), 16) | ||
|
||
|
||
def attack(iv, c, t): | ||
""" | ||
Uses a chosen-ciphertext attack to decrypt the ciphertext. | ||
:param iv: the initialization vector | ||
:param c: the ciphertext | ||
:param t: the tag corresponding to the ciphertext | ||
:return: the plaintext | ||
""" | ||
p_ = bytes(16) + iv + c | ||
iv_, c_, t_ = _encrypt(p_) | ||
c__ = iv + c | ||
p__ = _decrypt(iv_, c__, c_[-32:-16]) | ||
return p__[16:] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from Crypto.Cipher import AES | ||
from Crypto.Random import get_random_bytes | ||
from Crypto.Util.Padding import pad | ||
from Crypto.Util.Padding import unpad | ||
|
||
zero_iv = bytes(16) | ||
key = get_random_bytes(16) | ||
|
||
|
||
# Notice how the key is used for encryption and authentication... | ||
def _encrypt(p): | ||
p = pad(p, 16) | ||
iv = get_random_bytes(16) | ||
# MAC-then-encrypt using CBC-MAC to prevent chosen-ciphertext attacks. | ||
t = AES.new(key, AES.MODE_CBC, zero_iv).encrypt(p)[-16:] | ||
c = AES.new(key, AES.MODE_CBC, iv).encrypt(p + t) | ||
return iv, c | ||
|
||
|
||
def _decrypt(iv, c): | ||
d = AES.new(key, AES.MODE_CBC, iv).decrypt(c) | ||
p = d[:-16] | ||
t = d[-16:] | ||
t_ = AES.new(key, AES.MODE_CBC, zero_iv).encrypt(p)[-16:] | ||
# Check the MAC to be sure the message isn't forged. | ||
if t != t_: | ||
return None | ||
|
||
return unpad(p, 16) | ||
|
||
|
||
def attack(iv, c, encrypted_zeroes): | ||
""" | ||
Uses a chosen-ciphertext attack to decrypt the ciphertext. | ||
Prior knowledge of E_k(0^16) is required for this attack to work. | ||
:param iv: the initialization vector | ||
:param c: the ciphertext | ||
:param encrypted_zeroes: a full zero block encrypted using the key | ||
:return: the plaintext | ||
""" | ||
c_ = iv + c[:-16] + encrypted_zeroes | ||
p_ = _decrypt(bytes(16), c_) | ||
return p_[16:] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from Crypto.Util.strxor import strxor | ||
|
||
|
||
def attack(m1, t1, m2, t2): | ||
m3 = bytearray(m1) | ||
m3 += strxor(t1, m2[:16]) | ||
for i in range(16, len(m2), 16): | ||
m3 += m2[i:i + 16] | ||
return m3, t2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import zlib | ||
|
||
from Crypto.Cipher import AES | ||
from Crypto.Random import get_random_bytes | ||
from Crypto.Util import Counter | ||
|
||
key = get_random_bytes(16) | ||
secret = get_random_bytes(16) | ||
|
||
|
||
def _encrypt(p): | ||
return AES.new(key, AES.MODE_CTR, counter=Counter.new(128)).encrypt(zlib.compress(p + secret)) | ||
|
||
|
||
def attack(secret_len): | ||
""" | ||
Recovers a secret using the CRIME attack (CTR version). | ||
:param secret_len: the length of the secret to recover | ||
:return: the secret | ||
""" | ||
padding = bytearray() | ||
for i in range(secret_len): | ||
padding.append(i) | ||
|
||
s = bytearray() | ||
for i in range(secret_len): | ||
min = None | ||
for j in range(256): | ||
l = len(_encrypt(padding + s + bytes([j]) + padding)) | ||
if min is None or l < min[0]: | ||
min = (l, j) | ||
|
||
s.append(min[1]) | ||
|
||
return bytes(s) |
Oops, something went wrong.