def prepare(message): """ Suppose we intercept a padded ciphertext. Our goal is to completely decrypt it, just by using the oracle. """ message_encoded = PKCS1_encode(message, k) ciphertext = rsa.encrypt_string(pk, message_encoded) return ciphertext
def run_tests(m): """ Small sanity test suite """ menc = PKCS1_encode(m, k) print("1. (un)pad:", PKCS1_decode(menc) == m) m1 = rsa.decrypt_string(sk, rsa.encrypt_string(pk, m)) print("2. rsa w/o pad:", m == m1) m2 = PKCS1_decode(rsa.decrypt_string(sk, rsa.encrypt_string(pk, menc))) print("3. rsa w/ pad:", m == m2) m3 = oracle(rsa.encrypt_string(pk, menc)) == True print("4. oracle well-formed:", m3) m4 = oracle(rsa.encrypt_string(pk, m)) == False print("5. oracle not well-formed", m4)
data in there, and I completely ignore the implementation of 'other ASN.1 data'. """ assert len(string) < 256 assert bits % 8 == 0 byte_goal = bits / 8 prepend = "\x00\x01" append = "\x00ASN.1" + chr(len(string)) bytes_to_add = (byte_goal - (len(string) % byte_goal) - len(prepend) - len(append)) return prepend + ("\xff" * bytes_to_add) + append + string block = pkcs_1_5(hash, bits) signature = rsa.encrypt_string(block, R) # Note: signing is w/ priv key. def verify(sig, message, pubkey): block = rsa.decrypt_string(sig, pubkey) for i in range((bits/8) - len(block)): block = "\x00" + block return sha1(message).digest() == unpad(block) def unpad(string): state = "start" result = "" for i, c in enumerate(string): if i == 0 and c != "\x00": return "FAIL " + str(i) + str([c]) + "_" elif i == 0: continue
return (ciphertext * k**e) % n def cleanup(string, substitution=''): safe = '' for c in string: if 32 <= ord(c) <= 126: safe += c else: safe += substitution return safe b64s = 'VGhhdCdzIHdoeSBJIGZvdW5kIHlvdSBkb24ndCBwbGF5IGFyb3VuZCB3aXRoIHRoZSBGdW5reSBDb2xkIE1lZGluYQ==' plaintext = base64.b64decode(b64s) ciphertext = rsa.encrypt_string(plaintext, pubkey) # um, if e=3, I don't think this string wraps the modulus. So in # theory, I think we could just cube-root it, but oh well. bounds = [0, n] start = time.time() for i in range(2048): p = parity(multiply(ciphertext, 2**(i + 1), e, n)) half_the_dist = (bounds[1] - bounds[0]) / 2 if p == 0: bounds = [bounds[0], bounds[1] - half_the_dist] elif p == 1: bounds = [bounds[0] + half_the_dist, bounds[1]] if i % 16 == 0: print p, i, cleanup(rsa.i2s(bounds[1]), '_') # get 256 char wide screen
def multiply(ciphertext, k, e, n): return (ciphertext * k ** e) % n def cleanup(string, substitution=''): safe = '' for c in string: if 32 <= ord(c) <= 126: safe += c else: safe += substitution return safe b64s = 'VGhhdCdzIHdoeSBJIGZvdW5kIHlvdSBkb24ndCBwbGF5IGFyb3VuZCB3aXRoIHRoZSBGdW5reSBDb2xkIE1lZGluYQ==' plaintext = base64.b64decode(b64s) ciphertext = rsa.encrypt_string(plaintext, pubkey) # um, if e=3, I don't think this string wraps the modulus. So in # theory, I think we could just cube-root it, but oh well. bounds = [0, n] start = time.time() for i in range(2048): p = parity(multiply(ciphertext, 2**(i+1), e, n)) half_the_dist = (bounds[1] - bounds[0]) / 2 if p == 0: bounds = [bounds[0], bounds[1] - half_the_dist] elif p == 1: bounds = [bounds[0] + half_the_dist, bounds[1]] if i % 16 == 0: print p, i, cleanup(rsa.i2s(bounds[1]), '_') # get 256 char wide screen
# the file 'LICENSE' in the same directory as this file. from cryptopals import warn, cuberoot import rsa import copy k = 3 # How many times to encrypt the same plaintext, under different # public keys. message = 'Hello, world! I am gonna encrypt this thrice; uh oh.' bits = len(message) * 8 / 2 c = [None] * k n = [None] * k for i in range(k): U, R = rsa.keypair(bits) ciphertext = rsa.encrypt_string(message, U) c[i] = ciphertext n[i] = U[1] # the second part of the pubkey print "public " + str(U[1])[:60] + "...." print "ciphertext " + str(ciphertext)[:60] + "...." decrypt = rsa.decrypt_string(ciphertext, R) print print "Bob gets this message:", decrypt #### Eve # Calculate products of the moduli (pubkeys) EXCEPT pubkey number i. ms = [None] * k for i in range(k): x = copy.copy(n)
# the file 'LICENSE' in the same directory as this file. from cryptopals import warn, cuberoot import rsa import copy k = 3 # How many times to encrypt the same plaintext, under different # public keys. message = 'Hello, world! I am gonna encrypt this thrice; uh oh.' bits = len(message) * 8 / 2 c = [None]*k n = [None]*k for i in range(k): U, R = rsa.keypair(bits) ciphertext = rsa.encrypt_string(message, U) c[i] = ciphertext n[i] = U[1] # the second part of the pubkey print "public " + str(U[1])[:60] + "...." print "ciphertext " + str(ciphertext)[:60] + "...." decrypt = rsa.decrypt_string(ciphertext, R) print print "Bob gets this message:", decrypt #### Eve # Calculate products of the moduli (pubkeys) EXCEPT pubkey number i. ms = [None]*k for i in range(k): x = copy.copy(n)
def encrypt(self, message): result = {} result["ciphertext"] = rsa.encrypt_string(message, self.pub) result["pubkey"] = self.pub return result
plaintext = rsa.decrypt_string(ciphertext, privkey) assert bits % 8 == 0 bytes = bits / 8 diff = bytes - len(plaintext) plaintext = "\x00" * diff + plaintext assert len(plaintext) == bytes, len(plaintext) return plaintext[0] == "\x00" and plaintext[1] == "\x02" Bits = 768 / 2 pubkey, privkey = rsa.keypair(Bits) print pubkey[1].bit_length(), "bit modulus" short_message = """Now these points of data make a beautiful line And we're out of beta; we're releasing on time""" m = pkcs_1(short_message, Bits * 2) # Bits*2 = length of n c = rsa.encrypt_string(m, pubkey) print "Oracle says that raw ciphertext conforms?", oracle(c, privkey, Bits * 2) assert oracle(c, privkey, Bits*2) #### Step 1 (Easy if c is already PKCS conforming) e = pubkey[0] n = pubkey[1] k = Bits * 2 / 8 # Length of n in bytes B = 2 ** (8 * (k - 2)) s = [1] c = [c] M = [[[2*B, 3*B-1]]] # M is a list of sets of intervals. i = 1 start = time() while(1):
#!/usr/bin/env python # chal39.py - Implement RSA # # Copyright (C) 2015 Andrew J. Zimolzak <*****@*****.**>, # and licensed under GNU GPL version 3. Full notice is found in # the file 'LICENSE' in the same directory as this file. from cryptopals import warn import rsa hello = "Hello, world! This is a message from me to you! I am typing this on a certain type of computer, and I wonder how many bits I will need." bits = len(hello) * 8 / 2 print bits, "bit key" U, R = rsa.keypair(bits) ciphertext = rsa.encrypt_string(hello, U) decrypt = rsa.decrypt_string(ciphertext, R) print "Decrypted this message:", decrypt assert hello == decrypt #### tests #### warn("Passed assertions:", __file__)
def encrypt(self, message): result = {} result['ciphertext'] = rsa.encrypt_string(message, self.pub) result['pubkey'] = self.pub return result
#!/usr/bin/env python # chal39.py - Implement RSA # # Copyright (C) 2015 Andrew J. Zimolzak <*****@*****.**>, # and licensed under GNU GPL version 3. Full notice is found in # the file 'LICENSE' in the same directory as this file. from cryptopals import warn import rsa hello = 'Hello, world! This is a message from me to you! I am typing this on a certain type of computer, and I wonder how many bits I will need.' bits = len(hello) * 8 / 2 print bits, "bit key" U, R = rsa.keypair(bits) ciphertext = rsa.encrypt_string(hello, U) decrypt = rsa.decrypt_string(ciphertext, R) print "Decrypted this message:", decrypt assert hello == decrypt #### tests #### warn("Passed assertions:", __file__)