def recv1(self,I,A): self.A = A self.Ic = I # <<- incoming user, we will compare this after calcualting the recevied HMAC self.b = s2i(open("/dev/urandom").read(4)) # <<- random number self.salt = open("/dev/urandom").read(4) # <<- should be taken from a db x = s2i(hashlib.sha256(self.salt+self.P).digest()) # <<- this should be taken from a DB, although maybe scrypt/bcrypt/sth similar ? self.v = pow(self.g,x,self.N) self.B = (pow(self.g,self.b,self.N)) self.u = random.randint(2**127,(2**128)-1)
def tworker3(hpass,a,start,step,g,N,q): ''' this BF password ''' sc = ord('a')+start ec = ord('z') cc = [sc] while True: h_c = "".join([chr(c) for c in cc]) x = s2i(hashlib.sha256(h_c).digest()) S = pow(2,a+x,N) K = hashlib.sha256(i2s(S)).digest() if hmac.HMAC(K,"",hashlib.sha256).digest() == hpass: q.put(h_c) break cc[0] += step for i in range(0,len(cc)): if cc[i] > ec: try: cc[i+1] += 1 except: cc.append(sc) cc[i] %= (ec+1) cc[i] += sc else: break
def x_recovery(self, m, r, s, k, dgst=hashlib.sha1): # recovering x knowing k # m - message # r,s - public signature # k - this should be secret (nounce) top = (s*k)-s2i(dgst(m).digest()) return (top * invmod(r, self.q)) % self.q
def __init__(self,N,g,k,I,P): self.N = N self.g = g self.k = k self.I = I self.P = P self.a = s2i(open("/dev/urandom").read(2)) # in normal operations this should be bigger self.A = pow(self.g,self.a,self.N)
def verify(self, m, r, s, y, dgst=hashlib.sha1): # signature verification # https://en.wikipedia.org/wiki/Digital_Signature_Algorithm#Verifying assert (r > 0 and r < self.q), "wrong r: 0 < r < q" assert (s > 0 and s < self.q), "wrong s: 0 < s < q" w = invmod(s, self.q) u1 = (s2i(dgst(m).digest())*w) % self.q u2 = (r*w) % self.q v = ((modexp(self.g, u1, self.p)*modexp(y, u2, self.p)) % self.p )% self.q assert (v == r), "verification failed, v != r" return True
def signk(self, m, x, dgst=hashlib.sha1): # signing with a leak of the k value # m - message # x - private key # https://en.wikipedia.org/wiki/Digital_Signature_Algorithm#Signing r = 0 k = 0 while r == 0: k = randint(0, self.q) r = modexp(self.g, k, self.p) % self.q s = (invmod(k, self.q) * (s2i(dgst(m).digest())+(x*r))) % self.q return (r, s, k)
def tworker2(hpass,a,words,start,step,g,N,q): ''' dictionary attack ''' i = start while i < len(words): x = s2i(hashlib.sha256(words[i]).digest()) S = pow(2,a+x,N) K = hashlib.sha256(i2s(S)).digest() if hmac.HMAC(K,"",hashlib.sha256).digest() == hpass: q.put(words[i]) break i += step
def forging(mesg,key): e = key[0] n = key[1] if e != 3: raise Exception("e not equal 3") pkcs15 = PKCS15() dgst = hashlib.sha1(mesg).digest() keylen = len(i2s(n)) getcontext().prec = keylen * 8 # this is the valid beginning forge = "\x00\x01%s\x00%s" % ("\xff" * 8, dgst) # this will be garbge garbage = "\x00" * (keylen - 8 - len(dgst) - 13) whole = s2i(forge+garbage) cr = int(pow(whole,Decimal(1)/Decimal(3)))+1 return i2s(cr)
def attack(enc,key,iseven): e = key[0] # e - from the pub key n = key[1] # n - from the pub key ct = s2i(enc[0]) # encrypted message c2 = pow(2,e,n) # (2**e)%n) ct = (ct * c2) % n # we need to do this before we start counting limit = int(math.log(n,2))+1 # number of bits in the key getcontext().prec = limit # how precise our floats should be a = Decimal(0) b = Decimal(n) for x in range(limit): t = (a+b)/2 if iseven([i2s(ct)]): b = t else: a = t ct = (ct * c2) % n return i2s(int(b)).encode('string_escape')
def b_step2a (pubkey, prvkey, c, oracle): """ Bleichenbacher step 2a """ e = pubkey[0] n = pubkey[1] c = s2i("".join(c)) c0 = (c * modexp(1, e, n)) % n s1 = n // 0x3B count = 0 while True: c1 = (c0 * modexp(s1, e, n)) % n if oracle(prvkey, list(i2s(c1))): break s1 += 1 if count % 10 == 0: sys.stdout.write("%s \r" % (count)) sys.stdout.flush() count += 1 return s1
#!/usr/bin/env python from c39 import RSA # RSA from c36 import i2s, s2i if __name__ == "__main__": msg = "attack after the breakfast" rsa = RSA() pub,priv = rsa.keygen() C = rsa.encrypt(msg,pub) assert rsa.decrypt(C,priv) == msg, "bug in my RSA, decryption didn't provide the same clear text" S = 3 # lowest possible S C1 = list() # the cipher text is a list for ct in C: # lets iterate over the ciphertext C1.append(i2s((pow(S,pub[0],pub[1])*s2i(ct)) % pub[1])) # if C1 != C: # the C1 has to be different the C P1 = rsa.decrypt(C1,priv) print i2s((s2i(P1)/S)%pub[1]) else: print "something wrong C1 and C should be different"
def recv1(self,salt,B,u): self.salt = salt x = s2i(hashlib.sha256(self.salt+self.P).digest()) S = pow(B,(self.a+u*x),self.N) self.K = hashlib.sha256(i2s(S)).digest()
print "1. encrypting using pub key" ct1 = RSA().encrypt(cleartext,pub1) print "2. key generation" pub2,priv2 = RSA().keygen(l=2048,s=False) # s=False gives e=3 print "2. encrypting using pub key" ct2 = RSA().encrypt(cleartext,pub2) assert RSA().decrypt(ct0,priv0) == cleartext, "error on key0" assert RSA().decrypt(ct1,priv1) == cleartext, "error on key1" assert RSA().decrypt(ct2,priv2) == cleartext, "error on key2" # https://en.wikipedia.org/wiki/Coppersmith%27s_Attack#H.C3.A5stad.27s_Broadcast_Attack # https://en.wikipedia.org/wiki/Chinese_remainder_theorem c_0 = s2i(ct0[0]) c_1 = s2i(ct1[0]) c_2 = s2i(ct2[0]) n_0 = pub0[1] n_1 = pub1[1] n_2 = pub2[1] m_s_0 = n_1 * n_2 m_s_1 = n_0 * n_2 m_s_2 = n_0 * n_1 result = (c_0 * m_s_0 * invmod(m_s_0, n_0)) result += (c_1 * m_s_1 * invmod(m_s_1, n_1)) result += (c_2 * m_s_2 * invmod(m_s_2, n_2)) result %= (n_0 * n_1 * n_2) print i2s(int(pow(Decimal(result),Decimal(1)/Decimal(3)))+1)
len_n = len(i2s(n)) - 1 len_m = len(m) if len_n > len_m: return [i2s(pow(s2i(m), e, n))] else: cs = [] i = 0 while len_n * i < len_m: cs.append(i2s(pow(s2i(m[len_n * i : len_n * (i + 1)]), e, n))) i += 1 return cs def decrypt(self, cs, (d, n)): m = "" for c in cs: m += i2s(pow(s2i(c), d, n)) return m if __name__ == "__main__": k1, k2 = RSA().keygen() cleartext = "this is just a test of a message that will be encrypted using RSA private/public key cryptography, lets try something very long to see how this may woRk.\ We may also try to add some random things here and here, and here. Just a test like I said," # cleartext = open("c39.py").read() # <<-- this also works, but this actually needs padding print cleartext ciphertext = RSA().encrypt(cleartext, k1) print ciphertext decryptedtext = RSA().decrypt(ciphertext, k2) print decryptedtext