Python Public Key Encryption (RSA)

From , 5 Years ago, written in Python, viewed 86 times.
URL https://pastebin.vip/view/d0f4dae8
  1. # coding=utf-8
  2. from __future__ import division, absolute_import, print_function
  3. from base64 import b64encode
  4. from fractions import gcd
  5. from random import randrange
  6. from collections import namedtuple
  7. from math import log
  8. from binascii import hexlify, unhexlify
  9. import sys
  10.  
  11.  
  12. PY3 = sys.version_info[0] == 3
  13. if PY3:
  14.     binary_type = bytes
  15.     range_func = range
  16. else:
  17.     binary_type = str
  18.     range_func = xrange
  19.  
  20.  
  21. def is_prime(n, k=30):
  22.     # http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
  23.     if n <= 3:
  24.         return n == 2 or n == 3
  25.     neg_one = n - 1
  26.  
  27.     # write n-1 as 2^s*d where d is odd
  28.     s, d = 0, neg_one
  29.     while not d & 1:
  30.         s, d = s + 1, d >> 1
  31.     assert 2 ** s * d == neg_one and d & 1
  32.  
  33.     for _ in range_func(k):
  34.         a = randrange(2, neg_one)
  35.         x = pow(a, d, n)
  36.         if x in (1, neg_one):
  37.             continue
  38.         for _ in range_func(s - 1):
  39.             x = x ** 2 % n
  40.             if x == 1:
  41.                 return False
  42.             if x == neg_one:
  43.                 break
  44.         else:
  45.             return False
  46.     return True
  47.  
  48.  
  49. def randprime(n=10 ** 8):
  50.     p = 1
  51.     while not is_prime(p):
  52.         p = randrange(n)
  53.     return p
  54.  
  55.  
  56. def multinv(modulus, value):
  57.     """
  58.        Multiplicative inverse in a given modulus
  59.  
  60.        >>> multinv(191, 138)
  61.        18
  62.        >>> multinv(191, 38)
  63.        186
  64.        >>> multinv(120, 23)
  65.        47
  66.    """
  67.     # http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
  68.     x, lastx = 0, 1
  69.     a, b = modulus, value
  70.     while b:
  71.         a, q, b = b, a // b, a % b
  72.         x, lastx = lastx - q * x, x
  73.     result = (1 - lastx * modulus) // value
  74.     if result < 0:
  75.         result += modulus
  76.     assert 0 <= result < modulus and value * result % modulus == 1
  77.     return result
  78.  
  79.  
  80. KeyPair = namedtuple('KeyPair', 'public private')
  81. Key = namedtuple('Key', 'exponent modulus')
  82.  
  83.  
  84. def keygen(n, public=None):
  85.     """ Generate public and private keys from primes up to N.
  86.  
  87.    Optionally, specify the public key exponent (65537 is popular choice).
  88.  
  89.        >>> pubkey, privkey = keygen(2**64)
  90.        >>> msg = 123456789012345
  91.        >>> coded = pow(msg, *pubkey)
  92.        >>> plain = pow(coded, *privkey)
  93.        >>> assert msg == plain
  94.  
  95.    """
  96.     # http://en.wikipedia.org/wiki/RSA
  97.     prime1 = randprime(n)
  98.     prime2 = randprime(n)
  99.     composite = prime1 * prime2
  100.     totient = (prime1 - 1) * (prime2 - 1)
  101.     if public is None:
  102.         private = None
  103.         while True:
  104.             private = randrange(totient)
  105.             if gcd(private, totient) == 1:
  106.                 break
  107.         public = multinv(totient, private)
  108.     else:
  109.         private = multinv(totient, public)
  110.     assert public * private % totient == gcd(public, totient) == gcd(private, totient) == 1
  111.     assert pow(pow(1234567, public, composite), private, composite) == 1234567
  112.     return KeyPair(Key(public, composite), Key(private, composite))
  113.  
  114.  
  115. def encode(msg, pubkey, verbose=False):
  116.     chunksize = int(log(pubkey.modulus, 256))
  117.     outchunk = chunksize + 1
  118.     outfmt = '%%0%dx' % (outchunk * 2,)
  119.     bmsg = msg if isinstance(msg, binary_type) else msg.encode('utf-8')
  120.     result = []
  121.     for start in range_func(0, len(bmsg), chunksize):
  122.         chunk = bmsg[start:start + chunksize]
  123.         chunk += b'\x00' * (chunksize - len(chunk))
  124.         plain = int(hexlify(chunk), 16)
  125.         coded = pow(plain, *pubkey)
  126.         bcoded = unhexlify((outfmt % coded).encode())
  127.         if verbose:
  128.             print('Encode:', chunksize, chunk, plain, coded, bcoded)
  129.         result.append(bcoded)
  130.     return b''.join(result)
  131.  
  132.  
  133. def decode(bcipher, privkey, verbose=False):
  134.     chunksize = int(log(privkey.modulus, 256))
  135.     outchunk = chunksize + 1
  136.     outfmt = '%%0%dx' % (chunksize * 2,)
  137.     result = []
  138.     for start in range_func(0, len(bcipher), outchunk):
  139.         bcoded = bcipher[start: start + outchunk]
  140.         coded = int(hexlify(bcoded), 16)
  141.         plain = pow(coded, *privkey)
  142.         chunk = unhexlify((outfmt % plain).encode())
  143.         if verbose:
  144.             print('Decode:', chunksize, chunk, plain, coded, bcoded)
  145.         result.append(chunk)
  146.     return b''.join(result).rstrip(b'\x00').decode('utf-8')
  147.  
  148.  
  149. def key_to_str(key):
  150.     """
  151.    Convert `Key` to string representation
  152.    >>> key_to_str(Key(50476910741469568741791652650587163073, 95419691922573224706255222482923256353))
  153.    '25f97fd801214cdc163796f8a43289c1:47c92a08bc374e96c7af66eb141d7a21'
  154.    """
  155.     return ':'.join((('%%0%dx' % ((int(log(number, 256)) + 1) * 2)) % number) for number in key)
  156.  
  157.  
  158. def str_to_key(key_str):
  159.     """
  160.    Convert string representation to `Key` (assuming valid input)
  161.    >>> (str_to_key('25f97fd801214cdc163796f8a43289c1:47c92a08bc374e96c7af66eb141d7a21') ==
  162.    ...  Key(exponent=50476910741469568741791652650587163073, modulus=95419691922573224706255222482923256353))
  163.    True
  164.    """
  165.     return Key(*(int(number, 16) for number in key_str.split(':')))
  166.  
  167.  
  168. def main():
  169.     import doctest
  170.     print(doctest.testmod())
  171.  
  172.     pubkey, privkey = keygen(2 ** 64)
  173.     msg = u'the quick brown fox jumped over the lazy dog ® ⌀'
  174.     h = encode(msg, pubkey, True)
  175.     p = decode(h, privkey, True)
  176.     print('-' * 20)
  177.     print('message:', msg)
  178.     print('encoded:', b64encode(h).decode())
  179.     print('decoded:', p)
  180.     print('private key:', key_to_str(privkey))
  181.     print('public key:', key_to_str(pubkey))
  182.  
  183. if __name__ == '__main__':
  184.     main()
  185.  
  186.  
  187.  
  188. #//python/8981

Reply to "Python Public Key Encryption (RSA)"

Here you can reply to the paste above

captcha

https://burned.cc - Burn After Reading Website