Cryptography!!

Asymetric and symmetric

in transit and at rest


In [1]:
100 % 9


Out[1]:
1

In [2]:
(5**3) % 17


Out[2]:
6
$$ a = g^{b} \text{mod } p $$

In [8]:
import random
random.randint(0, 100)


Out[8]:
59

In [9]:
import os
 
def rand_int(nbytes):
    return int.from_bytes(os.urandom(nbytes), byteorder='little')

rand_int(50)


Out[9]:
127655184965292357528834588254369011680986639399801774380053531243130111608082697977683130879832513622690818970927896968

In [14]:
def rand_less_than(upper_bound):
    while True:
        r = rand_int(((upper_bound).bit_length() + 7) // 8)
        if r < upper_bound:
            return r

def is_prime(p):
    for _ in range(5): # do this 5 times
        a = rand_less_than(p)  # picks a number smaller than 
        if not pow(a, p - 1, p) == 1: # a**(p - 1) % p == 1
            return False
    return True

In [17]:
is_prime(233)


Out[17]:
True

In [18]:
# alice and bob are choose a big prime p, and a base g
# alice choose a secret called 'a'
# bob chooose a secret called 'b'
# alices sends g**a % p = A
# bob sends g**b % p = B
# alice calculates B**a
# bob calculates A**b

In [19]:
# A = g**a %p, b 
# A**b -> (g**a)**b % p

In [21]:
def choose_parameters():
    while True:
        modulus = rand_int(1024 // 8)
        if is_prime(modulus):
            break
    base = rand_less_than(modulus)
    return base, modulus

In [23]:
g, p = choose_parameters()

In [25]:
class Peep:
    def __init__(self, base, modulus): # g, p
        self.base = base
        self.modulus = modulus
        self.private = rand_less_than(modulus)
        self.public = pow(base, self.private, modulus)
 
    def send(self):
        return self.public
 
    def receive(self, B):
        self.shared_secret = pow(B, self.private, self.modulus)

In [28]:
alice = Peep(g, p)
bob = Peep(g, p)
A = alice.send()
B = bob.send()
A, B


Out[28]:
(24884367485109881412398240459388202132430510874214116392826216896961808112532396722940032373483868378904805908462916890862520265237205108581293708361151486941372475305342247210458232831379436683178003919586769280726687382268327889799124403070326934672334549576363198524738244651326038281841416767666246730655,
 123451532448179571111552285970321301090204456573277260185353415694384377333932310956418829246786739456896201533302942646394596942008383042519290721997220596110753176868150107032286884632491108153922711247397244185857059590918763005346644626176150984536255017479930078125497612205809491374834047297775179390262)

In [29]:
bob.receive(A)
alice.receive(B)

In [30]:
alice.shared_secret, bob.shared_secret


Out[30]:
(98154807023808799859686391310632953640759958498387740789147814164993025124815305150197247517371956411339653685498422232379968612824088824431083307094109584364005421957478064216759538663523548369701059838612432800624511234894755816581827253236165243308738881594899993978365389892050969762960675131189982434863,
 98154807023808799859686391310632953640759958498387740789147814164993025124815305150197247517371956411339653685498422232379968612824088824431083307094109584364005421957478064216759538663523548369701059838612432800624511234894755816581827253236165243308738881594899993978365389892050969762960675131189982434863)

In [ ]:
http://pastebin.com/7QARWsF0

In [31]:
from hashlib import sha256

In [35]:
hasher = sha256()

In [38]:
hasher.update('bad stuff'.encode('ascii'))

In [39]:
hasher.update('cuss words'.encode('ascii'))

In [40]:
hasher.digest()


Out[40]:
b'\xe0r~\xb1-\x80\x92\xcc\xcc<}\xbb3\x99\x11\xe0yY\xc4\x07\x90\xd8\xfdv\xb68_\x97\xf2\xc3\x16\x9b'

In [41]:
(2**8)**20


Out[41]:
1461501637330902918203684832716283019655932542976

In [43]:
import math
math.log10(1461501637330902918203684832716283019655932542976)


Out[43]:
48.16479930623699