from Crypto.Random import random import binascii import hashlib import challenge39 decryptedHashes = set() pub, priv = challenge39.genKey(128) def encrypt(plaintext): return challenge39.encryptbytes(pub, plaintext) def decryptOnce(ciphertext): sha1 = hashlib.sha1() sha1.update(ciphertext) digest = sha1.digest() if digest in decryptedHashes: raise ValueError('Already decrypted') decryptedHashes.add(digest) return challenge39.decryptbytes(priv, ciphertext) if __name__ == '__main__': plaintext = b'secret text' ciphertext = encrypt(plaintext) plaintext2 = decryptOnce(ciphertext) if plaintext2 != plaintext: raise ValueError(plaintext2 + b' != ' + plaintext)
import challenge39 import binascii import math (pub0, priv0) = challenge39.genKey(256) (pub1, priv1) = challenge39.genKey(256) (pub2, priv2) = challenge39.genKey(256) plaintext = b'This is a plaintext string' plainnum = challenge39.bytestonum(plaintext) c0 = challenge39.encryptnum(pub0, plainnum) c1 = challenge39.encryptnum(pub1, plainnum) c2 = challenge39.encryptnum(pub2, plainnum) n0 = pub0[1] n1 = pub1[1] n2 = pub2[1] ms0 = n1 * n2 ms1 = n0 * n2 ms2 = n0 * n1 N = n0 * n1 * n2 r0 = (c0 * ms0 * challenge39.invmod(ms0, n0)) r1 = (c1 * ms1 * challenge39.invmod(ms1, n1)) r2 = (c2 * ms2 * challenge39.invmod(ms2, n2)) r = (r0 + r1 + r2) % N
import challenge39 import challenge47 import itertools import re pub, priv = challenge39.genKey(768) def parityOracle(c): _, n = pub k = (n.bit_length() + 7) // 8 p = challenge39.decryptnum(priv, c) pbytes = challenge39.numtobytes(p) pbytes = (b'\x00' * (k - len(pbytes))) + pbytes return pbytes[0:2] == b'\x00\x02' def computeNextS(e, n, M, s, B, c0): if len(M) > 1: while True: s += 1 c = (c0 * pow(s, e, n)) % n if parityOracle(c): return (s, c) else: a, b = M[0] r = (2 * (b * s - 2 * B) + n - 1) // n while True: sLow = (2 * B + r * n + b - 1) // b sHigh = (3 * B + r * n + a - 1) // a for s in range(sLow, sHigh):
from Crypto.Random import random import challenge39 import re pub, priv = challenge39.genKey(256) def parityOracle(c): _, n = pub k = (n.bit_length() + 7) // 8 p = challenge39.decryptnum(priv, c) pbytes = challenge39.numtobytes(p) pbytes = (b'\x00' * (k - len(pbytes))) + pbytes return pbytes[0:2] == b'\x00\x02' def randnonzerobytes(k): return bytes(random.sample(range(1, 256), k)) def padPKCS15(s, n): if len(s) < 8: raise Exception('unexpected') k = (n.bit_length() + 7) // 8 padding = randnonzerobytes(k - 3 - len(s)) return b'\x00\x02' + padding + b'\x00' + s def computeFirstS(e, n, B, c0, parityOracle): s = (n + 3*B - 1) // (3*B) while True: c = (c0 * pow(s, e, n)) % n if parityOracle(c): return (s, c) s += 1
from Crypto.Random import random import binascii import hashlib import challenge39 decryptedHashes = set() pub, priv = challenge39.genKey(128) def encrypt(plaintext): return challenge39.encryptbytes(pub, plaintext) def decryptOnce(ciphertext): sha1 = hashlib.sha1() sha1.update(ciphertext) digest = sha1.digest() if digest in decryptedHashes: raise ValueError('Already decrypted') decryptedHashes.add(digest) return challenge39.decryptbytes(priv, ciphertext) if __name__ == '__main__': plaintext = b'secret text' ciphertext = encrypt(plaintext) plaintext2 = decryptOnce(ciphertext) if plaintext2 != plaintext: raise ValueError(plaintext2 + b' != ' + plaintext) (e, n) = pub s = random.randint(2, n - 1) c = challenge39.bytestonum(ciphertext)
import challenge39 import challenge47 import itertools import re pub, priv = challenge39.genKey(768) def parityOracle(c): _, n = pub k = (n.bit_length() + 7) // 8 p = challenge39.decryptnum(priv, c) pbytes = challenge39.numtobytes(p) pbytes = (b'\x00' * (k - len(pbytes))) + pbytes return pbytes[0:2] == b'\x00\x02' def computeNextS(e, n, M, s, B, c0): if len(M) > 1: while True: s += 1 c = (c0 * pow(s, e, n)) % n if parityOracle(c): return (s, c) else: a, b = M[0] r = (2 * (b * s - 2 * B) + n - 1) // n while True: sLow = (2*B + r*n + b - 1) // b sHigh = (3*B + r*n + a - 1) // a for s in range(sLow, sHigh): c = (c0 * pow(s, e, n)) % n if parityOracle(c):
return False digest = m.group(1) sha1 = hashlib.sha1() sha1.update(message) return digest == sha1.digest() def forgeSignature(pub, message): sha1 = hashlib.sha1() sha1.update(message) digest = sha1.digest() block = b'\x00\x01\xff\x00' + digest + (b'\x00' * (128 - len(digest) - 4)) (d, n) = pub blocknum = challenge39.bytestonum(block) signaturenum = challenge40.floorRoot(blocknum, 3) + 1 signature = challenge39.numtobytes(signaturenum) return signature if __name__ == '__main__': message = b'hi mom' pub, priv = challenge39.genKey(1024) signature = generateSignature(priv, message) print(signature) if not verifySignature(pub, message, signature): raise Exception(message + b' has invalid signature ' + signature) forgedSignature = forgeSignature(pub, message) print(forgedSignature) if not verifySignature(pub, message, forgedSignature): raise Exception(message + b' has invalid signature ' + forgedSignature)
block = b'\x00' + challenge39.encryptbytes(pub, signature) r = re.compile(b'\x00\x01\xff+?\x00(.{20})', re.DOTALL) m = r.match(block) if not m: return False digest = m.group(1) sha1 = hashlib.sha1() sha1.update(message) return digest == sha1.digest() def forgeSignature(pub, message): sha1 = hashlib.sha1() sha1.update(message) digest = sha1.digest() block = b'\x00\x01\xff\x00' + digest + (b'\x00' * (128 - len(digest) - 4)) (d, n) = pub blocknum = challenge39.bytestonum(block) signaturenum = challenge40.floorRoot(blocknum, 3) + 1 signature = challenge39.numtobytes(signaturenum) return signature if __name__ == '__main__': message = b'hi mom' pub, priv = challenge39.genKey(1024) signature = generateSignature(priv, message) if not verifySignature(pub, message, signature): raise Exception(message + b' has invalid signature ' + signature) forgedSignature = forgeSignature(pub, message) if not verifySignature(pub, message, forgedSignature): raise Exception(message + b' has invalid signature ' + forgedSignature)