Last active
October 19, 2025 03:12
-
-
Save avalonalex/2122098 to your computer and use it in GitHub Desktop.
Revisions
-
avalonalex revised this gist
Jun 3, 2015 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -259,9 +259,9 @@ def decrypt(secret, modN, d, blockSize): def block_size(val): try: v = int(val) assert(v >= 10 and v <= 1000) except: raise argparse.ArgumentTypeError("{} is not a valid block size".format(val)) return val if __name__ == '__main__': -
avalonalex revised this gist
Jun 3, 2015 . 1 changed file with 51 additions and 17 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,11 @@ #!/usr/bin/env python import argparse import copy import math import pickle import random from itertools import combinations def euclid(a, b): @@ -183,26 +187,27 @@ def newKey(a, b, k): break except: raise ValueError n = p * q m = (p - 1) * (q - 1) while True: e = random.randint(1, m) if coPrime([e, m]): break d = modInv(e, m) return (n, e, d) def string2numList(strn): """Converts a string to a list of integers based on ASCII values""" return [ ord(chars) for chars in pickle.dumps(strn) ] def numList2string(l): """Converts a list of integers to a string based on ASCII values""" return pickle.loads(''.join(map(chr, l))) def numList2blocks(l, n): @@ -251,18 +256,47 @@ def decrypt(secret, modN, d, blockSize): numList = blocks2numList(numBlocks, blockSize) return numList2string(numList) def block_size(val): try: v = int(val) assert(v >= 10 and c <= 1000) except: raise ArgumentTypeError("'%s' is not a valid block size" % val) return val if __name__ == '__main__': parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group(required=True) group.add_argument("-m", "--message", help="Text message to encrypt") group.add_argument("-f", "--file", type=file, help="Text file to encrypt") parser.add_argument("-b", "--block-size", type=block_size, default=15, help="Block size to break message info smaller trunks") args = parser.parse_args() print """ ------------------------------------------------------ This program is intended for the purpose pedagogy only ------------------------------------------------------ """ n, e, d = newKey(10 ** 100, 10 ** 101, 50) if args.message is not None: message = args.message else: print args.file try: message = args.file.read() finally: args.file.close() print "original message is {}".format(message) print "-"*80 cipher = encrypt(message, n, e, 15) print "cipher text is {}".format(cipher) print "-"*80 deciphered = decrypt(cipher, n, d, 15) print "decrypted message is {}".format(deciphered) -
avalonalex revised this gist
Aug 17, 2014 . 1 changed file with 45 additions and 45 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -5,7 +5,7 @@ def euclid(a, b): """returns the Greatest Common Divisor of a and b""" a = abs(a) b = abs(b) if a < b: @@ -15,52 +15,52 @@ def euclid(a, b): return a def coPrime(l): """returns 'True' if the values in the list L are all co-prime otherwise, it returns 'False'. """ for i, j in combinations(l, 2): if euclid(i, j) != 1: return False return True def extendedEuclid(a, b): """return a tuple of three values: x, y and z, such that x is the GCD of a and b, and x = y * a + z * b""" if a == 0: return b, 0, 1 else: g, y, x = extendedEuclid(b % a, a) return g, x - (b // a) * y, y def modInv(a, m): """returns the multiplicative inverse of a in modulo m as a positive value between zero and m-1""" # notice that a and m need to co-prime to each other. if coPrime([a, m]): linearCombination = extendedEuclid(a, m) return linearCombination[1] % m else: return 0 def extractTwos(m): """m is a positive integer. A tuple (s, d) of integers is returned such that m = (2 ** s) * d.""" # the problem can be break down to count how many '0's are there in # the end of bin(m). This can be done this way: m & a stretch of '1's # which can be represent as (2 ** n) - 1. assert m >= 0 i = 0 while m & (2 ** i) == 0: i += 1 return i, m >> i def int2baseTwo(x): """x is a positive integer. Convert it to base two as a list of integers in reverse order as a list.""" # repeating x >>= 1 and x & 1 will do the trick assert x >= 0 bitInverse = [] @@ -71,7 +71,7 @@ def int2baseTwo(x): def modExp(a, d, n): """returns a ** d (mod n)""" assert d >= 0 assert n >= 0 base2D = int2baseTwo(d) @@ -90,13 +90,13 @@ def modExp(a, d, n): def millerRabin(n, k): """ Miller Rabin pseudo-prime test return True means likely a prime, (how sure about that, depending on k) return False means definitely a composite. Raise assertion error when n, k are not positive integers and n is not 1 """ assert n >= 1 # ensure n is bigger than 1 assert k > 0 @@ -116,9 +116,9 @@ def millerRabin(n, k): assert 2 ** s * d == n - 1 def tryComposite(a): """Inner function which will inspect whether a given witness will reveal the true identity of n. Will only be called within millerRabin""" x = modExp(a, d, n) if x == 1 or x == n - 1: return None @@ -139,12 +139,12 @@ def tryComposite(a): def primeSieve(k): """return a list with length k + 1, showing if list[i] == 1, i is a prime else if list[i] == 0, i is a composite, if list[i] == -1, not defined""" def isPrime(n): """return True is given number n is absolutely prime, return False is otherwise.""" for i in range(2, int(n ** 0.5) + 1): if n % i == 0: return False @@ -159,9 +159,9 @@ def isPrime(n): def findAPrime(a, b, k): """Return a pseudo prime number roughly between a and b, (could be larger than b). Raise ValueError if cannot find a pseudo prime after 10 * ln(x) + 3 tries. """ x = random.randint(a, b) for i in range(0, int(10 * math.log(x) + 3)): if millerRabin(x, k): @@ -172,9 +172,9 @@ def findAPrime(a, b, k): def newKey(a, b, k): """ Try to find two large pseudo primes roughly between a and b. Generate public and private keys for RSA encryption. Raises ValueError if it fails to find one""" try: p = findAPrime(a, b, k) while True: @@ -187,28 +187,28 @@ def newKey(a, b, k): m = (p - 1) * (q - 1) while True: e = random.randint(1, m) if coPrime([e, m]): break d = modInv(e, m) return (n, e, d) def string2numList(strn): """Converts a string to a list of integers based on ASCII values""" # Note that ASCII printable characters range is 0x20 - 0x7E return [ord(chars) for chars in strn] def numList2string(l): """Converts a list of integers to a string based on ASCII values""" # Note that ASCII printable characters range is 0x20 - 0x7E return ''.join(map(chr, l)) def numList2blocks(l, n): """Take a list of integers(each between 0 and 127), and combines them into block size n using base 256. If len(L) % n != 0, use some random junk to fill L to make it.""" # Note that ASCII printable characters range is 0x20 - 0x7E returnList = [] toProcess = copy.copy(l) @@ -224,7 +224,7 @@ def numList2blocks(l, n): def blocks2numList(blocks, n): """inverse function of numList2blocks.""" toProcess = copy.copy(blocks) returnList = [] for numBlock in toProcess: @@ -238,15 +238,15 @@ def blocks2numList(blocks, n): def encrypt(message, modN, e, blockSize): """given a string message, public keys and blockSize, encrypt using RSA algorithms.""" numList = string2numList(message) numBlocks = numList2blocks(numList, blockSize) return [modExp(blocks, e, modN) for blocks in numBlocks] def decrypt(secret, modN, d, blockSize): """reverse function of encrypt""" numBlocks = [modExp(blocks, d, modN) for blocks in secret] numList = blocks2numList(numBlocks, blockSize) return numList2string(numList) @@ -256,13 +256,13 @@ def decrypt(secret, modN, d, blockSize): print ('n = {0}'.format(n)) print ('e = {0}'.format(e)) print ('d = {0}'.format(d)) message = """ We were the Leopards, the Lions, those who'll take our place will be little jackals, hyenas; But we'll go on thinking ourselves the salt of the earth. """ print(message) cipher = encrypt(message, n, e, 15) print(cipher) deciphered = decrypt(cipher, n, d, 15) print(deciphered) -
avalonalex revised this gist
Dec 25, 2013 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -72,7 +72,6 @@ def int2baseTwo(x): def modExp(a, d, n): '''returns a ** d (mod n)''' assert d >= 0 assert n >= 0 base2D = int2baseTwo(d) -
avalonalex revised this gist
Dec 25, 2013 . 1 changed file with 59 additions and 129 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,82 +1,40 @@ import random from itertools import combinations import math import copy def euclid(a, b): '''returns the Greatest Common Divisor of a and b''' a = abs(a) b = abs(b) if a < b: a, b = b, a while b != 0: a, b = b, a % b return a def coprime(l): '''returns 'True' if the values in the list L are all co-prime otherwier, it returns 'False'. ''' for i, j in combinations(l, 2): if euclid(i, j) != 1: return False return True def extendedEuclid(a, b): '''return a tuple of three values: x, y and z, such that x is the GCD of a and b, and x = y * a + z * b''' if a == 0: return (b, 0, 1) else: g, y, x = extendedEuclid(b % a, a) return (g, x - (b // a) * y, y) def modInv(a, m): '''returns the multiplicative inverse of a in modulo m as a positve value between zero and m-1''' # notice that a and m need to co-prime to each other. @@ -86,36 +44,6 @@ def modInv(a,m): linearcombination = extendedEuclid(a, m) return linearcombination[1] % m def extractTwos(m): '''m is a positive integer. A tuple (s, d) of integers is returned @@ -141,7 +69,8 @@ def int2baseTwo(x): x >>= 1 return bitInverse def modExp(a, d, n): '''returns a ** d (mod n)''' # a faster algorithms discussed in CIT 592 class assert d >= 0 @@ -150,16 +79,17 @@ def modExp(a,d,n): base2DLength = len(base2D) modArray = [] result = 1 for i in range(1, base2DLength + 1): if i == 1: modArray.append(a % n) else: modArray.append((modArray[i - 2] ** 2) % n) for i in range(0, base2DLength): if base2D[i] == 1: result *= base2D[i] * modArray[i] return result % n def millerRabin(n, k): ''' Miller Rabin pseudo-prime test @@ -194,24 +124,25 @@ def tryComposite(a): if x == 1 or x == n - 1: return None else: for j in range(1, s): x = modExp(x, 2, n) if x == 1: return False elif x == n - 1: return None return False for i in range(0, k): a = random.randint(2, n - 2) if tryComposite(a) == False: return False return True # actually, we should return probably true. def primeSieve(k): '''return a list with length k + 1, showing if list[i] == 1, i is a prime else if list[i] == 0, i is a composite, if list[i] == -1, not defined''' def isPrime(n): '''return True is given number n is absolutely prime, return False is otherwise.''' @@ -227,7 +158,8 @@ def isPrime(n): result[i] = 0 return result def findAPrime(a, b, k): '''Return a pseudo prime number roughly between a and b, (could be larger than b). Raise ValueError if cannot find a pseudo prime after 10 * ln(x) + 3 tries. ''' @@ -239,7 +171,8 @@ def findAPrime(a,b,k): x += 1 raise ValueError def newKey(a, b, k): ''' Try to find two large pseudo primes roughly between a and b. Generate public and private keys for RSA encryption. Raises ValueError if it fails to find one''' @@ -252,39 +185,36 @@ def newKey(a,b,k): except: raise ValueError n = p * q m = (p - 1) * (q - 1) while True: e = random.randint(1, m) if coprime([e, m]): break d = modInv(e, m) return (n, e, d) def string2numList(strn): '''Converts a string to a list of integers based on ASCII values''' # Note that ASCII printable characters range is 0x20 - 0x7E return [ord(chars) for chars in strn] def numList2string(l): '''Converts a list of integers to a string based on ASCII values''' # Note that ASCII printable characters range is 0x20 - 0x7E return ''.join(map(chr, l)) def numList2blocks(l, n): '''Take a list of integers(each between 0 and 127), and combines them into block size n using base 256. If len(L) % n != 0, use some random junk to fill L to make it.''' # Note that ASCII printable characters range is 0x20 - 0x7E returnList = [] toProcess = copy.copy(l) if len(toProcess) % n != 0: for i in range(0, n - len(toProcess) % n): toProcess.append(random.randint(32, 126)) for i in range(0, len(toProcess), n): block = 0 @@ -293,7 +223,8 @@ def numList2blocks(L,n): returnList.append(block) return returnList def blocks2numList(blocks, n): '''inverse function of numList2blocks.''' toProcess = copy.copy(blocks) returnList = [] @@ -306,34 +237,33 @@ def blocks2numList(blocks,n): returnList.extend(inner) return returnList def encrypt(message, modN, e, blockSize): '''given a string message, public keys and blockSize, encrypt using RSA algorithms.''' numList = string2numList(message) numBlocks = numList2blocks(numList, blockSize) return [modExp(blocks, e, modN) for blocks in numBlocks] def decrypt(secret, modN, d, blockSize): '''reverse function of encrypt''' numBlocks = [modExp(blocks, d, modN) for blocks in secret] numList = blocks2numList(numBlocks, blockSize) return numList2string(numList) if __name__ == '__main__': (n, e, d) = newKey(10 ** 100, 10 ** 101, 50) print ('n = {0}'.format(n)) print ('e = {0}'.format(e)) print ('d = {0}'.format(d)) message = ''' We were the Leopards, the Lions, those who'll take our place will be little jackals, hyenas; But we'll go on thinking ourselves the salt of the earth. ''' print(message) cipher = encrypt(message, n, e, 15) print(cipher) Amessage = decrypt(cipher, n, d, 15) print(Amessage) -
avalonalex revised this gist
Mar 19, 2012 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,6 @@ # Author Yuhan Hao # Email: yuhanhao@seas.upenn.edu # Tested under python3.2.2 import random import math -
avalonalex created this gist
Mar 19, 2012 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,340 @@ # October 2011 # Author Yuhan Hao # Email: yuhanhao@seas.upenn.edu # Tested under python3.2.2 # Coding Assignment 2 for CIT 592 import random import math import copy def euclid(a,b): '''returns the Greatest Common Divisor of a and b''' a = abs(a) b = abs(b) # make sure the algorithms still works even when # some negative numbers are passed to the program if a < b: a, b = b, a while b != 0: a, b = b, a % b return a def coprime(L): '''returns 'True' if the values in the list L are all co-prime otherwier, it returns 'False'. ''' for i in range (0, len(L)): for j in range (i + 1, len(L)): if euclid(L[i], L[j]) != 1: return False return True def extendedEuclid(a,b): '''return a tuple of three values: x, y and z, such that x is the GCD of a and b, and x = y * a + z * b''' footprint = [] # the boolean flag is used to make sure this function can return # right answer no matter which is bigger. if a < b: isASmallerThanB = True a, b = b, a else: isASmallerThanB = False while b != 0: footprint.append((a % b, 1, a, -(a//b), b)) # for each tuple in list footprint # footprint[i][0] == footprint [i][1] * footprint[i][2] # + footprint [i][3] * foorprint[i][4] # and # footprint[i][4] == footprint[i+1][0] # this two equations are key to generate the linear combination # of a and b so that the result will be their GCD (or GCF). a, b = b, a % b # Start work backward to compute the linear combination # of a and b so that this combination gives the GCD of a and b footprint.reverse() footprint.pop(0) #print (footprint) x = footprint[0][1] y = footprint[0][3] #print (x, y) for i in range (1, len(footprint)): x_temp = x y_temp = y x = y_temp * footprint[i][1] y = y_temp * footprint[i][3] + x_temp #print (x, y) if (isASmallerThanB != True): return (a, x, y) else: return (a, y, x) def modInv(a,m): '''returns the multiplicative inverse of a in modulo m as a positve value between zero and m-1''' # notice that a and m need to co-prime to each other. if coprime([a, m]) == False: return 0 else: linearcombination = extendedEuclid(a, m) return linearcombination[1] % m def crt(L): '''takes in a list of two or more tuples, ie L = [(a0, n0), (a1,n1),(a2,n2)...(ak nk)] if the n-s are not co-prime, this function prints an error message to the screen and returns -1. Otherwise it continues with the Chinese Remainder theorem, finding a value for x to return which satisfies x = ai( mod ni) for all tuples in the list L. This value must be between 0 and N-1 where N is the product of all the n in the list L''' NList = [] for item in L: NList.append(item[1]) if coprime(NList) == False: print ("The input is not valid!") return -1 else: bigN = 1 for numbers in NList: bigN *= numbers CRTresult = 0 for item in L: ai = item[0] Ci = bigN//item[1] #print (Ni, ai) Yi = extendedEuclid(Ci, item[1]) #print (Ci, item[1]) CRTresult += ai * Ci * Yi[1] return CRTresult % bigN # start of second project ***************************** def extractTwos(m): '''m is a positive integer. A tuple (s, d) of integers is returned such that m = (2 ** s) * d.''' # the problem can be break down to count how many '0's are there in # the end of bin(m). This can be done this way: m & a stretch of '1's # which can be represent as (2 ** n) - 1. assert m >= 0 i = 0 while m & (2 ** i) == 0: i += 1 return (i, m >> i) def int2baseTwo(x): '''x is a positive integer. Convert it to base two as a list of integers in reverse order as a list.''' # repeating x >>= 1 and x & 1 will do the trick assert x >= 0 bitInverse = [] while x != 0: bitInverse.append(x & 1) x >>= 1 return bitInverse def modExp(a,d,n): '''returns a ** d (mod n)''' # a faster algorithms discussed in CIT 592 class assert d >= 0 assert n >= 0 base2D = int2baseTwo(d) base2DLength = len(base2D) modArray = [] result = 1 for i in range (1, base2DLength + 1): if i == 1: modArray.append(a % n) else: modArray.append((modArray[i - 2] ** 2) % n) for i in range (0, base2DLength): if base2D[i] == 1: result *= base2D[i] * modArray[i] return result % n def millerRabin(n, k): ''' Miller Rabin pseudo-prime test return True means likely a prime, (how sure about that, depending on k) return False means definitely a composite. Raise assertion error when n, k are not positive integers and n is not 1 ''' assert n >= 1 # ensure n is bigger than 1 assert k > 0 # ensure k is a positive integer so everything down here makes sense if n == 2: return True # make sure to return True if n == 2 if n % 2 == 0: return False # immediately return False for all the even numbers bigger than 2 extract2 = extractTwos(n - 1) s = extract2[0] d = extract2[1] assert 2 ** s * d == n - 1 def tryComposite(a): '''Inner function which will inspect whether a given witness will reveal the true identity of n. Will only be called within millerRabin''' x = modExp(a, d, n) if x == 1 or x == n - 1: return None else: for j in range (1,s): x = modExp(x, 2, n) if x == 1: return False elif x == n - 1: return None return False for i in range (0, k): a = random.randint(2, n - 2) if tryComposite(a) == False: return False return True # actually, we should return probably true. def primeSieve(k): '''return a list with length k + 1, showing if list[i] == 1, i is a prime else if list[i] == 0, i is a composite, if list[i] == -1, not defined''' def isPrime(n): '''return True is given number n is absolutely prime, return False is otherwise.''' for i in range(2, int(n ** 0.5) + 1): if n % i == 0: return False return True result = [-1] * (k + 1) for i in range(2, int(k + 1)): if isPrime(i): result[i] = 1 else: result[i] = 0 return result def findAPrime(a,b,k): '''Return a pseudo prime number roughly between a and b, (could be larger than b). Raise ValueError if cannot find a pseudo prime after 10 * ln(x) + 3 tries. ''' x = random.randint(a, b) for i in range(0, int(10 * math.log(x) + 3)): if millerRabin(x, k): return x else: x += 1 raise ValueError def newKey(a,b,k): ''' Try to find two large pseudo primes roughly between a and b. Generate public and private keys for RSA encryption. Raises ValueError if it fails to find one''' try: p = findAPrime(a, b, k) while True: q = findAPrime(a, b, k) if q != p: break except: raise ValueError n = p * q m = (p-1) * (q-1) while True: e = random.randint(1, m) if coprime([e, m]): break d = modInv(e, m) return (n, e, d) def string2numList(strn): '''Converts a string to a list of integers based on ASCII values''' # Note that ASCII printable characters range is 0x20 - 0x7E returnList = [] for chars in strn: returnList.append(ord(chars)) return returnList def numList2string(L): '''Converts a list of integers to a string based on ASCII values''' # Note that ASCII printable characters range is 0x20 - 0x7E returnList = [] returnString = '' for nums in L: returnString += chr(nums) return returnString def numList2blocks(L,n): '''Take a list of integers(each between 0 and 127), and combines them into block size n using base 256. If len(L) % n != 0, use some random junk to fill L to make it ''' # Note that ASCII printable characters range is 0x20 - 0x7E returnList = [] toProcess = copy.copy(L) if len(toProcess) % n != 0: for i in range (0, n - len(toProcess) % n): toProcess.append(random.randint(32, 126)) for i in range(0, len(toProcess), n): block = 0 for j in range(0, n): block += toProcess[i + j] << (8 * (n - j - 1)) returnList.append(block) return returnList def blocks2numList(blocks,n): '''inverse function of numList2blocks.''' toProcess = copy.copy(blocks) returnList = [] for numBlock in toProcess: inner = [] for i in range(0, n): inner.append(numBlock % 256) numBlock >>= 8 inner.reverse() returnList.extend(inner) return returnList def encrypt(message, modN, e, blockSize): '''given a string message, public keys and blockSize, encrypt using RSA algorithms.''' cipher = [] numList = string2numList(message) numBlocks = numList2blocks(numList, blockSize) for blocks in numBlocks: cipher.append(modExp(blocks, e, modN)) return cipher def decrypt(secret, modN, d, blockSize): '''reverse function of encrypt''' numBlocks = [] numList = [] for blocks in secret: numBlocks.append(modExp(blocks, d, modN)) numList = blocks2numList(numBlocks, blockSize) message = numList2string(numList) return message if __name__=='__main__': (n, e, d) = newKey(10**100, 10**101, 50) print ('n = {0}'.format(n)) print ('e = {0}'.format(e)) print ('d = {0}'.format(d)) message = '''We were the Leopards, the Lions, those who'll take our place will be little jackals, hyenas; But we'll go on thinking ourselves the salt of the earth.''' print(message) cipher = encrypt(message, n, e, 15) print(cipher) Amessage = decrypt(cipher, n, d, 15) print(Amessage)