Differences between revisions 75 and 121 (spanning 46 versions)
Revision 75 as of 2019-08-09 18:58:53
Size: 37856
Editor: amy
Comment:
Revision 121 as of 2019-08-09 22:04:04
Size: 61191
Editor: amy
Comment:
Deletions are marked like this. Additions are marked like this.
Line 5: Line 5:
This page was first created at Sage Days 103, 7-9 August 2019 by Sarah Arpin, Catalina Camacho-Navarro, Holly Paige Chaos, Amy Feaver, Eva Goedhart, Rebecca Lauren Miller, Alexis Newton, and Nandita Sahajpal. Text edited by Holly Paige Chaos, Amy Feaver, Eva Goedhart, and Alexis Newton. This project was led by Amy Feaver. This page was first created at Sage Days 103, 7-9 August 2019 by Sarah Arpin, Catalina Camacho-Navarro, Holly Paige Chaos, Amy Feaver, Eva Goedhart, Sara Lapan, Rebecca Lauren Miller, Alexis Newton, and Nandita Sahajpal. Text edited by Holly Paige Chaos, Amy Feaver, Eva Goedhart, and Alexis Newton. This project was led by Amy Feaver and Eva Goedhart.
Line 29: Line 29:
print "Put your message inside the provided quotes (with no additional quotes or apostrophes!), and select your desired shift: "
@interact
def shift_cipher(message = input_box(default='"secrets"', width = 50), shift=slider(0,25,1,3)):
pretty_print(html("<h>Put your message inside the provided quotes (with no additional quotes or apostrophes!), and select your desired shift:<h>"))
@interact
def shift_cipher(message = input_box(default='"secrets"',label="Message:"), shift=slider(0,25,1,3,label="Shift by:")):
Line 36: Line 36:
    print "This is your encrypted text shifted by ",shift,":"     print "This is your encrypted text shifted by",shift,":"
Line 50: Line 50:
print "Enter the encrypted text in quotes, and enter a guess for the shift amount:"
@interact
def shift_decrypt(text = input_box('"KL"'), shift_by = input_box(0)):
pretty_print(html("<h>Enter the encrypted text in quotes, and enter a guess for the shift amount:<h>"))
@interact
def shift_decrypt(text = input_box(default='"KL"',label="Message:"), shift_by = input_box(default = 0, label="Shift by:")):
Line 59: Line 59:
    print "These are the possibilities for the plaintext:"     print "\nThese are the possibilities for the plaintext:"
Line 62: Line 62:
    print "These are the possibilities ranked by likelihood with the chi-squared function:"     print "\nThese are the possibilities ranked by likelihood with the chi-squared function:"
Line 82: Line 82:
def affine_cipher(message = input_box(default='"secrets"', width = 50), a=[1,3,5,7,9,11,15,17,19,21,23], b =[0..25]): def affine_cipher(message = input_box(default='"secrets"', label="Message:"), a=[1,3,5,7,9,11,15,17,19,21,23], b =[0..25]):
Line 102: Line 102:
def shift_decrypt(text = input_box('"XNSILPCVA"'), a=[1,3,5,7,9,11,15,17,19,21,23,25], b =[0..25]): def shift_decrypt(text = input_box('"XNSILPCVA"', label="Message:"), a=[1,3,5,7,9,11,15,17,19,21,23,25], b =[0..25]):
Line 123: Line 123:

pretty_print(html('<h1> Substitution Cipher'))
print "Select your letter substitutions and enter your message in quotes."
from string import ascii_uppercase
left_over_letters=[0] +[let for let in ascii_uppercase]
@interact
def _(A =selector(left_over_letters, default=0)):
    if A!=0:
        left_over_letters.remove(A)
 # print left_over_letters
    
        @interact
        def _(B =selector(left_over_letters, default=0)):
            if B!=0:
                left_over_letters.remove(B)
 # print left_over_letters
        
                @interact
                def _(C =selector(left_over_letters, default=0)):
                    if C!=0:
                        left_over_letters.remove(C)
                        @interact
                        def _(D =selector(left_over_letters, default=0)):
                            if D!=0:
                                left_over_letters.remove(D)
                                @interact
                                def _(E =selector(left_over_letters, default=0)):
                                    if E!=0:
                                        left_over_letters.remove(E)

                                        @interact
                                        def _(F =selector(left_over_letters, default=0)):
                                            if F!=0:
                                                left_over_letters.remove(F)

                                                @interact
                                                def _(G =selector(left_over_letters, default=0)):
                                                    if G!=0:
                                                        left_over_letters.remove(G)

                                                        @interact
                                                        def _(H =selector(left_over_letters, default=0)):
                                                            if H!=0:
                                                                left_over_letters.remove(H)

                                                                @interact
                                                                def _(I =selector(left_over_letters, default=0)):
                                                                    if I!=0:
                                                                        left_over_letters.remove(I)

                                                                        @interact
                                                                        def _(J =selector(left_over_letters, default=0)):
                                                                            if J!=0:
                                                                                left_over_letters.remove(J)

                                                                                @interact
                                                                                def _(K =selector(left_over_letters, default=0)):
                                                                                    if K!=0:
                                                                                        left_over_letters.remove(K)
                                                                                        @interact
                                                                                        def _(L =selector(left_over_letters, default=0)):
                                                                                            if L!=0:
                                                                                                left_over_letters.remove(L)

                                                                                                @interact
                                                                                                def _(M =selector(left_over_letters, default=0)):
                                                                                                    if M!=0:
                                                                                                        left_over_letters.remove(M)

                                                                                                        @interact
                                                                                                        def _(N =selector(left_over_letters, default=0)):
                                                                                                            if N!=0:
                                                                                                                left_over_letters.remove(N)

                                                                                                                @interact
                                                                                                                def _(O =selector(left_over_letters, default=0)):
                                                                                                                    if O!=0:
                                                                                                                        left_over_letters.remove(O)

                                                                                                                        @interact
                                                                                                                        def _(P =selector(left_over_letters, default=0)):
                                                                                                                            if P!=0:
                                                                                                                                left_over_letters.remove(P)

                                                                                                                                @interact
                                                                                                                                def _(Q =selector(left_over_letters, default=0)):
                                                                                                                                    if Q!=0:
                                                                                                                                        left_over_letters.remove(Q)


                                                                                                                                        @interact
                                                                                                                                        def _(R =selector(left_over_letters, default=0)):
                                                                                                                                            if R!=0:
                                                                                                                                                left_over_letters.remove(R)

                                                                                                                                                @interact
                                                                                                                                                def _(S =selector(left_over_letters, default=0)):
                                                                                                                                                    if S!=0:
                                                                                                                                                        left_over_letters.remove(S)

                                                                                                                                                        @interact
                                                                                                                                                        def _(T =selector(left_over_letters, default=0)):
                                                                                                                                                            if T!=0:
                                                                                                                                                                left_over_letters.remove(T)

                                                                                                                                                                @interact
                                                                                                                                                                def _(U =selector(left_over_letters, default=0)):
                                                                                                                                                                    if U!=0:
                                                                                                                                                                        left_over_letters.remove(U)

                                                                                                                                                                        @interact
                                                                                                                                                                        def _(V =selector(left_over_letters, default=0)):
                                                                                                                                                                            if V!=0:
                                                                                                                                                                                left_over_letters.remove(V)

                                                                                                                                                                                @interact
                                                                                                                                                                                def _(W =selector(left_over_letters, default=0)):
                                                                                                                                                                                    if W!=0:
                                                                                                                                                                                        left_over_letters.remove(W)

                                                                                                                                                                                        @interact
                                                                                                                                                                                        def _(X =selector(left_over_letters, default=0)):
                                                                                                                                                                                            if X!=0:
                                                                                                                                                                                                left_over_letters.remove(X)

                                                                                                                                                                                                @interact
                                                                                                                                                                                                def _(Y =selector(left_over_letters, default=0)):
                                                                                                                                                                                                    if Y!=0:
                                                                                                                                                                                                        left_over_letters.remove(Y)

                                                                                                                                                                                                        @interact
                                                                                                                                                                                                        def _(Z =selector(left_over_letters, default=0)):
                                                                                                                                                                                                            if Z!=0:
                                                                                                                                                                                                                left_over_letters.remove(Z)




                                                                                                                                                                                                                @interact
                                                                                                                                                                                                                def _(text=input_box(default='"MESSAGE"',label="Message:")):
                                                                                                                                                                                                                    new_ordering=[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z];
                                                                                                                                                                                                                    new_key=[ord(new_ordering[i])-65 for i in range(26)]
                                                                                                                                                                                                                    alphabet=AlphabeticStrings()
                                                                                                                                                                                                                    Es=SubstitutionCryptosystem(alphabet)
                                                                                                                                                                                                                    Key = alphabet(new_key)
                                                                                                                                                                                                                    e = Es(Key)
                                                                                                                                                                                                                    TEXT0=text
                                                                                                                                                                                                                    TEXT=alphabet.encoding(TEXT0)
                                                                                                                                                                                                                    print "Ciphertext:", e(TEXT)
Line 133: Line 279:

=== Playfair Encryption ===

Use this interact to encrypt a message using the playfair cipher.
Line 211: Line 361:
def _(Message=input_box(default="'message'"),Key=input_box(default="'key'"),showmatrix=checkbox(True, label='Show polybius square')): def _(Message=input_box(default='"message"', label="Message:"),Key=input_box(default='"key"', label="Key:"),showmatrix=checkbox(True, label='Show polybius square:')):
Line 322: Line 472:
print 'Playfair cipher decryption' pretty_print(html("<h1>Playfair Cipher Decryptor</h1>"))
Line 326: Line 476:
def _(Ciphertext=input_box(default="'Ciphertext'"),Key=input_box(default="'key'", label='Guess key'),showmatrix=checkbox(True, label='Show polybius square')): def _(Ciphertext=input_box(default='"LYXAXGDA"', label="Message:"),Key=input_box(default='"key"', label='Guess key:'),showmatrix=checkbox(True, label='Show polybius square:')):
Line 380: Line 530:
This interact prints a suggested translation of the input text by matching frequencies of letters in the input to frequencies of letters in the English language. With the output you will see that some letters were substituted in correctly, and others were not. Usually frequency analysis requires additional work and some trial and error to discover the original message, especially if the input text is not long enough. This interact prints a suggested translation of the input text by matching frequencies of letters in the input to frequencies of letters in the English language. With the output you will see that some letters were substituted incorrectly, and others were not. Usually frequency analysis requires additional work and some trial and error to discover the original message, especially if the input text is not long enough.
Line 414: Line 564:
Use this interact to encrypt a message using the Vigenère Cipher.
Line 417: Line 569:
Use this interact to encrypt a message using the Vigenère Cipher.
Line 458: Line 609:
One-time pad is an encryption method that cannot be cracked, but requires a single-use shared key (known as a one-time pad) the length of the message or longer. In this method, every letter in the message is first converted to numbers using the standard A=0, B=1, C=2, etc. Then each character in the message is multiplied modulo 26 by the number in the corresponding position in the key. This is then converted back to letters to produce the encrypted text. One-time pad is an encryption method that cannot be cracked. It requires a single-use shared key (known as a one-time pad) the length of the message or longer. In this method, every letter is first converted to numbers using the standard A=0, B=1, C=2, etc. Then each character in the message is multiplied modulo 26 by the number in the corresponding position in the key. This is then converted back to letters to produce the encrypted text.
Line 495: Line 646:
The Hill cipher requires some basic knowledge of Linear Algebra. In this encryption method, an invertible n x n matrix of integers modulo 26 is used as the key. The message is first converted to numbers and spit into chunks size n. These chunks are then converted to n x 1 vectors and multiplied by the key modulo 26 to produce 1 x n vectors. The integers from these vectors are converted back letters to produce the encrypted text.
Line 499: Line 651:
Use this interact to encrypt a message with the Hill cipher. Be sure to use an invertible matrix so that your message can be decrypted!
Line 501: Line 655:
print "Please input the size of your key:" pretty_print(html("<h1>Hill Cipher Encryptor</h1>"))
print "Please select the size of your key:"
print " "
Line 564: Line 720:
Use this interact to decrypt messages encrypted by the Hill cipher. Remember that this only works if the message was encrypted using an invertible matrix as the key!
Line 571: Line 729:
print " "
Line 668: Line 827:
This section gives visual representations of the modular arithmetic necessary for RSA, Diffie-Hellman, and El Gamal.
Line 675: Line 834:
Given a positive integer n, this prints the multiplication mod n. Each entry in this table corresponds to the product of the row number by the column number, modulo n.
Line 677: Line 838:
pretty_print(html("<h1>Multiplication Table modulo n</h1>"))
Line 685: Line 847:

=== Modular Exponentiation ===

by Rebecca Lauren Miller, Kate Stange

Given a modulus n and a nonnegative exponent a, this displays a graph where each integer between 0 and n-1 is mapped to its a-th power, mod n.

{{{#!sagecell
#Last edited 8/9/19 at 2:46pm
pretty_print(html("<h1>Arrow Diagram modulo n</h1>"))
print "Input your modulus, 𝑛, and an integer, 𝑎. The output will be an arrow diagram picture of 𝑥↦𝑎𝑥 on the ring ℤ/𝑛ℤ, i.e. the elements modulo 𝑛."
@interact
def modular_multiplication_graph(n = input_box(default = 7, width = 25), a = input_box(default = 2, width = 25)):
    R = IntegerModRing(n)
    left=[' '+str(r)+' ' for r in R]
    right=[' '+str(r)+' ' for r in R]
    pre_pos=graphs.CompleteBipartiteGraph(len(left),len(right)).get_pos()
    G = DiGraph()
    pos={}
    for (i,v) in enumerate(left+right):
        G.add_vertex(v)
        pos[v]=pre_pos[i]
    for l in range(n):
        G.add_edge(left[l],right[lift(R(a*l))])
    show(G.plot(pos=pos))
}}}


=== Discrete Log Problem ===
by Sara Lapan

The discrete logarithm, log(x) with base a, is an integer b such that a^b^ = x. Computing logarithms is computationally difficult, and there are no efficient algorithms known for the worst case scenarios. However, the discrete exponentiation is comparatively simple (for instance, it can be done efficiently using squaring). This asymmetry in complexity has been exploited in constructing cryptographic systems. Typically, it is much easier to solve for x in x = a^b^ (mod m) when a, b, and m are known, than it is to solve for b when x, a, and m are known.

==== Solving for x ====

Interact to find x when a, b, and m are known:

{{{#!sagecell
pretty_print(html("<h1>Solving for x</h1>"))
print('This will evaluate x=a^b (mod m). Choose your base (a), exponent (b), and modulus (m). These should all be positive integers.')
@interact
def DLP_solve(a=input_box(default=5),b=input_box(default=25),m=input_box(default=47)):
    if (not a in ZZ) or (not b in ZZ) or (not m in ZZ) or (a<=0) or (b<=0) or (m<=0):
        print "*********** ERROR: a,b,m should all be positive integers. ***********"
        print
    else:
        a=Integer(a)
        b=Integer(b)
        m=Integer(m)
        print('This is the evaluation process using squares:')
        print('')
        C=b.str(base=2)
        L=len(C)
        S=[]
        T=[]
    # print "The base 2 expansion of",b,"is",C
        ans=str(a)
        ans_num=a
        for i in range(L):
            pow=L-i-1
            #print C[pow],"copy(ies) of",2,"^",i,"=",2^i
            # Convert to integer:
            # Integer(C[i],base=2)
            S+=[(2^pow)]
            print "Step",i+1,":",str(a)+"^"+str(2^i),"=",ans,"=",ans_num,"mod",m
            #ans_num= a^(i+1) %m
            ans=str(ans_num)+"^"+str(2)
            ans_num= (ans_num)^2%m
            if C[pow]=="1":
                T+=[2^i]
            else:
                T
        expansion = ""
        STR=""
        STR_eval=""
        STR_eval_num=1
        while len(T)>1:
            expansion += str(T[-1])+"+"
            STR += "("+str(a)+"^"+str(T[-1])+")"
            STR_eval += "("+str(a^(T[-1])%47)+")"
            STR_eval_num = STR_eval_num*(a^(T[-1])%47)
            T.remove(T[-1])
        expansion+=str(T[0])
        STR += "("+str(a)+"^"+str(T[0])+")"
        STR_eval += "("+str(a^(T[0])%47)+")"
        STR_eval_num = STR_eval_num*(a^(T[0])%47)
        STR_eval_num = STR_eval_num%47
        print "Step",L+1,":",str(a)+"^"+str(b),"=",STR,"=",STR_eval,"=",STR_eval_num,"mod",m
        print
        print " Since, as a sum of powers of 2,",str(b)+" is "+expansion+"."
        print
        print "CONCLUSION: "+str(STR_eval_num)+" = "+str(a)+"^"+str(b)+" mod",m,". It takes",L+1,"steps to calculate x with this method."

}}}

==== Solving for b ====

Interact to find b when a, x, and m are known:

{{{#!sagecell
pretty_print(html("<h1>Solving for b</h1>"))
print('This will solve for the exponent, b, in x=a^b (mod m) assuming an integer solution exists. Choose your base (a), modulus (m), and solution (x). These should all be positive integers.')
@interact
def DLP_break(a=input_box(default=5),x=input_box(default=22),m=input_box(default=47)):
    if (not a in ZZ) or (not x in ZZ) or (not m in ZZ) or (a<=0) or (x<0) or (m<=0):
        print "*********** ERROR: a,m,x should all be integers with a,m>0. ***********"
        print
# Note: presumably there isn't always a solution? If so, add another error message
    elif x==1:
        print "b=0"
    else:
        a=Integer(a)
        x=Integer(x)
        m=Integer(m)
        ind=0
        for i in [1..m]:
            temp = a^i %m
            if temp==x:
                ind=1
                print "This process took",i,"steps to determine that","b="+str(i)
                break
            else:
                temp
        if ind==0:
            print "*********** ERROR: No integer solution for b.***********"

}}}
Line 687: Line 977:
Named for the authors Rivest, Shamir, Aldeman, RSA uses exponentiation and modular arithmetic to encrypt and decrypt messages between two parties. Each of those parties has their own secret and public key. To see how it works, following along while Alice and Babette share a message. -EG Named for the authors Rivest, Shamir, and Aldeman, RSA uses exponentiation and modular arithmetic to encrypt and decrypt messages between two parties. Each of those parties has their own secret and public key. To see how it works, following along while Alice and Babette share a message.
Line 692: Line 982:
Babette  sent Alice an encrypted message. You , as Alice, will provide information so that you can read Babette's message. Babette sent Alice an encrypted message. You, as Alice, will provide information so that you can read Babette's message.
Line 696: Line 986:
pretty_print(html("<h1>RSA, From Alice's Perspective</h1>"))
Line 699: Line 990:
print " The size of the primes depends on the size of Babette's message. Her message requires p,q > 10. A longer and stronger encrypted message requires larger primes." print " The size of the primes depends on the size of Babette's message. Her message requires p,q > 10. A longer and stronger encrypted"
print "
message requires larger primes."
Line 708: Line 1000:
    #print "************************************************************************************************"
    #print "WARNINGS: p and q should be different primes, both larger than 10."
    #print "e should be relatively prime to φ(pq). To check this, see the factorization of φ(pq) below."
    #print "************************************************************************************************"
    #print ""
Line 776: Line 1063:
#Last edited 8/8/19 at 12:30pm
print "Hi, Babette! Let's send a message to Alice using RSA."
p = next_prime(100)
q = next_prime(p)
phi = (p-1)*(q-1)
e = 13
N = p*q
R = IntegerModRing(phi)
d = (e^(R(e).multiplicative_order()-1)).mod(phi)
print "Alice's public key is: N =",N,", e =",e,"."
message = raw_input("Type a message for Alice:")
ascii_secret = []
for char in message:
    ascii_secret.append(ord(char))
print "We turn these characters into ascii:"
print ascii_secret
#Last edited 8/9/19 2:40pm
pretty_print(html("<h1>RSA, From Babette's Perspective</h1>"))
print "Hi, Babette! Let's send a message to Alice using her PUBLIC key (N, e) with RSA."
Line 793: Line 1067:
print "Then we encode them by raising each ascii number to the e-th power modulo N."
encrypted_ascii = []
for ascii in ascii_secret:
    encrypted_ascii.append(power_mod(ascii,e,N))
print encrypted_ascii
print ""
@interact
def rsa():
    print "Alice receives our secret and uses her private key to decrypt the message."
print "1. Input Babette's secret message for Alice in between the quotation marks below."
print " Make sure that there are no apostrophes or extra quotation marks in your message."
@interact
def rsa(message = input_box(default = '"Secrets for Alice"',label="Message:")):
    p = next_prime(100)
    q = next_prime(p)
    phi = (p-1)*(q-1)
    e = 13
    N = p*q
    R = IntegerModRing(phi)
    d = (e^(R(e).multiplicative_order()-1)).mod(phi)
    ascii_secret = []
    for char in message:
        ascii_secret.append(ord(char))
    print "2. Using ASCII, we take the characters in our message and convert each of them into integers."
    print ""
    print " ",ascii_secret
    print ""
    print "Alice's PUBLIC key is given to be (N, e) = (",N,",",e,")."
    print ""
    print "4. We encode the list of numbers by raising each integer to the e-th power modulo N. Recall that e is called the encryption key. This is what get's sent to Alice:"
    encrypted_ascii = []
    for ascii in ascii_secret:
        encrypted_ascii.append(power_mod(ascii,e,N))
    print ""
    print " ",encrypted_ascii
    print ""
    print "5. To decrypt, Alice raises each integer to the d-th power modulo N, where d is Alice's PRIVATE decryption key."
Line 805: Line 1098:
    print decrypted_ascii     print ""
    print " ",
decrypted_ascii
Line 810: Line 1104:
    print "Going from ascii to letters, she figures out your message was: "
    print decrypted_secret
    print "6. Going from the integers to letters using ASCII, we find that Babette's message was "
    print ""
    print " ",
decrypted_secret
Line 822: Line 1117:

== Diffe-Hellman Key Exchange ==

Sage Interactions - Cryptography

This page was first created at Sage Days 103, 7-9 August 2019 by Sarah Arpin, Catalina Camacho-Navarro, Holly Paige Chaos, Amy Feaver, Eva Goedhart, Sara Lapan, Rebecca Lauren Miller, Alexis Newton, and Nandita Sahajpal. Text edited by Holly Paige Chaos, Amy Feaver, Eva Goedhart, and Alexis Newton. This project was led by Amy Feaver and Eva Goedhart.

We acknowledge Katherine Stange, who allowed us to use code from her cryptography course as a starting point for many of these interacts. Dr. Stange's original code and course page can be found at http://crypto.katestange.net/

If you have cryptography-related interactions that you are interested in adding to this page, please do so. You can also contact Amy Feaver at [email protected]

goto interact main page

Shift Cipher

The shift cipher is a classical cryptosystem that takes plaintext and shifts it through the alphabet by a given number of letters. For example, a shift of 2 would replace all A's with C's, all B's with D's, etc. When the end of the alphabet is reached, the letters are shifted cyclically back to the beginning. Thus, a shift of 2 would replace Y's with A's and Z's with B's.

Shift Cipher Encryption

by Sarah Arpin, Alexis Newton

You can use this interact to encrypt a message with a shift cipher.

Shift Cipher Decryption

by Sarah Arpin, Alexis Newton

If you know that your message was encrypted using a shift cipher, you can use the known shift value to decrypt. If this is not known, brute force can be used to get 26 possible decrypted messages. The chi-squared function ranks the brute force results by likelihood according to letter frequency.

Affine Cipher

An affine cipher combines the idea of a shift cipher with a multiplicative cipher. In this particular example, we map consecutive letters of the alphabet to consecutive numbers, starting with A=0 (you can also do this cipher differently, and starting with A=1). The user selects two values, a and b. The value a is the multiplier and must be relatively prime to 26 in order to guarantee that each letter is encoded uniquely. The value b is the addend. Each letter's value is multiplied by a, and the product is added to b. This is then replaced with a new letter, corresponding to the result modulo 26.

Affine Cipher Encryption

by Sarah Arpin, Alexis Newton

You can use this interact to encrypt a message with the affine cipher. Notice that the only choices for a can be numbers that are relatively prime to 26. This cipher will encipher a letter m of your message as a*m + b.

Affine Cipher Decryption

by Sarah Arpin, Alexis Newton

If you know that your message was encrypted using an affine cipher, you can use the known a and b values to decrypt. If these are not known, brute force can be used to get a list of possible decrypted messages. The chi-squared function ranks these results by likelihood according to letter frequency.

Substitution Cipher

by Catalina Camacho-Navarro

A substitution cipher encrypts messages by assigning each letter of the alphabet to another letter. For instance, if A is assigned to F, then all A's in the original message will be substituted with F's in the encrypted message. Brute force or frequency analysis can be used to decrypt a message encrypted with a substitution cipher.

Playfair Cipher

by Catalina Camacho-Navarro

Based on code from Alasdair McAndrew at trac.sagemath.org/ticket/8559.

A playfair cipher is a special type of substitution cipher in which the plaintext is broken up into two-letter digraphs with some restrictions. Those digraphs are encrypted using a Polybius square, (i.e. a 5x5 grid in which each letter of the alphabet is its own entry with the exception of ij which are placed together). The positions of the letters in the digraph determine how the digraph is encrypted.

Playfair Encryption

Use this interact to encrypt a message using the playfair cipher.

Playfair Decryption

Frequency Analysis Tools

Frequency analysis is a technique for breaking a substitution cipher that utilizes the frequencies of letters appearing in the English language. For example, E is the most common letter in the English language, so if a piece of encrypted text had many instances of the letter Q, you would guess that Q had been substituted in for E. The next two interacts create a couple of basic tools that could be useful in cracking a substitution cipher.

Letter Frequency Counter

by Rebecca Lauren Miller, Katherine Stange

This tool looks at the percentage of appearances of each letter in the input text and plots these percentages. The encrypted input text is a bit strange, but was constructed by Amy Feaver to give a short block of text that matched the frequencies of letters in the English language relatively well, to make this message easier to decrypt.

Frequency Analysis Decryption Guesser

by Rebecca Lauren Miller, Katherine Stange

This interact prints a suggested translation of the input text by matching frequencies of letters in the input to frequencies of letters in the English language. With the output you will see that some letters were substituted incorrectly, and others were not. Usually frequency analysis requires additional work and some trial and error to discover the original message, especially if the input text is not long enough.

Vigenère Cipher

A Vigenère cipher is an example of a polyalphabetic cipher. Using a secret codeword as the key, the Vigenère encrypts each letter of a message by shifting it according to the corresponding letter in the key. For example, we will use the key "CAT" to encrypt our default text "secrets hi". To do this the message is first broken up into three-letter chunks, because the key is three letters long, to be "SEC RET SHI". Next each letter of the chunk is shifted by the value of the corresponding letter in the key. The standard shifts are A=0, B=1, C=2, etc. So in our example, S shifts by C=2 letters to U, E shifts by A=0 letters and remains at E, and C shifts by T=19 letters to V. Thus "SECRETSHI" becomes UEVTEMUHB when encrypted. To decrypt the message, simply use the keyword to undo the encryption process. Cryptography by Simon Rubinstein-Salzedo was used as reference for this interact.

Vigenère Cipher Encryption

by Holly Paige Chaos, Rebecca Lauren Miller, Katherine Stange

Use this interact to encrypt a message using the Vigenère Cipher.

Vigenère Cipher Decryption

by Holly Paige Chaos, Rebecca Lauren Miller, Katherine Stange

If you used the Vigenère Cipher to encrypt a message, you can use this interact to decrypt by inputting your key and encrypted text.

One-Time Pad

by Sarah Arpin, Alexis Newton

One-time pad is an encryption method that cannot be cracked. It requires a single-use shared key (known as a one-time pad) the length of the message or longer. In this method, every letter is first converted to numbers using the standard A=0, B=1, C=2, etc. Then each character in the message is multiplied modulo 26 by the number in the corresponding position in the key. This is then converted back to letters to produce the encrypted text.

Hill Cipher

The Hill cipher requires some basic knowledge of Linear Algebra. In this encryption method, an invertible n x n matrix of integers modulo 26 is used as the key. The message is first converted to numbers and spit into chunks size n. These chunks are then converted to n x 1 vectors and multiplied by the key modulo 26 to produce 1 x n vectors. The integers from these vectors are converted back letters to produce the encrypted text.

Hill Cipher Encryption

by Holly Paige Chaos, Alexis Newton

Use this interact to encrypt a message with the Hill cipher. Be sure to use an invertible matrix so that your message can be decrypted!

Hill Cipher Decryption

by Holly Paige Chaos, Alexis Newton

Use this interact to decrypt messages encrypted by the Hill cipher. Remember that this only works if the message was encrypted using an invertible matrix as the key!

Modular Arithmetic (Preliminaries for RSA, Diffie-Hellman, El Gamal)

This section gives visual representations of the modular arithmetic necessary for RSA, Diffie-Hellman, and El Gamal.

Modular Arithmetic Multiplication Table

by Rebecca Lauren Miller, Kate Stange

Given a positive integer n, this prints the multiplication mod n. Each entry in this table corresponds to the product of the row number by the column number, modulo n.

Modular Exponentiation

by Rebecca Lauren Miller, Kate Stange

Given a modulus n and a nonnegative exponent a, this displays a graph where each integer between 0 and n-1 is mapped to its a-th power, mod n.

Discrete Log Problem

by Sara Lapan

The discrete logarithm, log(x) with base a, is an integer b such that ab = x. Computing logarithms is computationally difficult, and there are no efficient algorithms known for the worst case scenarios. However, the discrete exponentiation is comparatively simple (for instance, it can be done efficiently using squaring). This asymmetry in complexity has been exploited in constructing cryptographic systems. Typically, it is much easier to solve for x in x = ab (mod m) when a, b, and m are known, than it is to solve for b when x, a, and m are known.

Solving for x

Interact to find x when a, b, and m are known:

Solving for b

Interact to find b when a, x, and m are known:

RSA

Named for the authors Rivest, Shamir, and Aldeman, RSA uses exponentiation and modular arithmetic to encrypt and decrypt messages between two parties. Each of those parties has their own secret and public key. To see how it works, following along while Alice and Babette share a message.

RSA, From Alice's Perspective

by Sarah Arpin, Eva Goedhart

Babette sent Alice an encrypted message. You, as Alice, will provide information so that you can read Babette's message.

RSA, From Babette's Perspective

by Sarah Arpin, Eva Goedhart

RSA With Digital Signatures

by Sarah Arpin, Eva Goedhart

interact/cryptography (last edited 2019-11-14 19:53:51 by chapoton)