# RSAtools.py                                      David MacQuigg 13-March-2010
'''
Python is great for crypto.
  1) Easy interactive environment for prototyping and experimentation.
  2) Long integers for public keys, etc.

Run this file in Python 2.6.  Try the commands in the >>> examples.
~'''

### Random Bits
from random import getrandbits

a,b,m = getrandbits(512), getrandbits(512), getrandbits(384)  # long integers
'''
>>> a
87638194511408989261438753250719754638828743912429765499507120091357674569882808
90862859998699808605307665820696568046132523175744106743803372585080828726L
>>> b
57579891920620594921553065324099857848201813159629630310669085501543819427295796
09887603084816533251318617299467986239404540879435342090928431485352784952L
>>> m
33980144669810108281160822352744739279623941703077092883034667556498921065193304
60680842427694402677672470050075321L
'''

### Huge exponentials like a ** b (mod m) are common in crypto systems.

exp = pow(abm)  # pow() is a function written in C - very fast.
'''
>>> pow(a, b, m)
26616164385017850397090293477494464399221960596510492575571803619978316656538353
42475518596170907523282061732994456L
'''

### Define functions

from simple_crypto import factorsfactorialprimesprimefactors,\
                          isPrimesieveinverse

from Crypto.Util.number import getPrime
from random import randint

def getPrimes(n1n2isPrime):
    ls = []
    for n in range(n1n2+12):
        if isPrime(n):
            ls.append(n)
    return ls

n1 = getPrime(256)
n2 = getPrime(256)
n3 = n1 * n2
n4 = getPrime(512)

def sieveTest(N):
    '''Sieve test only from simple_crypto.isPrime()'''
    if N <= 1return False
    if N in sievereturn True
    for i in sieve:
        if (N % i) == 0return False
    return True

def mrTest(N):
    '''Miller-Rabin test only, no sieve'''
    # Miller-Rabin algorithm (Stinson p.188)
    
    # Find m,k: m*2**k = N-1, with m odd.    # N   = 111001
    m,r = N-10                             # N-1 = 111000
    k = 0
    while (m & 1) == 0:                      # m & 1      0
        m,r = divmod(m2)                   # m,r    11100, 0
        k += 1                               # k          1

    a = randint(1N-1)
    b = pow(amN)  # a**m (mod N)
    if b == 1:
        return True
    for i in range(0k):
        if b == N-1:  # -1 (mod N)
            return True
        b = b*b % N
        
    return False


### RSA Example (Stinson p.174)
p = 101q = 113n = p*q  # 11413
phi = (p-1)*(q-1)          # 11200
b = 3533                           # public key
a = inverse(bphi)        # 6597  # private key
x = 9726                           # plaintext
y = pow(xbn)           # 5761  # ciphertext
z = pow(yan)           # 9726  # decrypted plaintext

def keydata(pqe):
    '''
    Given two large primes, and a public key e, return modulus n and
    private key d.
    '''
    n = p * q
    phi = (p-1) * (q-1)  # Euler function
    d = inverse(ephi)
    return (nd)


from Crypto.PublicKey import RSA
# from Crypto.Util.number import getPrime, getRandomNumber, isPrime

# Generate a 512-bit key pair as a private object
keys = RSA.generate(512)  # <_RSAobj @0x754328 n(512),e,d,p,q,u,private>
# The public part
kpub = keys.publickey()   # <_RSAobj @0x745788 n(512),e>
'''
>>> keys.n
10234627198605513639397634685673808088862885727436246123175195869546876043619\
177469648169969957996459717595131085472587737664700976414283898364959753144431L
>>> keys.e
65537L
>>> kpub.n
10234627198605513639397634685673808088862885727436246123175195869546876043619\
177469648169969957996459717595131085472587737664700976414283898364959753144431L
>>> kpub.e
65537L
>>> keys.d
25064584362668186507214556159889012287143036136129476521195949418836284923033\
48455100437453295920795995642901835947770124620525487363485041044782436782273L
>>> keys.p
96742629864732603418864512406761098475238631440988147476367753084012776627793L
>>> keys.q
105792319403718559888423419116790072822332865896274893402668847153102331071167L

>>> phi = (keys.p - 1) * (keys.q - 1)
>>> phi
10234627198605513639397634685673808088862885727436246123175195869546876043618\
974934698901518794689171786071579914175016240327437935535247298127844645445472L
>>> (keys.e * keys.d) % phi
1L
>>> keys.p * keys.q
10234627198605513639397634685673808088862885727436246123175195869546876043619\
177469648169969957996459717595131085472587737664700976414283898364959753144431L
>>> n,d = keydata(keys.p, keys.q, keys.e)
>>> n
10234627198605513639397634685673808088862885727436246123175195869546876043619\
177469648169969957996459717595131085472587737664700976414283898364959753144431L
>>> d
25064584362668186507214556159889012287143036136129476521195949418836284923033\
48455100437453295920795995642901835947770124620525487363485041044782436782273L

>>> x = 12345678987654
>>> y = pow(x, keys.e, keys.n)
>>> y
30265197677604831928111872062026166837484863311372420565956699732727257718633\
08128760539488324408005664686810761373457968796412747320091540601398665932855L
>>> z = pow(y, keys.d, keys.n)
>>> z
12345678987654L
'''