Advertisement
Guest User

Untitled

a guest
Apr 19th, 2014
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.46 KB | None | 0 0
  1. import random
  2. import math
  3. import sys
  4. import struct
  5.  
  6.  
  7.  
  8. class RSA(object):
  9.     """
  10.    To generate RSA keypair we need to follow these steps:
  11.    1. Find two large enough prime numbers, preferably of equal bytelength, p and q.
  12.    2. Calculate modulo (p * q), it will be the common part of both private and public key.
  13.    3. Calculate totient of p and q, also known as Euler function: phi(p, q) = (p-1)*(q-1).
  14.    4. Find coprime number to totient and use it as public exponent, therefore completing public key.
  15.       It can be achieved by checking elements of first 100 primes (starting from 17 for security) to have GCD = 1 with totient.
  16.       If so, it means that these numbers are coprime. We'll use extended Euclidian algorithm.
  17.    5. To generate private exponent, we need to find modular inverse of e modulo totient with help of EEA.
  18.    """
  19.    
  20.     LowPrimes =   [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97
  21.                    ,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179
  22.                    ,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269
  23.                    ,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367
  24.                    ,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461
  25.                    ,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571
  26.                    ,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661
  27.                    ,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773
  28.                    ,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883
  29.                    ,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]
  30.  
  31.  
  32.     def RabinMillerTest(self, n):
  33.         #Miller-Rabin non-determnisctic test for primacy
  34.         s = n - 1
  35.         t = 0
  36.         #Rewriting n as (2**s)*t
  37.         while s & 1 == 0:
  38.             s = s / 2
  39.             t += 1
  40.         k = 0
  41.         while k < 128: #Selecting depth of primacy test. With k < 128, probability of n not being prime is r**(-126)
  42.             a = random.randrange(2, n - 1)
  43.             v = pow(a, s, n) #Very fast C hook - equal to a**s mod n
  44.             if v != 1:
  45.                 i = 0
  46.                 while v != (n - 1):
  47.                     if i == t - 1:
  48.                         return False
  49.                     else:
  50.                         i = i + 1
  51.                         v = pow(v, 2, n)
  52.             k += 2
  53.         return True
  54.  
  55.     def IsNumberPrime(self,n):
  56.         #Checking number for primacy. To decrease computation time we'll check first 100 primes as divisors to n.
  57.         if (n >= 3):
  58.             if (n & 1 != 0): #We don't intrested in even numbers
  59.                 for p in self.LowPrimes:
  60.                     if (n == p):
  61.                         return True
  62.                     if (n % p == 0):
  63.                         return False
  64.                 return self.RabinMillerTest(n)
  65.         return False
  66.  
  67.     def GeneratePrime(self,k):
  68.         r = 100 * (math.log(k, 2) + 1)
  69.         r_ = r
  70.         while r > 0:
  71.             n = random.randrange(2**(k-1),2**(k))
  72.             r -= 1
  73.             if self.IsNumberPrime(n) == True:
  74.                 return n
  75.         return "Failed after "+str(r_)+" tries."
  76.  
  77.     def Totient(self,p,q):
  78.         return (p-1)*(q-1)
  79.  
  80.     def ExtendedEuclidian(self,a,b):
  81.         x, y,  u, v = 0, 1,  1, 0
  82.         while a!=0:
  83.             q, r = b//a, b%a
  84.             m, n = x - u*q, y - v*q
  85.             b, a, x, y, u, v = a, r, u, v, m, n
  86.         gcd = b
  87.         return gcd, x, y    
  88.  
  89.     def ModuloInversion(self,a,m):
  90.         gcd, x, y = self.ExtendedEuclidian(a, m)
  91.         if gcd != 1:
  92.             return None
  93.         else:
  94.             return x % m
  95.  
  96.     def GenerateKeypair(self, keylength):
  97.         if keylength % 2 != 0 or keylength > 2048:
  98.             print "Invalid key length (not even or too big)"
  99.             return None
  100.         else:
  101.             print "OK. Generating keypair, keylength = " + str(keylength)+ " bits."
  102.         keylength = keylength / 2
  103.         print "Generating p and q"
  104.         p = self.GeneratePrime(keylength)
  105.         q = self.GeneratePrime(keylength)
  106.         print "Calculating n..."
  107.         n = p * q
  108.         print "Calculating totient..."
  109.         phi = self.Totient(p,q)
  110.         print "Calculating e..."
  111.         e = 0
  112.         for prime in self.LowPrimes[5:]:
  113.             if self.ExtendedEuclidian(prime,phi)[0]==1:
  114.                 e = prime
  115.                 break
  116.         print "Calculating d..."
  117.         d = self.ModuloInversion(e, phi)
  118.         PubKey = (e, n)
  119.         PrivKey = (d, n)
  120.         self.WriteKey("public.txt", PubKey)
  121.         self.WriteKey("private.txt", PrivKey)
  122.         print "Keypair generated and saved."
  123.  
  124.     def WriteKey(self, filename, (exponent, modulo)):
  125.         exponent = hex(exponent)[2:]
  126.         if exponent[-1] == "L":
  127.             exponent = exponent[:-1]
  128.            
  129.         modulo = hex(modulo)[2:]
  130.         if modulo[-1] == "L":
  131.             modulo = modulo[:-1]
  132.  
  133.         keytostr = exponent+":"+modulo
  134.            
  135.         with open(filename, 'w') as f:
  136.             f.write(keytostr)
  137.  
  138.     def ReadKey(self, filename):
  139.         with open(filename, 'r') as f:
  140.             strtokey = f.read().split(':')
  141.             exponent = int(strtokey[0],16)
  142.             modulo = int(strtokey[1],16)
  143.             return exponent, modulo
  144.    
  145.  
  146.     def Encode(self, pubkeypath, filepath):
  147.         exponent, modulo = self.ReadKey(pubkeypath)
  148.         keylen = (len(bin(modulo))-2)/8
  149.         chunksize = keylen - 1
  150.        
  151.         with open(filepath, 'rb') as f:
  152.             filecontent = f.read()
  153.  
  154.         #Break file in chunks sized keylen/8 - 1 to encode'
  155.         chunks , lastsize = self.Chunker(filecontent, chunksize)
  156.            
  157.         #Encode:
  158.         processedchunks = [pow(chunks[x],exponent, modulo) for x in xrange(len(chunks))]
  159.         processedcontent = self.DechunkerEnc(processedchunks, chunksize)
  160.  
  161.         header = "SNKKZRSA"+str(lastsize)+'&&&&&&&&&&'
  162.         with open(filepath, 'wb') as f:
  163.             f.write(header+processedcontent)
  164.  
  165.  
  166.     def Decode(self, privkeypath, filepath):
  167.         exponent, modulo = self.ReadKey(privkeypath)
  168.         keylen = (len(bin(modulo))-2)/8
  169.         chunksize = keylen
  170.        
  171.         with open(filepath, 'rb') as f:
  172.             filecontent = f.read()
  173.  
  174.         #Extract header
  175.         headerstop=filecontent.find("&&&&&&&&&&")
  176.         header = filecontent[:headerstop+10]
  177.         lastsize = int(header[8:-10])
  178.         filecontent=filecontent[headerstop+10:]
  179.        
  180.         #Break file in chunks sized keylen/8  to decode'
  181.         chunks = self.Chunker(filecontent, chunksize)[0]
  182.            
  183.         #Decode:
  184.         processedchunks = [pow(chunks[x],exponent, modulo) for x in xrange(len(chunks))]
  185.         processedcontent = self.DechunkerDec(processedchunks, chunksize, lastsize)
  186.  
  187.         with open(filepath, 'wb') as f:
  188.             f.write(processedcontent)        
  189.        
  190.  
  191.                
  192.     def Chunker(self, st, chunksize):
  193.         chunks = [st[x:x+chunksize] for x in xrange(0,len(st),chunksize)]
  194.         intchunks = [int(chunks[x].encode('hex'), 16) for x in xrange(len(chunks))]
  195.         return intchunks, len(chunks[-1])
  196.  
  197.     def DechunkerEnc(self, chunks, chunksize):
  198.         chunksize += 1
  199.         hexchunks = [hex(chunks[x])[2:] for x in xrange(len(chunks))]
  200.        
  201.         for x in xrange(len(hexchunks)):
  202.             if hexchunks[x][-1] == "L":
  203.                 hexchunks[x] = hexchunks[x][:-1]
  204.             if len(hexchunks[x])<chunksize*2:
  205.                 hexchunks[x] = '0'*((chunksize*2)-len(hexchunks[x])) + hexchunks[x]
  206.         dechunked = ''
  207.         for x in xrange(len(hexchunks)):
  208.             dechunked+=hexchunks[x].decode('hex')
  209.        
  210.         return dechunked
  211.  
  212.     def DechunkerDec(self, chunks, chunksize, lastsize):
  213.         chunksize -= 1
  214.         hexchunks = [hex(chunks[x])[2:] for x in xrange(len(chunks))]
  215.  
  216.         for x in xrange(len(hexchunks)):
  217.             if hexchunks[x][-1] == "L":
  218.                 hexchunks[x] = hexchunks[x][:-1]
  219.                
  220.         for x in xrange(len(hexchunks)-1):
  221.             if len(hexchunks[x])<chunksize*2:
  222.                 hexchunks[x] = '0'*((chunksize*2)-len(hexchunks[x])) + hexchunks[x]
  223.  
  224.         if len(hexchunks[-1]) < lastsize*2:
  225.             hexchunks[-1]='0'*((lastsize*2)-len(hexchunks[-1]))+hexchunks[-1]
  226.              
  227.        
  228.         dechunked = ''
  229.         for x in xrange(len(hexchunks)):
  230.             dechunked+=hexchunks[x].decode('hex')
  231.        
  232.         return dechunked
  233.            
  234.        
  235.  
  236.  
  237. usage = "RSA cipherer and key generator. \nUsage:\n     RSA2.py generate <keylength> - generate key pair.\n     RSA2.py encrypt <public key file> <file to encrypt> - Encrypt a file.\n     RSA2.py decrypt <private key file> <file to decrypt> - Decrypt a file."
  238.  
  239. asymmetrical = RSA()
  240.  
  241. if len(sys.argv) < 2 or len(sys.argv) > 4 or sys.argv[1] == 'help':
  242.     print usage
  243.  
  244. try:
  245.     if sys.argv[1] == 'generate':
  246.         keylen=int(sys.argv[2])
  247.         asymmetrical.GenerateKeypair(keylen)
  248.         quit()
  249.     elif sys.argv[1] == 'encrypt':
  250.         keypath=sys.argv[2]
  251.         filepath=sys.argv[3]
  252.         asymmetrical.Encode(keypath,filepath)
  253.         quit()
  254.     elif sys.argv[1] == 'decrypt':
  255.         keypath=sys.argv[2]
  256.         filepath=sys.argv[3]
  257.         asymmetrical.Decode(keypath,filepath)
  258.         quit()
  259. except IndexError:
  260.     print "Invalid parameters"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement