├── .gitignore ├── Book.pdf ├── CipherWheel.pdf ├── CryptolReference.pdf ├── src ├── figures │ ├── Enigma1.jpg │ ├── HelloCaesar.pdf │ ├── HelloCaesar.png │ ├── Enigma_Milano.jpg │ ├── Enigma-plugboard.jpg │ ├── EnigmaOffsetsBwd.pdf │ ├── EnigmaOffsetsFwd.pdf │ ├── ReflectorOffsets.pdf │ ├── UnicodeFunnyFigure.pdf │ ├── OneRotorPaperEnigma.jpg │ ├── ReverseCaesarCipherKit.pdf │ ├── AtoD.eps │ └── ReverseCaesarCipherKit.ps ├── cryptol │ ├── caesar.cry │ ├── threeRotors.cry │ └── enigma.cry ├── book.rst ├── 01_intro.rst ├── Makefile ├── CryptolReference.tex ├── conf.py ├── 04_morecomplex.rst ├── 06_enigmacomplete.rst ├── 02_encoding.rst ├── 05_enigma.rst └── 03_cryptol.rst ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *\#* 2 | *~ 3 | .DS_Store 4 | .fseventsd 5 | -------------------------------------------------------------------------------- /Book.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/Book.pdf -------------------------------------------------------------------------------- /CipherWheel.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/CipherWheel.pdf -------------------------------------------------------------------------------- /CryptolReference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/CryptolReference.pdf -------------------------------------------------------------------------------- /src/figures/Enigma1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/Enigma1.jpg -------------------------------------------------------------------------------- /src/figures/HelloCaesar.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/HelloCaesar.pdf -------------------------------------------------------------------------------- /src/figures/HelloCaesar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/HelloCaesar.png -------------------------------------------------------------------------------- /src/figures/Enigma_Milano.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/Enigma_Milano.jpg -------------------------------------------------------------------------------- /src/figures/Enigma-plugboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/Enigma-plugboard.jpg -------------------------------------------------------------------------------- /src/figures/EnigmaOffsetsBwd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/EnigmaOffsetsBwd.pdf -------------------------------------------------------------------------------- /src/figures/EnigmaOffsetsFwd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/EnigmaOffsetsFwd.pdf -------------------------------------------------------------------------------- /src/figures/ReflectorOffsets.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/ReflectorOffsets.pdf -------------------------------------------------------------------------------- /src/figures/UnicodeFunnyFigure.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/UnicodeFunnyFigure.pdf -------------------------------------------------------------------------------- /src/figures/OneRotorPaperEnigma.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/OneRotorPaperEnigma.jpg -------------------------------------------------------------------------------- /src/figures/ReverseCaesarCipherKit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylanmc/CryptoBook/HEAD/src/figures/ReverseCaesarCipherKit.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This book is covered by the Creative Commons Attribution-ShareAlike 4.0 International License. 2 | 3 | See https://creativecommons.org/licenses/by-sa/4.0/legalcode 4 | -------------------------------------------------------------------------------- /src/cryptol/caesar.cry: -------------------------------------------------------------------------------- 1 | alphabet : [26][8] 2 | alphabet = ['a' .. 'z'] 3 | 4 | toLower c = if c < 0x61 then c + 0x20 else c 5 | asciiToIndex c = (toLower c) - 'a' 6 | encryptChar wheel c = if c == ' ' then c else wheel @ (asciiToIndex c) 7 | codeWheel key = reverse alphabet >>> key 8 | encrypt key message = [ encryptChar (codeWheel key) c | c <- message ] 9 | -------------------------------------------------------------------------------- /src/book.rst: -------------------------------------------------------------------------------- 1 | .. CryptoBook documentation master file, created by 2 | sphinx-quickstart on Mon Nov 7 09:45:04 2016. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Cryptography, Math and Programming 7 | ================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | 12 | 01_intro 13 | 02_encoding 14 | 03_cryptol 15 | 04_morecomplex 16 | 05_enigma 17 | 06_enigmacomplete 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Goals of this book 2 | 3 | Shooting for high-school-ish aged students who want to learn about cryptography, 4 | and are willing to learn about math and programming along the way. 5 | 6 | ## Beginnings of an Outline 7 | 8 | * Introduction 9 | * what to expect, what we expect of you 10 | * encrypting punchlines with Reverse-Caesar codewheels 11 | * Encoding information - Binary, ASCII, UTF-8, Morse code, Huffman encoding 12 | * each chapter begins with "what you'll get out of this chapter", which can also be "if you know all this, you can skim this chapter" 13 | * Introduction to Cryptol 14 | * data types 15 | * sequences, comprehensions 16 | * functions 17 | * Implementing the Caesar Cipher in Cryptol 18 | * The Enigma 19 | * a bit of history 20 | * building one with paper 21 | * implementing the Enigma in Cryptol 22 | 23 | ## Tools used to build the book 24 | 25 | I'm writing the book in ReStructuredText, and converting to PDF and HTML via Sphinx. 26 | (I switched from Pandoc/Markdown to make it easier to generate the index, and other improvements) 27 | -------------------------------------------------------------------------------- /src/figures/AtoD.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 EPSF-3.0 2 | %%BoundingBox: 10 10 150 150 3 | %%Creator: Dylan McNamee, by hand 4 | %%Title: TempConversion 5 | %%Pages: 1 6 | %%PageOrder: Ascend 7 | %%EndComments 8 | 9 | % Caesar Cipher wheel in PostScript. 10 | % Written by Dylan McNamee for a Cryptol book. 11 | % Copyright 2016, Creative Commons Attribution Share-alike 12 | % dylan dot mcnamee at gmail dot com is how to reach me 13 | 14 | % This program does both normal and Reverse-Caesar 15 | % ciphers Reverse one has the advantage that it 16 | % doesn't matter which wheel is plaintext and which 17 | % is ciphertext - they're symmetric. 18 | 19 | % max randRange #0->max 20 | realtime srand 21 | /randRange { rand 16#7fffffff div mul cvi } def 22 | 23 | /doCyberGizmo { 24 | /step exch def 25 | /radius exch def 26 | /minRad exch def /yStart exch def /xStart exch def 27 | 0 step 360 step sub { /startAng exch def 28 | /angDelta step 2 div cvi randRange startAng add 5 add def 29 | xStart yStart minRad radius randRange add startAng angDelta arc 30 | xStart yStart minRad radius randRange sub angDelta startAng step add arc 31 | } for 32 | closepath 33 | } def 34 | 35 | 0.4 0.4 scale 36 | 37 | 0.9 setgray 38 | % 300 300 150 25 15 doCyberGizmo 39 | % gsave stroke grestore fill 40 | 200 200 70 0 360 arc fill 41 | 42 | %0.8 setgray 43 | %200 200 100 25 15 doCyberGizmo 44 | %gsave stroke grestore fill 45 | 46 | 0.6 setgray 47 | 200 200 50 15 40 doCyberGizmo 48 | gsave stroke grestore fill 49 | 50 | 1 setgray 51 | 200 200 25 0 360 arc fill 52 | 53 | 0 setgray 54 | 55 | 56 | % x y centerMark - 57 | % draws a plus @x,y 58 | /centerMark { moveto currentpoint -2 0 rmoveto 4 0 rlineto stroke moveto 0 -2 rmoveto 0 4 rlineto stroke } def 59 | 60 | /Alphabet [(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)] def 61 | /AlphabetLength Alphabet length def 62 | 63 | /AlphabetLower [(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)] def 64 | 65 | /AlphabetRev [ AlphabetLength 1 sub -1 0 66 | { Alphabet exch get } for 67 | ] def 68 | 69 | % /AlphabetRev Alphabet def 70 | 71 | /Helvetica findfont 24 scalefont setfont 72 | 73 | /cshow { dup stringwidth pop 2 div -1 mul 0 rmoveto show } def 74 | 75 | % x y r text wheelShow - 76 | % shows the text centered in a circle of radius r 77 | /wheelShow { /clicks exch def 78 | /chars exch def /radius exch def /yCenter exch def /xCenter exch def 79 | /count chars length def 80 | /anglePerClick -360.0 count div def 81 | gsave 82 | xCenter yCenter centerMark 83 | xCenter yCenter radius add translate 84 | % advance wheel by # clicks 85 | 0 0 moveto 0 radius -1 mul translate 86 | clicks anglePerClick mul rotate 87 | 0 radius translate 88 | chars 89 | { 90 | 0 0 moveto 91 | 0 radius -1 mul translate 92 | cshow 93 | anglePerClick rotate 94 | 0 radius translate 95 | } forall 96 | grestore 97 | } def 98 | 99 | gsave 100 | [3 3] 0 setdash 101 | 200 200 124 0 360 arc stroke 102 | 200 200 centerMark 103 | 200 200 100 AlphabetRev 4 wheelShow 104 | grestore 105 | 106 | 200 200 130 Alphabet 0 wheelShow 107 | 200 200 154 0 360 arc stroke 108 | 109 | showpage 110 | -------------------------------------------------------------------------------- /src/01_intro.rst: -------------------------------------------------------------------------------- 1 | Getting started 2 | =============== 3 | 4 | This book is a guide to learning about cryptography, the math that 5 | cryptography is built on, and how to write programs that implement 6 | cryptographic algorithms. Don't worry if any of that sounds too 7 | complicated: it's all explained inside. Also don't worry if it sounds 8 | too boring: these topics are surprisingly deep and interesting -- 9 | there's a lot of cool stuff even jaded students (of all ages!) can 10 | learn. 11 | 12 | At the beginning of each chapter, we'll describe what you'll know by the 13 | end of the chapter. If you feel like you already know that stuff, try 14 | skimming the chapter (don't skip it!) to make sure that you do, and slow 15 | down and read the new stuff. 16 | 17 | At the end of this chapter you'll know what resources you'll need to 18 | complete the activities in the book, and you'll have encrypted and 19 | decrypted a message using the Caesar cipher. Let's get going! 20 | 21 | What you'll need 22 | ---------------- 23 | 24 | You'll need a sense of curiosity. You'll also need a dedication to 25 | actually doing the exercises: if you just read this material you'll only 26 | get a small fraction of the benefit of doing. You'll need access to a 27 | computer. It can be a Windows, MacOS or Linux computer - they're all 28 | fine. 29 | 30 | Having a group of people to work with is a good idea. A lot of the 31 | activities require serious thought, and it's totally normal to get stuck 32 | (often). If you work with a group of people, when one of you gets stuck, 33 | the others can help out. Not by giving answers, but by nudging in 34 | productive directions. Often all it takes to do this is to ask "What are 35 | you working on? What have you tried? Is there anything you haven't tried 36 | yet?" Explaining the answers to these questions to another person is 37 | often enough to get unstuck. 38 | 39 | Why cryptography? 40 | ----------------- 41 | 42 | Cryptography is the mathematics of secret messages. The popularity and 43 | pervasiveness of social media has caused some people to comment "nothing 44 | is secret any more." But is that really true? People share photos taken 45 | in restaurants all the time, but is it a good idea to share a photo of 46 | the credit card you used to pay for your food? What about sharing your 47 | social media passwords? Needless to say, privacy and cryptography are 48 | both interesting, and are related to each other in subtle ways. 49 | 50 | Cryptography can be used for other purposes than keeping information 51 | secret, too. For example, *cryptographic signatures* can be used in 52 | place of a pen-and-ink signature to indicate you agree to something. 53 | Another application is *cryptographic hashes*, which can tell you, 54 | with high confidence, whether a document has been tampered with. 55 | 56 | Let's get started 57 | ----------------- 58 | 59 | Print out and assemble the "Caesar cipher kit" that comes with the book. 60 | The Caesar cipher is one of the earliest known ciphers, used by Caesar to 61 | communicate orders to distant generals. The idea is that if the 62 | messenger was intercepted by foes of Caesar, that they wouldn't learn 63 | any secrets from the message they carried. 64 | 65 | .. figure:: figures/HelloCaesar.pdf 66 | :alt: Encrypting "HELLO" with the Caesar cipher. Key is A\ :math:`\leftrightarrow`\ D 67 | :figclass: align-center 68 | 69 | Encrypting "HELLO" with the Caesar cipher. Key is A\ :math:`\leftrightarrow`\ D 70 | 71 | Follow the instructions on the kit to decode the following punch-lines: 72 | 73 | I wondered why the ball was getting bigger ... (Use the key: 74 | J\ :math:`\leftrightarrow`\ M) 75 | 76 | ``CORI NC ONC JR`` 77 | 78 | What do you call a counterfeit noodle? (Key: 79 | F\ :math:`\leftrightarrow`\ O) 80 | 81 | ``TG LHETBAT`` 82 | 83 | A backward poet ... (Key: H\ :math:`\leftrightarrow`\ H) 84 | 85 | ``SXGVKW GBTKXWK`` 86 | 87 | If you managed to decrypt all three of these, congratulations - that's a 88 | lot of work! When I use a Caesar cipher wheel, it takes about 3 89 | seconds per letter to encrypt or decrypt a message. At that rate, it 90 | would take about an hour to encrypt a whole page of text, which is way 91 | too long. 92 | 93 | Given how tedious it is to decrypt, even when you know the key, it's not 94 | too hard of a stretch to imagine Caesar thinking this cipher was good 95 | enough. Now that we have computers, it's a lot easier to encrypt and 96 | decrypt messages, and the Caesar cipher is not close to good enough. 97 | We'll learn about how modern cryptography works later in this 98 | book. 99 | 100 | Things to ponder 101 | ---------------- 102 | 103 | 1. Notice that the order of the alphabet is reversed on your Caesar 104 | cipher's inner wheel. You may have seen a Caesar cipher whose inner 105 | wheel and outer wheel go in the same direction. What attributes do 106 | each version have? What advantages or disadvantages can you think 107 | between the two versions? 108 | 109 | 2. If it took you one minute to try to decrypt a message using a key you 110 | guessed, how long would it take, on average, to decrypt a Caesar 111 | cipher message whose key you don't know\ [1]_? If it takes a computer 112 | 1 millisecond try one key on a message, how long, on average, would 113 | it take to decrypt a message without knowing the key? 114 | 115 | .. [1] Hint: first, how many different possible keys are there? It's 116 | safe to guess that, on average, you'll have to try half of them before 117 | guessing the right one. 118 | 119 | 3. How much more secure would it be to have weird symbols (Greek letters 120 | or Egyptian hieroglyphics), instead of letters, for the ciphertext in 121 | a Caesar cipher? Explain your answer. 122 | 123 | .. index:: ! key distribution 124 | 125 | 4. *Key distribution* is the challenge of getting the secret key to your 126 | friend. One way to distribute a key would be to include it in some 127 | hidden way in the message. Come up with a few ways you could do this 128 | with the Caesar Cipher. Another way would be to agree on a shared key 129 | when in the same room as your friend. What are some of the advantages 130 | and disadvantages of these two approaches? 131 | 132 | Take-aways 133 | ---------- 134 | 135 | You've thought about why cryptography is important. You know how to 136 | encrypt and decrypt messages using the Caesar cipher. You have thought 137 | about how secure it is, including the aspects of key distribution. 138 | -------------------------------------------------------------------------------- /src/figures/ReverseCaesarCipherKit.ps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 2 | %%BoundingBox: 0 0 612 792 3 | %%DocumentMedia Letter 612 792 75 white ( ) 4 | %%Creator: Dylan McNamee, by hand 5 | %%Title: Caesar cipher Kit 6 | %%Pages: 1 7 | %%PageOrder: Ascend 8 | %%EndComments 9 | 10 | % Caesar cipher wheel in PostScript. 11 | % Written by Dylan McNamee for a Cryptol book. 12 | % Copyright 2016, Creative Commons Attribution Share-alike 13 | % dylan dot mcnamee at gmail dot com is how to reach me 14 | 15 | % This program can create both normal and Reverse-Caesar 16 | % ciphers. The Reverse has the advantage that it 17 | % doesn't matter which wheel is plaintext and which 18 | % is ciphertext - they're symmetric. 19 | 20 | % this document is licensed under Creative Commons 21 | % Attribution-ShareAlike 4.0 license 22 | % http://creativecommons.org/licenses/by-sa/4.0/ 23 | 24 | % first, a little decoration: 25 | 26 | % max randRange #0->max 27 | realtime srand 28 | /randRange { rand 16#7fffffff div mul cvi } def 29 | 30 | % xPos yPos minRadius maxRand stepDegrees doCyberGizmo - 31 | % draws a cyber-gizmo thing @xPos,yPos 32 | /doCyberGizmo { 33 | /step exch def 34 | /radius exch def 35 | /minRad exch def /yStart exch def /xStart exch def 36 | 0 step 360 step sub { /startAng exch def 37 | /angDelta step 2 div cvi randRange startAng add 5 add def 38 | xStart yStart minRad radius randRange add startAng angDelta arc 39 | xStart yStart minRad radius randRange sub angDelta startAng step add arc 40 | } for 41 | closepath 42 | } def 43 | 44 | 0.4 setgray 45 | 200 550 60 0 360 arc closepath fill 46 | 0.6 setgray 47 | 200 550 50 20 30 doCyberGizmo fill 48 | 0.8 setgray 49 | 200 550 35 0 360 arc closepath fill 50 | 51 | 0 setgray 52 | 53 | % x y centerMark - 54 | % draws a plus @x,y 55 | /centerMark { moveto currentpoint -2 0 rmoveto 4 0 rlineto stroke moveto 0 -2 rmoveto 0 4 rlineto stroke } def 56 | 57 | /Alphabet [(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)] def 58 | /AlphabetLength Alphabet length def 59 | 60 | /AlphabetLower [(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)] def 61 | 62 | /AlphabetRev [ AlphabetLength 1 sub -1 0 63 | { Alphabet exch get } for 64 | ] def 65 | 66 | % uncomment the line below for a normal Caesar cipher wheel 67 | % /AlphabetRev Alphabet def 68 | 69 | /Helvetica findfont 24 scalefont setfont 70 | 71 | /ccshow { dup stringwidth pop -2 div 0 rmoveto show } def 72 | 73 | % x y r text wheelShow - 74 | % shows the text centered in a circle of radius r 75 | /wheelShow { /chars exch def /radius exch def /yCenter exch def /xCenter exch def 76 | /count chars length def 77 | gsave 78 | xCenter yCenter centerMark 79 | xCenter yCenter radius add translate 80 | chars 81 | { 82 | 0 0 moveto 83 | 0 radius -1 mul translate 84 | ccshow 85 | -360.0 count div rotate 86 | 0 radius translate 87 | } forall 88 | grestore 89 | } def 90 | 91 | % draw the inner wheel 92 | gsave 93 | [3 3] 0 setdash 94 | 200 550 124 0 360 arc stroke 95 | 200 550 centerMark 96 | 200 550 100 AlphabetRev wheelShow 97 | grestore 98 | 99 | % draw the outer wheel 100 | 200 240 130 Alphabet wheelShow 101 | 200 240 154 0 360 arc stroke 102 | 103 | %% takes , sets margins 104 | /margin-set { 105 | /line-height exch def 106 | /line-y exch def 107 | /line-x exch def 108 | line-x line-y moveto 109 | } bind def 110 | 111 | %% carriage return. 112 | /cr {/line-y line-y line-height sub def 113 | line-x line-y moveto} def 114 | 115 | %% half-line advance 116 | /hcr {/line-y line-y line-height 2 div sub def 117 | line-x line-y moveto} def 118 | 119 | %% show/cr 120 | /scr {show cr} bind def 121 | 122 | /rcr {dup stringwidth pop -1 mul 0 rmoveto scr} def 123 | 124 | /ccr {dup stringwidth pop -2 div 0 rmoveto scr} def 125 | 126 | %% (string) stringdims -> dx dy 127 | /stringdims { false charpath flattenpath pathbbox exch 4 -1 roll sub 3 1 roll exch sub } def 128 | 129 | /cshow {-2 div /height exch def 130 | dup stringwidth pop -2 div height rmoveto show } def 131 | 132 | 72 720 moveto 133 | /Helvetica findfont 42 scalefont setfont 134 | (Caesar cipher kit) show 135 | /head { /Helvetica findfont 15 scalefont setfont } def 136 | /body { /Helvetica findfont 10 scalefont setfont } def 137 | 400 680 14 margin-set 138 | head (Assembly Instructions:) scr 139 | body hcr 140 | (1 - print this page on thick paper) scr 141 | (2 - cut out the upper wheel along) scr 142 | ( dotted lines) scr 143 | (3 - push a pin or tack through both) scr 144 | ( wheels, smaller wheel on top) scr 145 | () scr 146 | head (Encrypt a message:) scr 147 | body hcr 148 | (1 - choose an alignment of the wheels) scr 149 | (2 - write down any pair of inner/outer) scr 150 | ( letters - this is your key.) scr 151 | ( Share it with your friend in secret) scr 152 | (3 - for each letter in your message) scr 153 | ( find the letter on one wheel,) scr 154 | ( and write down the letter on) scr 155 | ( the other wheel) scr 156 | (4 - this is your encrypted message.) scr 157 | ( give it to a friend to decrypt) scr 158 | () scr 159 | hcr 160 | head (Decrypt a message:) scr 161 | body hcr 162 | (1 - you have a key \(shared previously\)) scr 163 | ( and a secret message.) scr 164 | (2 - align the wheels so the two letters) scr 165 | ( in the key are lined up) scr 166 | (3 - for each letter in the encrypted) scr 167 | ( message, find the letter on one )scr 168 | ( wheel, and write down the letter on) scr 169 | ( the other wheel.) scr 170 | (4 - congratulations - You've decrypted) scr 171 | ( a secret message!)scr 172 | () scr 173 | head (Things to ponder:) scr 174 | body hcr 175 | (1 - how are the encrypt and decrypt) scr 176 | ( processes similar?) scr 177 | (2 - how are they different?) scr 178 | (3 - if someone doesn't have the key,) scr 179 | ( how difficult is decryption?) scr 180 | (4 - does it matter which wheel you use) scr 181 | ( for encrypting or decrypting?) scr 182 | (5 - other than size, are the wheels) scr 183 | ( different? Why might that be?) scr 184 | 185 | 36 52 12 margin-set 186 | /Helvetica findfont 8 scalefont setfont 187 | (This kit is part of an in-progress book about Cryptography, Programming and Mathematics) scr 188 | (by Dylan McNamee. It is released under the Creative Commons Attribution-ShareAlike license.) scr 189 | (Visit https://github.com/dylanmc/CryptoBook for more information. Version 1.3, October 11, 2016) scr 190 | showpage 191 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | all: latexpdf 4 | 5 | # You can set these variables from the command line. 6 | SPHINXOPTS = 7 | SPHINXBUILD = sphinx-build 8 | PAPER = 9 | BUILDDIR = .build 10 | 11 | # Internal variables. 12 | PAPEROPT_a4 = -D latex_paper_size=a4 13 | PAPEROPT_letter = -D latex_paper_size=letter 14 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 15 | # the i18n builder cannot share the environment and doctrees with the others 16 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 17 | 18 | .PHONY: help 19 | help: 20 | @echo "Please use \`make ' where is one of" 21 | @echo " html to make standalone HTML files" 22 | @echo " dirhtml to make HTML files named index.html in directories" 23 | @echo " singlehtml to make a single large HTML file" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " applehelp to make an Apple Help Book" 29 | @echo " devhelp to make HTML files and a Devhelp project" 30 | @echo " epub to make an epub" 31 | @echo " epub3 to make an epub3" 32 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 33 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 34 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 35 | @echo " text to make text files" 36 | @echo " man to make manual pages" 37 | @echo " texinfo to make Texinfo files" 38 | @echo " info to make Texinfo files and run them through makeinfo" 39 | @echo " gettext to make PO message catalogs" 40 | @echo " changes to make an overview of all changed/added/deprecated items" 41 | @echo " xml to make Docutils-native XML files" 42 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 43 | @echo " linkcheck to check all external links for integrity" 44 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 45 | @echo " coverage to run coverage check of the documentation (if enabled)" 46 | @echo " dummy to check syntax errors of document sources" 47 | 48 | .PHONY: clean 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | .PHONY: html 53 | html: 54 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 55 | @echo 56 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 57 | 58 | .PHONY: dirhtml 59 | dirhtml: 60 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 61 | @echo 62 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 63 | 64 | .PHONY: singlehtml 65 | singlehtml: 66 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 67 | @echo 68 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 69 | 70 | .PHONY: pickle 71 | pickle: 72 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 73 | @echo 74 | @echo "Build finished; now you can process the pickle files." 75 | 76 | .PHONY: json 77 | json: 78 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 79 | @echo 80 | @echo "Build finished; now you can process the JSON files." 81 | 82 | .PHONY: htmlhelp 83 | htmlhelp: 84 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 85 | @echo 86 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 87 | ".hhp project file in $(BUILDDIR)/htmlhelp." 88 | 89 | .PHONY: qthelp 90 | qthelp: 91 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 92 | @echo 93 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 94 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 95 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/CryptoBook.qhcp" 96 | @echo "To view the help file:" 97 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/CryptoBook.qhc" 98 | 99 | .PHONY: applehelp 100 | applehelp: 101 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 102 | @echo 103 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 104 | @echo "N.B. You won't be able to view it unless you put it in" \ 105 | "~/Library/Documentation/Help or install it in your application" \ 106 | "bundle." 107 | 108 | .PHONY: devhelp 109 | devhelp: 110 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 111 | @echo 112 | @echo "Build finished." 113 | @echo "To view the help file:" 114 | @echo "# mkdir -p $$HOME/.local/share/devhelp/CryptoBook" 115 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/CryptoBook" 116 | @echo "# devhelp" 117 | 118 | .PHONY: epub 119 | epub: 120 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 121 | @echo 122 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 123 | 124 | .PHONY: epub3 125 | epub3: 126 | $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 127 | @echo 128 | @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." 129 | 130 | .PHONY: latex 131 | latex: 132 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 133 | @echo 134 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 135 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 136 | "(use \`make latexpdf' here to do that automatically)." 137 | 138 | .PHONY: latexpdf 139 | latexpdf: 140 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 141 | @echo "Running LaTeX files through pdflatex..." 142 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 143 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 144 | 145 | .PHONY: latexpdfja 146 | latexpdfja: 147 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 148 | @echo "Running LaTeX files through platex and dvipdfmx..." 149 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 150 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 151 | 152 | .PHONY: text 153 | text: 154 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 155 | @echo 156 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 157 | 158 | .PHONY: man 159 | man: 160 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 161 | @echo 162 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 163 | 164 | .PHONY: texinfo 165 | texinfo: 166 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 167 | @echo 168 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 169 | @echo "Run \`make' in that directory to run these through makeinfo" \ 170 | "(use \`make info' here to do that automatically)." 171 | 172 | .PHONY: info 173 | info: 174 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 175 | @echo "Running Texinfo files through makeinfo..." 176 | make -C $(BUILDDIR)/texinfo info 177 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 178 | 179 | .PHONY: gettext 180 | gettext: 181 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 182 | @echo 183 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 184 | 185 | .PHONY: changes 186 | changes: 187 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 188 | @echo 189 | @echo "The overview file is in $(BUILDDIR)/changes." 190 | 191 | .PHONY: linkcheck 192 | linkcheck: 193 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 194 | @echo 195 | @echo "Link check complete; look for any errors in the above output " \ 196 | "or in $(BUILDDIR)/linkcheck/output.txt." 197 | 198 | .PHONY: doctest 199 | doctest: 200 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 201 | @echo "Testing of doctests in the sources finished, look at the " \ 202 | "results in $(BUILDDIR)/doctest/output.txt." 203 | 204 | .PHONY: coverage 205 | coverage: 206 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 207 | @echo "Testing of coverage in the sources finished, look at the " \ 208 | "results in $(BUILDDIR)/coverage/python.txt." 209 | 210 | .PHONY: xml 211 | xml: 212 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 213 | @echo 214 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 215 | 216 | .PHONY: pseudoxml 217 | pseudoxml: 218 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 219 | @echo 220 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 221 | 222 | .PHONY: dummy 223 | dummy: 224 | $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy 225 | @echo 226 | @echo "Build finished. Dummy builder generates no files." 227 | -------------------------------------------------------------------------------- /src/cryptol/threeRotors.cry: -------------------------------------------------------------------------------- 1 | module Enigma where 2 | 3 | // BeginBasicTypes 4 | type Char = [8] // ASCII characters 5 | type Index = [7] // A -> 0, .. Z -> 25 6 | type Offset = [6] // distance between 2 chars 7 | 8 | alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 9 | // rotorIchars = "EK ... " // <- from your Enigma 10 | 11 | // some helpers to go from Char to Index and back: 12 | indexToChar : Index -> Char 13 | indexToChar i = (0b0 # i) + 'A' 14 | 15 | charToIndex : Char -> Index 16 | charToIndex c = drop`{1}(c - 'A') 17 | 18 | stringToOffsets : [26]Char -> [26]Offset 19 | stringToOffsets chars = 20 | [ drop`{2}((c + 26 - a) %26) 21 | | c <- chars 22 | | a <- alphabet 23 | ] 24 | // EndBasicTypes 25 | 26 | // BeginRotorType 27 | // a rotor elt is: (Fwd, Rev, Pin) 28 | type RotorElement = (Offset, Offset, Bit) 29 | type Rotor = [26]RotorElement 30 | // EndRotorType 31 | 32 | type CharPerm = [26]Char 33 | type Reflector= [26]Offset 34 | type Swaps n = [n][2]Char 35 | 36 | rotorIchars = "EKMFLGDQVZNTOWYHXUSPAIBRCJ" 37 | rotorIIchars = "AJDKSIRUXBLHWTMCQGZNPYFVOE" 38 | rotorIIIchars = "BDFHJLCPRTXVZNYEIWGAKMUSQO" 39 | reflBchars = "YRUHQSLDPXNGOKMIEBFZCWVJAT" 40 | 41 | 42 | // BeginRotorDef 43 | buildRotor : [26]Char -> [26]Bit -> Rotor 44 | buildRotor rotorChars pins = [ (of, ob, p) 45 | | of <- fwd 46 | | ob <- rev 47 | | p <- pins 48 | ] where 49 | fwd = stringToOffsets rotorChars 50 | revChars = invertPermutation rotorChars 51 | rev = stringToOffsets revChars 52 | // EndRotorDef 53 | 54 | // BeginReflectorDef 55 | doReflector : [26]Offset -> Index -> Index 56 | doReflector rf i = (i + (0b0 # (rf@i)) ) % 26 57 | 58 | doRotorFwd : Rotor -> Index -> Index 59 | doRotorFwd r i = (i + (0b0 # (r@i).0 )) % 26 60 | 61 | doRotorRev : Rotor -> Index -> Index 62 | doRotorRev r i = (i + (0b0 # (r@i).1 )) % 26 63 | 64 | doOneRotor refl rotor i = 65 | doRotorRev rotor (doReflector refl (doRotorFwd rotor i)) 66 | 67 | doTwoRotors refl r1 r2 i = 68 | doRotorRev r2 (doOneRotor refl r1 69 | (doRotorFwd r2 i)) 70 | // EndReflectorDef 71 | 72 | // BeginIndexOf 73 | indexOf c permutation = candidates ! 0 where 74 | candidates = [ -1 ] # [ if c == s then i else p 75 | | s <- permutation 76 | | p <- candidates 77 | | i <- [ 0 .. 25 ] 78 | ] 79 | // EndIndexOf 80 | 81 | // BeginInvertPermutation 82 | invertPermutation perm = 83 | [ indexToChar (indexOf c perm) 84 | | c <- alphabet 85 | ] 86 | // EndInvertPermutation 87 | 88 | applyOffsetToIndex : [26]Offset -> Index -> Index 89 | applyOffsetToIndex offsets i = 90 | ((0b0 # (offsets @ i)) + i) % 26 91 | 92 | // BeginOneChar 93 | // encryptOneChar 94 | // takes the offsets of a rotor, its inversion, 95 | // a reflector and a character and 96 | // returns the encrypted character 97 | encryptOneChar : [26]Offset -> [26]Offset -> 98 | [26]Offset -> Char -> Char 99 | encryptOneChar rotorFwd rotorRev reflector 100 | inputChar = outputChar where 101 | inputIndex = charToIndex inputChar 102 | afterRI = applyOffsetToIndex rotorFwd inputIndex 103 | afterRefl = applyOffsetToIndex reflector afterRI 104 | outputIndex = applyOffsetToIndex rotorRev afterRefl 105 | outputChar = indexToChar outputIndex 106 | 107 | // encryptOneRotor 108 | // takes the strings for a rotor and a reflector 109 | // and message and encrypts the message one character 110 | // at a time, first rotating the rotor each step 111 | encryptOneRotor rotor reflector message = 112 | [ encryptOneChar (rotorOff <<< i) 113 | (rotorRevOff <<< i) 114 | reflectorOff c 115 | | c <- message 116 | | i <- [1 .. 100] 117 | ] where 118 | rotorOff = stringToOffsets rotor 119 | rotorRev = invertPermutation rotor 120 | rotorRevOff = stringToOffsets rotorRev 121 | reflectorOff = stringToOffsets reflector 122 | // EndOneChar 123 | 124 | // Chapter 6 functions: 125 | 126 | // BeginPinsDef 127 | setBit : {a, b} (fin a, fin b, b >= 1) 128 | => [a] -> [b] -> [b] 129 | setBit b n = n || (1 >>> 1 >> b) 130 | 131 | pinsI, pinsII, pinsIII : [26] 132 | pinsI = setBit (indexOf 'Q' alphabet) zero 133 | pinsII = setBit (indexOf 'E' alphabet) zero 134 | pinsIII = setBit (indexOf 'V' alphabet) zero 135 | 136 | rotorI = buildRotor rotorIchars pinsI 137 | rotorII = buildRotor rotorIIchars pinsII 138 | rotorIII = buildRotor rotorIIIchars pinsIII 139 | // EndPinsDef 140 | 141 | reflB = stringToOffsets reflBchars 142 | 143 | doThreeRotors refl rs i = 144 | doRotorRev r3 (doTwoRotors refl r1 r2 145 | (doRotorFwd r3 i)) where 146 | r1 = rs@0 147 | r2 = rs@1 148 | r3 = rs@2 149 | 150 | doPlugFwd : CharPerm -> Char -> Index 151 | doPlugFwd plugboard c = charToIndex newC where 152 | newC = plugboard@(charToIndex c) 153 | 154 | doPlugRev : CharPerm -> Index -> Char 155 | doPlugRev plugboard i = plugboard@i 156 | 157 | // BeginEnigmaStateDef 158 | type EnigmaState = { 159 | rotors : [3]Rotor, 160 | reflector : Reflector, 161 | plugboard : CharPerm 162 | } 163 | 164 | buildEnigmaState r1 r2 r3 refl plug = 165 | { rotors = [r1,r2,r3] 166 | , reflector = refl 167 | , plugboard = plug 168 | } 169 | 170 | // EndEnigmaStateDef 171 | 172 | // BeginRotationsDef 173 | // getRotations takes 3 rotors, returns a bit 174 | // for each rotor, whether it should advance. 175 | getRotations : [3]Rotor -> [3]Bit 176 | getRotations rs = [r0, r1, r2] where 177 | pins = getPins rs 178 | r0 = pins@1 179 | r1 = pins@2 || pins@1 180 | r2 = True 181 | 182 | // getPins: Extracts the pin values from 3 rotors 183 | getPins : [3]Rotor -> [3]Bit 184 | getPins rs = [ ((rs@0)@0).2 185 | , ((rs@1)@0).2 186 | , ((rs@2)@0).2 187 | ] 188 | // EndRotationsDef 189 | 190 | // BeginAdvanceDef 191 | advanceRotor : Rotor -> Bit -> Rotor 192 | advanceRotor r b = if b then r <<< 1 else r 193 | 194 | advanceRotors : EnigmaState -> EnigmaState 195 | advanceRotors state = 196 | { rotors = newRotors 197 | , reflector = state.reflector 198 | , plugboard = state.plugboard 199 | } where 200 | newRotors = [ advanceRotor r b 201 | | r <- state.rotors 202 | | b <- rbits 203 | ] 204 | rbits = getRotations state.rotors 205 | // EndAdvanceDef 206 | // Cryptol wibble: it would be nice to have syntax shorthand for 207 | // creating a new record from an old one, with only one field 208 | // changed. 209 | 210 | // BeginRotorStates 211 | enigmaStates start = estates where 212 | estates = [start] # [advanceRotors prev | prev <- estates] 213 | // EndRotorStates 214 | 215 | // BeginPlugboardDef 216 | buildPlugboard : {n} (fin n, width n >= 1) => 217 | Swaps n -> [26][8] -> [width n] -> CharPerm 218 | 219 | buildPlugboard swaps permutation i = 220 | if i >= width swaps 221 | then permutation 222 | else buildPlugboard swaps swappedPerm (i + 1) where 223 | swappedPerm = doSwap (swaps@i) permutation 224 | 225 | doSwap : [2][8] -> [26][8] -> [26][8] 226 | doSwap [c, d] perm = perm2 where 227 | indexOfC = indexOf c perm 228 | indexOfD = indexOf d perm 229 | perm1 = [ if i == indexOfC then d else x 230 | | x <- perm | i <- [0..25]] 231 | perm2 = [ if i == indexOfD then c else x 232 | | x <- perm1 | i <- [0..25]] 233 | 234 | franklinHeathPlugboard = buildPlugboard 235 | ["AP","BR","CM","FZ","GJ","IL","NT","OV","QS","WX"] 236 | alphabet 0 237 | // EndPlugboardDef 238 | 239 | basicEnigmaState = buildEnigmaState 240 | rotorI rotorII rotorIII reflB 241 | franklinHeathPlugboard 242 | 243 | simpleEnigmaState = buildEnigmaState 244 | rotorI rotorII rotorIII reflB 245 | alphabet 246 | 247 | // BeginDoOneChar 248 | doOneChar : Char -> EnigmaState -> Char 249 | doOneChar c es = 250 | doPlugRev es.plugboard 251 | (doThreeRotors 252 | es.reflector 253 | es.rotors 254 | (doPlugFwd es.plugboard c)) 255 | // EndDoOneChar 256 | 257 | // BeginDoEnigma 258 | doEnigma startState message = 259 | [ doOneChar c es 260 | | c <- message 261 | | es <- drop`{1}(enigmaStates startState) 262 | ] 263 | // EndDoEnigma 264 | // Cryptol wibble: need ()'s or the drop messes parser up 265 | 266 | // BeginSetKey 267 | setKey : EnigmaState -> [3]Char -> EnigmaState 268 | setKey state key = { rotors = rs' 269 | , reflector = state.reflector 270 | , plugboard = state.plugboard 271 | } where 272 | rs' = [ r <<< o 273 | | r <- state.rotors 274 | | o <- keyOffs ] 275 | keyOffs = [ charToIndex c | c <- key ] 276 | // EndSetKey 277 | -------------------------------------------------------------------------------- /src/CryptolReference.tex: -------------------------------------------------------------------------------- 1 | \documentclass[9pt,letter]{article} 2 | \usepackage[margin=1cm,landscape]{geometry} 3 | %\usepackage{fontspec} 4 | \usepackage[]{flowfram} 5 | \usepackage{mathspec} 6 | \setallmainfonts(Digits,Latin){Times Roman} 7 | \ffvadjustfalse 8 | \setlength{\columnsep}{1cm} 9 | \Ncolumn{3} 10 | \setmainfont[Ligatures=TeX]{Times Roman} 11 | \setsansfont{Helvetica} 12 | \setmonofont{Menlo}[Scale=0.8] 13 | %\linespread{0.5} 14 | \usepackage{enumitem} 15 | \setlist{noitemsep} 16 | % hide section numbers: 17 | \renewcommand{\thesection}{} 18 | \renewcommand{\thesubsection}{} 19 | \makeatletter 20 | \def\@seccntformat#1{\csname #1ignore\expandafter\endcsname\csname the#1\endcsname\quad} 21 | \let\sectionignore\@gobbletwo 22 | \let\latex@numberline\numberline 23 | \def\numberline#1{\if\relax#1\relax\else\latex@numberline{#1}\fi} 24 | \makeatother 25 | 26 | \begin{document} 27 | \section{Cryptol Reference Card} 28 | A brief summary of Cryptol's syntax and basic patterns. For more details, look for the book {\it Programming Cryptol}. 29 | \section{Starting Cryptol, basic commands} 30 | Start Cryptol either by itself, or with the name of a Cryptol file as its argument: 31 | \begin{verbatim} 32 | % cryptol myfile.cry 33 | _ _ 34 | ___ _ __ _ _ _ __ | |_ ___ | | 35 | / __| '__| | | | '_ \| __/ _ \| | 36 | | (__| | | |_| | |_) | || (_) | | 37 | \___|_| \__, | .__/ \__\___/|_| 38 | |___/|_| version 2.4.0 39 | 40 | Loading module Cryptol 41 | Cryptol> 42 | \end{verbatim} 43 | 44 | At the Cryptol prompt, a number of commands are available: 45 | \begin{verbatim} 46 | :set base=10 47 | :set ascii=on // or =off 48 | :r // or :reload - reloads file 49 | :l // or :load 50 | :e // edits the current file 51 | \end{verbatim} 52 | Pressing Tab at the \verb|Cryptol>| prompt, after typing \verb|:|, or after \verb|:set | shows you available options. Experiment! 53 | 54 | \section{Data and types} 55 | Cryptol's types include: 56 | \begin{itemize} 57 | \item{\it Bit} values can be \verb|True| or \verb|False| 58 | \item{\it Sequences} whose elements must have the same type, like 59 | \verb+[0xa, 0xb, 0xc]+. Elements of sequences can be accessed with 60 | the \verb|@| and \verb|!| indexing operators, which index from 61 | the beginning and the end of the sequence, respectively. For 62 | example \texttt{[0xa, 0xb, 0xc]@0} is \verb+0xa+. 63 | \item{\it Tuples} whose elements can have different types, like \verb+('a', 0xf00d, (True, False))+ Elements of tuples can be accessed via \verb+.+ like this: \texttt{(True, 0xa).0} is \verb+True+. 64 | \item{\it Records} are like tuples with named elements, and are also accessed with \verb+.+ like this: \texttt{ \string{ foo=1, bar=2 \string}.bar} is 2. 65 | \end{itemize} 66 | 67 | \subsection{Querying types} 68 | Functions, expressions and values all have types in Cryptol. You can ask Cryptol what the type of something is with the \verb|:t| command, like this: 69 | \begin{verbatim} 70 | Cryptol> :t "Hello, world!" 71 | "Hello, world!" : [13][8] 72 | Cryptol> :t 123 73 | 123 : {a} (fin a, a >= 7) => [a] 74 | Cryptol> :t 0xf00d 75 | 0xf00d : [16] 76 | Cryptol> :t (||) 77 | (||) : {a} a -> a -> a 78 | Cryptol> :t (+) 79 | (+) : {a} (Arith a) => a -> a -> a 80 | \end{verbatim} 81 | These say, in order: 82 | \begin{itemize} 83 | \item{"the string 'Hello, world!' is a sequence of 13 8-bit words} 84 | \item{the number 123 takes a finite number, {\it a}, of bits, where $a >= 7$.} 85 | \item{the number \verb|0xf00d| is a 16-bit sequence} 86 | \item{the operator \verb+||+ takes two arguments of the same type, and its return value has the same type} 87 | \item{the operator \verb|+| takes two arguments of class \verb|Arith| and returns a value of the same type} 88 | \end{itemize} 89 | 90 | \section{Sequence constructors} 91 | Sequences are the most commonly-used 92 | structure in Cryptol. They can be constructed in a number of ways. We've already seen sequence literals, like \verb+[1, 2, 3]+. 93 | You can construct sequences of finite length by specifying the first and last elements, like this: 94 | \begin{verbatim} 95 | Cryptol> [1 .. 10] 96 | [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 97 | \end{verbatim} 98 | Specify the step between elements by providing the first two: 99 | \begin{verbatim} 100 | Cryptol> [1,3 .. 10] 101 | Assuming a = 4 102 | [1, 3, 5, 7, 9] 103 | \end{verbatim} 104 | Descending sequences have descending first two elements: 105 | \begin{verbatim} 106 | Cryptol> [10, 9 .. 0] 107 | Assuming a = 4 108 | [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 109 | \end{verbatim} 110 | Infinite sequences are created with \verb+...+ Since the elements of a sequence all have to have the same (finite) type, the sequence will wrap around. For example: 111 | \begin{verbatim} 112 | Cryptol> [1, 2 ...] // 2 bits per element 113 | Assuming a = 2 114 | [1, 2, 3, 0, 1, ...] 115 | Cryptol> [0x1, 0x3 ...] // 4 bits/elt 116 | [1, 3, 5, 7, 9, ...] 117 | \end{verbatim} 118 | Finally, Cryptol lets you specify the elements of a sequence with the {\it sequence comprehension} syntax, which is inspired by the same concept in mathematics notation. Here are some examples: 119 | \begin{verbatim} 120 | Cryptol> [ a + 3 | a <- [1 .. 10] ] 121 | [4, 5, 6, 7, 8, 9, 10, 11, 12, 13] 122 | Cryptol> [ a + b | a <- [1 .. 10] \ 123 | | b <- [3 ...] ] 124 | [4, 6, 8, 10, 12, 14, 0, 2, 4, 6] 125 | \end{verbatim} 126 | The first one would be described as ``a sequence of elements whose 127 | values are $a + 3$, where a is drawn from the sequence `1 to 10' ''. 128 | The second one is a {\it parallel comprehension}. The resulting length 129 | of a parallel comprehension is the shortest length of its {\it legs}. 130 | In this case, we would describe it as ``a sequence of elements whose 131 | values are $a + b$ where a is drawn from the sequence `1 to 10' and b 132 | is drawn from the infinite sequence starting at 3''. 133 | 134 | Cryptol also supports {\it Cartesian comprehensions}, whose legs are 135 | separated by commas. The first element of the first leg is paired with 136 | each element of the other leg(s), followed by the second element of 137 | the first leg, etc: 138 | \begin{verbatim} 139 | Cryptol> [(a, b) | a <- [1, 2]\ 140 | , b <- [3, 4] ] 141 | [(1, 3), (1, 4), (2, 3), (2, 4)] 142 | \end{verbatim} 143 | 144 | Other things you can do with sequences: the built-in \verb+reverse+ 145 | function reverses the elements of a sequence, and the \verb+#+ 146 | operator concatenates two sequences (of course the two arguments to 147 | \verb+#+ must have elements of the same type). 148 | \begin{verbatim} 149 | Cryptol> reverse ['0' .. '9'] # ['a' .. 'z'] 150 | "9876543210abcdefghijklmnopqrstuvwxyz" 151 | \end{verbatim} 152 | 153 | \section{Functions in Cryptol} 154 | A function declaration looks like this: 155 | \begin{verbatim} 156 | f x y = x + y 157 | \end{verbatim} 158 | The type of this function is: 159 | \begin{verbatim} 160 | f : {a} (Arith a) => a -> a -> a 161 | \end{verbatim} 162 | Reading the type of a function in Cryptol, you have: 163 | \begin{itemize} 164 | \item{the name of the function, } 165 | \item{\verb+:+} 166 | \item{in curly braces, \verb+{}+, the names of {\em type variables}, } 167 | \item{in parentheses the {\em type constraints} (in this case, that the type \verb+a+ needs to be something that supports arithmetic operations (\verb+Arith+),} 168 | \item{a {\em fat arrow} (\verb+=>+),} 169 | \item{the types of the arguments, separated by \verb+->+} 170 | \item{the final element is the type of the return value.} 171 | \end{itemize} 172 | 173 | Cryptol supports {\em curried} arguments, which means that if you pass 174 | fewer arguments than a function takes, the result is a function that 175 | accepts the remaining arguments and has the same return type. For 176 | example: 177 | \begin{verbatim} 178 | addThree = f 3 179 | addThree 8 // value is 11 180 | \end{verbatim} 181 | 182 | You can provide the type of a function along with its definition, or 183 | you can let Cryptol infer a function's type for you. Sometimes 184 | providing the type can help Cryptol give you better error messages - 185 | Cryptol's inferred types are very general, and can be confusing 186 | sometimes. 187 | 188 | \section{Type variables} 189 | Type variables can occur in a few contexts in a Cryptol program. 190 | Some functions take type-level arguments, such as \verb+take+ and \verb+drop+: 191 | \begin{verbatim} 192 | take`{2}[1 .. 10] 193 | // value: [1, 2] 194 | drop`{2}[1 .. 10] 195 | // value: [3, 4 .. 10] 196 | \end{verbatim} 197 | Type-level arguments can be positional or named, like this: 198 | \begin{verbatim} 199 | Cryptol> :t take 200 | take : {front, back, elem} (fin front) => 201 | [front + back]elem -> [front]elem 202 | Cryptol> take`{back=3}[1 .. 10] 203 | [1, 2, 3, 4, 5, 6, 7] 204 | \end{verbatim} 205 | We asked for the type of \verb+take+, and we learned that its argument 206 | is $front+back$ elements long, and that it returns $front$ elements. 207 | If we pass \verb+back=3+ as the type argument to \verb+take+, Cryptol 208 | knows the list has $10$ elements, and also that $front+3=10$, so it 209 | infers that we want to take $7$ elements of our list \verb+[1 .. 10]+. 210 | 211 | \section{{\tt :prove} and {\tt :sat}} 212 | If a function returns \verb+Bit+, you can use Cryptol's powerful 213 | theorem proving powers to either prove that the function is true {\em 214 | for all} values of its argument(s), using \verb+:prove+, or that {\em 215 | there exists} at least one input value that makes the function return 216 | True, using \verb+:sat+. Here, we prove that $x + x$ is always equal 217 | to $x << 1$. 218 | \begin{verbatim} 219 | Cryptol> :prove (\x -> x + x == x << 1):[32]->Bit 220 | Q.E.D. 221 | \end{verbatim} 222 | 223 | One limitation of {\tt :prove} and {\tt :sat} is that the arguments 224 | have to be {\em monomorphic}. That's why we had to specify the 225 | function had type \verb+[32]->Bit+. Here we prove that $x+y == y+x$ 226 | for all 32-bit values x and y: 227 | \begin{verbatim} 228 | Main> :prove (\x y -> x+y == y+x):[32]->[32]->Bit 229 | Q.E.D. 230 | \end{verbatim} 231 | Here we ask Cryptol if there are an 8-bit $x$ and $y$ such that $x^y = 123$: 232 | \begin{verbatim} 233 | Cryptol> :sat (\x y -> x ^^ y == 123):[8]->[8]->Bit 234 | ((\x y -> x ^^ y == 123) : [8] -> [8] -> Bit) 235 | 51 31 = True 236 | Cryptol> 51 ^^ 31:[8] 237 | 123 238 | \end{verbatim} 239 | \section{Defining types} 240 | Type names typically start with capital letters. You can define a new type like this: 241 | \begin{verbatim} 242 | type NumChars = 26 243 | type Permutation=[NumChars]Char 244 | type Index=[7] 245 | \end{verbatim} 246 | Having defined this type, you can define functions that take 247 | arguments, or return values of that type. Your code becomes more 248 | readable with descriptive type names. 249 | \begin{verbatim} 250 | invertPermutation : Permutation -> Permutation 251 | invertPermutation perm = 252 | [ indexToChar (indexOf c perm) 253 | | c <- alphabet 254 | ] 255 | indexToChar : Index -> Char 256 | indexToChar i = (0b0 # i) + 'A' 257 | \end{verbatim} 258 | \section{Cryptol idioms} 259 | Pretty much everything you do in Cryptol should be operating on sequences. 260 | If you're tempted to call a function recursively, you'll probably be better served by refactoring your problem into recursive operations on sequences. Here's an idiomatic Fibonacci sequence in Cryptol: 261 | \begin{verbatim} 262 | fibs = [0,1] # 263 | [ a + b 264 | | a <- fibs 265 | | b <- drop`{1}fibs] 266 | take`{10}(fibs:[_][12]) 267 | // value: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 268 | (fibs:[_][64])@85 269 | // value: 0x039a9fadb327f099 270 | \end{verbatim} 271 | \begin{verbatim} 272 | \end{verbatim} 273 | 274 | \vskip 6\baselineskip 275 | This reference card is by Dylan McNamee, 276 | and is hosted on GitHub. See \verb+github.com/dylanmc/CryptoBook+ 277 | 278 | \end{document} 279 | -------------------------------------------------------------------------------- /src/cryptol/enigma.cry: -------------------------------------------------------------------------------- 1 | alphabet = [ 'A' .. 'Z' ] 2 | // ABCDEFGHIJKLMNOPQRSTUVWXYZ 3 | rotorIchars = "EKMFLGDQVZNTOWYHXUSPAIBRCJ" 4 | rotorIIchars = "AJDKSIRUXBLHWTMCQGZNPYFVOE" 5 | rotorIIIchars = "BDFHJLCPRTXVZNYEIWGAKMUSQO" 6 | rotorIVchars = "ESOVPZJAYQUIRHXLNFTGKDCMWB" // from Wikipedia Enigma_rotor_details 7 | rotorVchars = "VZBRGITYUPSDNHLXAWMJQOFECK" 8 | rotorVIchars = "JPGVOUMFYQBENHZRDKASXLICTW" 9 | rotorVIIchars = "NZJHGRCXMYSWBOUFAIVLPEKQDT" 10 | rotorVIIIchars = "FKQHTLXOCBJSPDZRAMEWNIUYGV" 11 | reflectorAchars = "EJMZALYXVBWFCRQUONTSPIKHGD" // permutation with rotor set to A 12 | reflectorBchars = "YRUHQSLDPXNGOKMIEBFZCWVJAT" 13 | reflectorCchars = "FVPJIAOYEDRZXWGCTKUQSBNMHL" 14 | 15 | notchI = (1 << asciiToIndex 'Q' ):[26] 16 | notchII = (1 << asciiToIndex 'E' ):[26] 17 | notchIII = (1 << asciiToIndex 'V' ):[26] 18 | 19 | offsetToChar : Offset -> Char 20 | offsetToChar o = 'A' + (0b0 # o) 21 | charToOffset : Char -> Offset 22 | charToOffset c = drop`{1}(c - 'A') 23 | 24 | // extract offsets from character permutation 25 | // stringToOffsets : {n} (fin n) => String n -> Offsets n 26 | stringToOffsets : String 26 -> Offsets 26 27 | stringToOffsets reflector = [ drop`{1}((26 + r - c) % 26) | c <- alphabet | r <- reflector ] 28 | 29 | reflectorAoff = stringToOffsets reflectorAchars 30 | reflectorBoff = stringToOffsets reflectorBchars 31 | reflectorCoff = stringToOffsets reflectorCchars 32 | 33 | rotorIoff, rotorIIoff, rotorIIIoff : Offsets 26 34 | rotorIoff = stringToOffsets rotorIchars 35 | rotorIIoff = stringToOffsets rotorIIchars 36 | rotorIIIoff = stringToOffsets rotorIIIchars 37 | rotorVIoff = stringToOffsets rotorVIchars 38 | rotorVIIIoff = stringToOffsets rotorVIIIchars 39 | 40 | rotorIrev = invertPermutation rotorIchars 41 | rotorIIrev = invertPermutation rotorIIchars 42 | rotorIIIrev = invertPermutation rotorIIIchars 43 | rotorVIrev = invertPermutation rotorVIchars 44 | rotorVIIIrev = invertPermutation rotorVIIIchars 45 | 46 | rotorIoffBwd = stringToOffsets rotorIrev 47 | rotorIIoffBwd = stringToOffsets rotorIIrev 48 | rotorIIIoffBwd = stringToOffsets rotorIIIrev 49 | rotorVIoffBwd = stringToOffsets rotorVIrev 50 | rotorVIIIoffBwd = stringToOffsets rotorVIIIrev 51 | 52 | sum ls = sums!0 where sums= [0] # [ (p + n) % 26 | p <- ls | n <- sums ] 53 | // sum reflectorBoff == 0 54 | // theorem: sum of any permutation offsets = 0? 55 | 56 | type Char = [8] 57 | type Offset = [7] 58 | type Rotor = [26](Offset,Offset,Bit) // fwd, rev, pin 59 | type Pins = [26]Bit 60 | type OffsetPerm = [26]Offset 61 | type CharPerm = [26]Char 62 | type Reflector = [26]Offset 63 | type ThreeRotors = [3]Rotor 64 | type Offsets n = [n]Offset 65 | type Swaps n = [n][2][8] 66 | type Rings n = Offsets n 67 | type InitialPosn n = Offsets n 68 | 69 | buildPlugboard : {n} (fin n, width n >= 1) => Swaps n -> [26][8] -> [width n] -> CharPerm 70 | buildPlugboard swaps permutation i = 71 | if i >= width swaps 72 | then permutation 73 | else buildPlugboard swaps swappedPerm (i + 1) where 74 | swappedPerm = doSwap (swaps@i) permutation 75 | 76 | // cryptol wibble: without parens above, got weird error 77 | 78 | doSwap : [2][8] -> [26][8] -> [26][8] 79 | doSwap [c, d] perm = perm2 where 80 | indexOfC = indexOf c perm 81 | indexOfD = indexOf d perm 82 | perm1 = [ if i == indexOfC then d else x | x <- perm | i <- [0..25]] 83 | perm2 = [ if i == indexOfD then c else x | x <- perm1 | i <- [0..25]] 84 | 85 | pinsI, pinsII, pinsIII, pinsVI, pinsVIII, zeroPins : Pins 86 | zeroPins = 0 87 | 88 | setBit : {a, b} (fin a, fin b, b >= 1) => [a] -> [b] -> [b] 89 | setBit b n = n || ((1 >>> 1) >> b) 90 | 91 | pinsI = setBit (indexOf 'Q' alphabet) zeroPins 92 | pinsII = setBit (indexOf 'E' alphabet) zeroPins 93 | pinsIII = setBit (indexOf 'V' alphabet) zeroPins 94 | pinsVI = zero // need to find this 95 | pinsVIII = zero // need to find this 96 | 97 | buildRotor : OffsetPerm -> OffsetPerm -> Pins -> Rotor 98 | buildRotor fwd rev bs = [ ( of, ob, b ) 99 | | of <- fwd 100 | | ob <- rev 101 | | b <- bs 102 | ] 103 | 104 | type EnigmaState = { 105 | rotors : ThreeRotors, 106 | reflector : Reflector, 107 | plugboard : CharPerm 108 | } 109 | 110 | // Basic Enigma state has Rings all at 1, Rotors at "AAA" 111 | buildBasicState : [3]OffsetPerm -> [3]OffsetPerm -> [3]Pins -> 112 | Reflector -> CharPerm -> EnigmaState 113 | buildBasicState fwdOffs revOffs pins refl plug = 114 | { rotors = rs, reflector = refl, plugboard = plug } where 115 | rs = [ buildRotor f b p 116 | | f <- fwdOffs 117 | | b <- revOffs 118 | | p <- pins 119 | ] 120 | 121 | buildEnigmaState : [3]OffsetPerm -> [3]OffsetPerm -> [3]Pins -> 122 | Reflector -> CharPerm -> Rings 3 -> String 3 -> EnigmaState 123 | buildEnigmaState fo bo pins refl plug rings key = 124 | { rotors = rs, 125 | reflector = refl, 126 | plugboard = plug } where 127 | rs0 = [ buildRotor (f >>> ring) (b >>> ring) p 128 | | f <- fo 129 | | b <- bo 130 | | ring <- rings 131 | | p <- pins 132 | ] 133 | rs = [ r <<< o | r <- rs0 | o <- keyOffs ] 134 | keyOffs = [ charToOffset c | c <- key ] 135 | 136 | // plugboard from FranklinHeath wiki: 137 | franklinHeathPlugboard = buildPlugboard 138 | ["AP","BR","CM","FZ","GJ","IL","NT","OV","QS","WX"] alphabet 0 139 | nullPlugboard = alphabet 140 | 141 | franklinHeathRings = [9,13,20] // "JNU" 142 | 143 | testEnigmaState = buildBasicState [ rotorIoff, rotorIIoff, rotorIIIoff ] 144 | [ rotorIoffBwd, rotorIIoffBwd, rotorIIIoffBwd ] 145 | [ pinsI, pinsII, pinsIII ] 146 | reflectorBoff 147 | nullPlugboard 148 | 149 | // these settings are in this Enigma Simulator URL 150 | // http://enigma.louisedade.co.uk/enigma.html?m3;b;b123;AJNU;AXYZ;AP-BR-CM-FZ-GJ-IL-NT-QS-WX 151 | 152 | // http://enigma.louisedade.co.uk/enigma.html?m3;b;b123;AJNU;AXYZ 153 | // QKTPEBZIUK -> GOODRESULT 154 | franklinHeathState = buildEnigmaState 155 | [ rotorIoff, rotorIIoff, rotorIIIoff ] 156 | [ rotorIoffBwd, rotorIIoffBwd, rotorIIIoffBwd ] 157 | [ pinsI, pinsII, pinsIII ] 158 | reflectorBoff 159 | franklinHeathPlugboard 160 | franklinHeathRings 161 | "VQQ" 162 | 163 | 164 | // http://enigma.louisedade.co.uk/enigma.html?m3;b;b123;AJNU;AVQQ;AP-BR-CM-FZ-GJ-IL-NT-OV-QS-WX 165 | // HABHVHLYDFNADZY -> THATSITWELLDONE 166 | 167 | getPins : ThreeRotors -> [3]Bit 168 | getPins rs = [ ((rs@0)@0).2, ((rs@1)@0).2, ((rs@2)@0).2 ] 169 | // rs@0 is the first rotor (type: [26](Char,Bit) 170 | // (rs@0)@0 is the first element of the first rotor (type: (Char,Bit) 171 | // ((rs@0)@0).0 is the character part of that first element (type: Char) 172 | // ((rs@0)@0).1 is the Pin part of that first element (type: Bit) 173 | 174 | // Cryptol wibble: shouldn't need parens above, @ should be 175 | // left-associate, and >= priority to "." 176 | 177 | 178 | getRotorRotations : ThreeRotors -> ([3]Bit, Bit) 179 | getRotorRotations rs = ([r1, r2, r3], rf) where 180 | pins = getPins rs 181 | r1 = pins@1 // only rotate when middle pin set 182 | r2 = pins@2 || pins@1 // rotate if middle or right pin set 183 | r3 = True // rightmost rotor always advances 184 | rf = reflAttachedToR1 && r1 185 | 186 | // some Enigmas, the Reflector is attached to R1, so it rotates along 187 | // with it. In most, though, the reflector never rotates. 188 | reflAttachedToR1 = False 189 | 190 | advanceRotor : Rotor -> Bit -> Rotor 191 | advanceRotor r b = if b then r <<< 1 else r 192 | 193 | advanceRotors : EnigmaState -> EnigmaState 194 | advanceRotors es = { rotors = newrs, reflector = newrefl, plugboard = es.plugboard} where 195 | newrs = [ advanceRotor r b 196 | | r <- es.rotors 197 | | b <- rbits 198 | ] 199 | (rbits, refbit) = getRotorRotations es.rotors 200 | newrefl = if refbit then es.reflector <<< 1 else es.reflector 201 | // to model a reflector attached to R1, we rotate the 202 | // reflector when R1 does 203 | 204 | rotorSequence es = sequence where 205 | sequence = [es] # [ advanceRotors ies | ies <- sequence ] 206 | 207 | // The double-step happens here: 208 | // > drop`{99}(rotorSequence testEnigmaState.rotors) 209 | 210 | doReflector : Reflector -> Offset -> Offset 211 | doReflector r o = (o + r@o) % 26 212 | 213 | asciiToIndex c = c - 'A' 214 | indexToAscii i = i + 'A' 215 | 216 | doRotorFwd, doRotorBwd : Rotor -> Offset -> Offset 217 | doRotorFwd rotor o = (o + (rotor @ o).0) % 26 218 | doRotorBwd rotor o = (o + (rotor @ o).1) % 26 219 | 220 | encryptOneChar : [26]Offset -> [26]Offset -> Char -> Char 221 | encryptOneChar rotor reflector inputChar = outputChar where 222 | inputOffset = charToOffset inputChar 223 | rotorO = rotor @ inputOffset 224 | reflO = reflector @ rotorO 225 | outputOffset = rotor @ reflO 226 | outputChar = offsetToChar outputOffset 227 | 228 | doOneRotor : Rotor -> Reflector -> Offset -> Offset 229 | doOneRotor rotor rOffsets o = doRotorBwd rotor (doReflector rOffsets (doRotorFwd rotor o)) 230 | 231 | indexOf c chars = candidates ! 0 where 232 | candidates = [ -1 ] # [ if c == s then i else prev 233 | | s <- chars 234 | | prev <- candidates 235 | | i <- [ 0 .. 25 ] 236 | ] 237 | 238 | invertPermutation : [26]Char -> [26]Char 239 | invertPermutation permutation = [ alphabet @ (indexOf c permutation) 240 | | c <- alphabet ] 241 | 242 | // encryptOneRotor : {n} (fin n) => Rotor -> Reflector -> String n -> String n 243 | encryptOneRotor rotor reflOf message = 244 | [ encryptOneChar (rotor <<< i) reflOf c 245 | | c <- message 246 | | i <- [1 .. 100] 247 | ] 248 | 249 | doTwoRotors r1 r2 refl c = 250 | doRotorBwd 251 | r2 252 | (doOneRotor 253 | r1 254 | refl 255 | (doRotorFwd r2 c)) 256 | 257 | doThreeRotors r1 r2 r3 refl c = 258 | doRotorBwd 259 | r3 260 | (doTwoRotors 261 | r1 262 | r2 263 | refl 264 | (doRotorFwd r3 c)) 265 | 266 | doPlugboard : CharPerm -> Char -> Char 267 | doPlugboard plugPerm c = plugPerm@(charToOffset c) 268 | 269 | doEnigma : {n} (fin n) => EnigmaState -> String n -> String n 270 | doEnigma es message = 271 | [ enigmaStep estate inChar 272 | | estate <- drop`{1}(rotorSequence es) 273 | | inChar <- message 274 | ] 275 | 276 | enigmaStep : EnigmaState -> Char -> Char 277 | enigmaStep es inC = doPlugboard es.plugboard (offsetToChar eno) where 278 | eno = doThreeRotors (es.rotors@0) (es.rotors@1) (es.rotors@2) 279 | es.reflector (charToOffset (doPlugboard es.plugboard inC)) 280 | 281 | // Cryptol wibble: without outer parens above, get awful error 282 | 283 | // encryptOneRotor (buildRotor rotorI zero) reflectorBoff "YMXOVPE" 284 | // "GOODJOB" 285 | 286 | enigmaManualPlugboard = buildPlugboard 287 | ["AM","FI","NV","PS","TU","WZ"] alphabet 0 288 | enigmaManualRings = [24,13,22] 289 | enigmaManualState = buildEnigmaState 290 | [ rotorIIoff, rotorIoff, rotorIIIoff ] 291 | [ rotorIIoffBwd, rotorIoffBwd, rotorIIIoffBwd ] 292 | [ pinsII, pinsI, pinsIII ] 293 | reflectorAoff 294 | enigmaManualPlugboard 295 | enigmaManualRings 296 | "ABL" 297 | enigmaManualMessage="GCDSEAHUGWTQGRKVLFGXUCALXVYMIGMMNMFDXTGNVHVRMMEVOUYFZSLRHDRRXFJWCFHUHMUNZEFRDISIKBGPMYVXUZ" 298 | 299 | scharnhorstPlugboard = buildPlugboard 300 | ["AN","EZ","HK","IJ","LR","MQ","OT","PV","SW","UX"] alphabet 0 301 | scharnhorstRings = [01,08,13] 302 | scharnhorstState = buildEnigmaState 303 | [ rotorIIIoff, rotorVIoff, rotorVIIIoff ] 304 | [ rotorIIIoffBwd, rotorVIoffBwd, rotorVIIIoffBwd ] 305 | [ pinsIII, pinsVI, pinsVIII ] 306 | reflectorBoff 307 | scharnhorstPlugboard 308 | scharnhorstRings 309 | "UZV" 310 | scharnhorstMessage = "YKAENZAPMSCHZBFOCUVMRMDPYCOFHADZIZMEFXTHFLOLPZLFGGBOTGOXGRETDWTJIQHLMXVJWKZUASTR" 311 | 312 | fhKeyAAAState = buildEnigmaState 313 | [ rotorIoff, rotorIIoff, rotorIIIoff ] 314 | [ rotorIoffBwd, rotorIIoffBwd, rotorIIIoffBwd ] 315 | [ pinsI, pinsII, pinsIII ] 316 | reflectorBoff 317 | nullPlugboard 318 | franklinHeathRings 319 | "AAA" 320 | -------------------------------------------------------------------------------- /src/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # CryptoBook documentation build configuration file, created by 5 | # sphinx-quickstart on Mon Nov 7 09:45:04 2016. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | # import os 21 | # import sys 22 | # sys.path.insert(0, os.path.abspath('.')) 23 | 24 | # -- General configuration ------------------------------------------------ 25 | 26 | # If your documentation needs a minimal Sphinx version, state it here. 27 | # 28 | # needs_sphinx = '1.0' 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | 'sphinx.ext.todo', 35 | 'sphinx.ext.mathjax', 36 | 'sphinx.ext.githubpages', 37 | ] 38 | 39 | # Add any paths that contain templates here, relative to this directory. 40 | templates_path = ['.templates'] 41 | 42 | # The suffix(es) of source filenames. 43 | # You can specify multiple suffix as a list of string: 44 | # 45 | # source_suffix = ['.rst', '.md'] 46 | source_suffix = '.rst' 47 | 48 | # The encoding of source files. 49 | # 50 | source_encoding = 'utf-8-sig' 51 | # source_encoding = 'iso-8859-15' 52 | 53 | # The master toctree document. 54 | master_doc = 'book' 55 | 56 | # General information about the project. 57 | project = 'CryptoBook' 58 | copyright = '2017, Dylan McNamee' 59 | author = 'Dylan McNamee' 60 | 61 | # The version info for the project you're documenting, acts as replacement for 62 | # |version| and |release|, also used in various other places throughout the 63 | # built documents. 64 | # 65 | # The short X.Y version. 66 | version = '1.0' 67 | # The full version, including alpha/beta/rc tags. 68 | release = '1' 69 | 70 | # The language for content autogenerated by Sphinx. Refer to documentation 71 | # for a list of supported languages. 72 | # 73 | # This is also used if you do content translation via gettext catalogs. 74 | # Usually you set "language" from the command line for these cases. 75 | language = None 76 | 77 | # There are two options for replacing |today|: either, you set today to some 78 | # non-false value, then it is used: 79 | # 80 | # today = '' 81 | # 82 | # Else, today_fmt is used as the format for a strftime call. 83 | # 84 | # today_fmt = '%B %d, %Y' 85 | 86 | # List of patterns, relative to source directory, that match files and 87 | # directories to ignore when looking for source files. 88 | # This patterns also effect to html_static_path and html_extra_path 89 | exclude_patterns = ['.build', 'Thumbs.db', '.DS_Store'] 90 | 91 | # The reST default role (used for this markup: `text`) to use for all 92 | # documents. 93 | # 94 | # default_role = None 95 | 96 | # If true, '()' will be appended to :func: etc. cross-reference text. 97 | # 98 | # add_function_parentheses = True 99 | 100 | # If true, the current module name will be prepended to all description 101 | # unit titles (such as .. function::). 102 | # 103 | # add_module_names = True 104 | 105 | # If true, sectionauthor and moduleauthor directives will be shown in the 106 | # output. They are ignored by default. 107 | # 108 | # show_authors = False 109 | 110 | # The name of the Pygments (syntax highlighting) style to use. 111 | pygments_style = 'sphinx' 112 | 113 | # A list of ignored prefixes for module index sorting. 114 | # modindex_common_prefix = [] 115 | 116 | # If true, keep warnings as "system message" paragraphs in the built documents. 117 | # keep_warnings = False 118 | 119 | # If true, `todo` and `todoList` produce output, else they produce nothing. 120 | todo_include_todos = True 121 | 122 | 123 | # -- Options for HTML output ---------------------------------------------- 124 | 125 | # The theme to use for HTML and HTML Help pages. See the documentation for 126 | # a list of builtin themes. 127 | # 128 | html_theme = 'alabaster' 129 | 130 | # Theme options are theme-specific and customize the look and feel of a theme 131 | # further. For a list of options available for each theme, see the 132 | # documentation. 133 | # 134 | # html_theme_options = {} 135 | 136 | # Add any paths that contain custom themes here, relative to this directory. 137 | # html_theme_path = [] 138 | 139 | # The name for this set of Sphinx documents. 140 | # " v documentation" by default. 141 | # 142 | # html_title = 'CryptoBook v1.0a1' 143 | 144 | # A shorter title for the navigation bar. Default is the same as html_title. 145 | # 146 | # html_short_title = None 147 | 148 | # The name of an image file (relative to this directory) to place at the top 149 | # of the sidebar. 150 | # 151 | # html_logo = None 152 | 153 | # The name of an image file (relative to this directory) to use as a favicon of 154 | # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 155 | # pixels large. 156 | # 157 | # html_favicon = None 158 | 159 | # Add any paths that contain custom static files (such as style sheets) here, 160 | # relative to this directory. They are copied after the builtin static files, 161 | # so a file named "default.css" will overwrite the builtin "default.css". 162 | html_static_path = ['.static'] 163 | 164 | # Add any extra paths that contain custom files (such as robots.txt or 165 | # .htaccess) here, relative to this directory. These files are copied 166 | # directly to the root of the documentation. 167 | # 168 | # html_extra_path = [] 169 | 170 | # If not None, a 'Last updated on:' timestamp is inserted at every page 171 | # bottom, using the given strftime format. 172 | # The empty string is equivalent to '%b %d, %Y'. 173 | # 174 | # html_last_updated_fmt = None 175 | 176 | # If true, SmartyPants will be used to convert quotes and dashes to 177 | # typographically correct entities. 178 | # 179 | # html_use_smartypants = True 180 | 181 | # Custom sidebar templates, maps document names to template names. 182 | # 183 | # html_sidebars = {} 184 | 185 | # Additional templates that should be rendered to pages, maps page names to 186 | # template names. 187 | # 188 | # html_additional_pages = {} 189 | 190 | # If false, no module index is generated. 191 | # 192 | # html_domain_indices = True 193 | 194 | # If false, no index is generated. 195 | # 196 | # html_use_index = True 197 | 198 | # If true, the index is split into individual pages for each letter. 199 | # 200 | # html_split_index = False 201 | 202 | # If true, links to the reST sources are added to the pages. 203 | # 204 | # html_show_sourcelink = True 205 | 206 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 207 | # 208 | # html_show_sphinx = True 209 | 210 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 211 | # 212 | # html_show_copyright = True 213 | 214 | # If true, an OpenSearch description file will be output, and all pages will 215 | # contain a tag referring to it. The value of this option must be the 216 | # base URL from which the finished HTML is served. 217 | # 218 | # html_use_opensearch = '' 219 | 220 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 221 | # html_file_suffix = None 222 | 223 | # Language to be used for generating the HTML full-text search index. 224 | # Sphinx supports the following languages: 225 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' 226 | # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh' 227 | # 228 | # html_search_language = 'en' 229 | 230 | # A dictionary with options for the search language support, empty by default. 231 | # 'ja' uses this config value. 232 | # 'zh' user can custom change `jieba` dictionary path. 233 | # 234 | # html_search_options = {'type': 'default'} 235 | 236 | # The name of a javascript file (relative to the configuration directory) that 237 | # implements a search results scorer. If empty, the default will be used. 238 | # 239 | # html_search_scorer = 'scorer.js' 240 | 241 | # Output file base name for HTML help builder. 242 | htmlhelp_basename = 'CryptoBookdoc' 243 | 244 | # -- Options for LaTeX output --------------------------------------------- 245 | 246 | latex_engine = 'xelatex' 247 | latex_elements = { 248 | 'fontenc': '\\usepackage{fontspec}', 249 | 'fontpkg': '''\ 250 | \\setmainfont{Linux Libertine O} 251 | \\setsansfont{Optima} 252 | \\setmonofont[Scale=0.8]{Menlo}''', 253 | 254 | 'geometry': '\\usepackage[paperheight=8.5in, paperwidth=5.5in, vmargin=2.5cm, inner=2.5cm, outer=2.5cm]{geometry}', 255 | 'printindex': '\\footnotesize\\raggedright\\printindex', 256 | 257 | # Font can also be Times/Helvetica, or whatever you have & like. 258 | # I got the idea for using Libertine from the SICP PDF, link 259 | # here: https://github.com/sarabander/sicp-pdf 260 | 261 | # The paper size ('letterpaper' or 'a4paper'). 262 | # 263 | # 'papersize': 'letterpaper', 264 | # 'papersize': 'a5paper', 265 | # if you prefer a5paper (live in a sane part of the paper world), 266 | # remove the paperwidth/height directives from geometry above, 267 | # and select a5paper. 268 | 269 | # The font size ('10pt', '11pt' or '12pt'). 270 | # 271 | # 'pointsize': '10pt', 272 | 273 | # Additional stuff for the LaTeX preamble. 274 | # 275 | # preamble': '', 276 | 277 | # Latex figure (float) alignment 278 | # 279 | # 'figure_align': 'htbp', 280 | } 281 | 282 | # Grouping the document tree into LaTeX files. List of tuples 283 | # (source start file, target name, title, 284 | # author, documentclass [howto, manual, or own class]). 285 | latex_documents = [ 286 | (master_doc, 'CryptoBook.tex', 'Cryptography, Math and Programming', 287 | 'Dylan McNamee', 'manual'), 288 | ] 289 | 290 | # The name of an image file (relative to this directory) to place at the top of 291 | # the title page. 292 | # 293 | # latex_logo = None 294 | 295 | # For "manual" documents, if this is true, then toplevel headings are parts, 296 | # not chapters. 297 | # 298 | # latex_use_parts = False 299 | 300 | # If true, show page references after internal links. 301 | # 302 | # latex_show_pagerefs = False 303 | 304 | # If true, show URL addresses after external links. 305 | # 306 | # latex_show_urls = False 307 | 308 | # Documents to append as an appendix to all manuals. 309 | # 310 | # latex_appendices = [] 311 | 312 | # It false, will not define \strong, \code, itleref, \crossref ... but only 313 | # \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added 314 | # packages. 315 | # 316 | # latex_keep_old_macro_names = True 317 | 318 | # If false, no module index is generated. 319 | # 320 | # latex_domain_indices = True 321 | 322 | 323 | # -- Options for manual page output --------------------------------------- 324 | 325 | # One entry per manual page. List of tuples 326 | # (source start file, name, description, authors, manual section). 327 | man_pages = [ 328 | (master_doc, 'cryptobook', 'Cryptography, Math and Programming', 329 | [author], 1) 330 | ] 331 | 332 | # If true, show URL addresses after external links. 333 | # 334 | # man_show_urls = False 335 | 336 | 337 | # -- Options for Texinfo output ------------------------------------------- 338 | 339 | # Grouping the document tree into Texinfo files. List of tuples 340 | # (source start file, target name, title, author, 341 | # dir menu entry, description, category) 342 | texinfo_documents = [ 343 | (master_doc, 'CryptoBook', 'Cryptography, Math and Programming', 344 | author, 'CryptoBook', 'An introduction to cryptography, math and programming (in Crytpol and maybe Python).', 345 | 'Miscellaneous'), 346 | ] 347 | 348 | # Documents to append as an appendix to all manuals. 349 | # 350 | # texinfo_appendices = [] 351 | 352 | # If false, no module index is generated. 353 | # 354 | # texinfo_domain_indices = True 355 | 356 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 357 | # 358 | # texinfo_show_urls = 'footnote' 359 | 360 | # If true, do not generate a @detailmenu in the "Top" node's menu. 361 | # 362 | # texinfo_no_detailmenu = False 363 | 364 | 365 | # -- Options for Epub output ---------------------------------------------- 366 | 367 | # Bibliographic Dublin Core info. 368 | epub_title = project 369 | epub_author = author 370 | epub_publisher = author 371 | epub_copyright = copyright 372 | 373 | # The basename for the epub file. It defaults to the project name. 374 | # epub_basename = project 375 | 376 | # The HTML theme for the epub output. Since the default themes are not 377 | # optimized for small screen space, using the same theme for HTML and epub 378 | # output is usually not wise. This defaults to 'epub', a theme designed to save 379 | # visual space. 380 | # 381 | # epub_theme = 'epub' 382 | 383 | # The language of the text. It defaults to the language option 384 | # or 'en' if the language is not set. 385 | # 386 | # epub_language = '' 387 | 388 | # The scheme of the identifier. Typical schemes are ISBN or URL. 389 | # epub_scheme = '' 390 | 391 | # The unique identifier of the text. This can be a ISBN number 392 | # or the project homepage. 393 | # 394 | # epub_identifier = '' 395 | 396 | # A unique identification for the text. 397 | # 398 | # epub_uid = '' 399 | 400 | # A tuple containing the cover image and cover page html template filenames. 401 | # 402 | # epub_cover = () 403 | 404 | # A sequence of (type, uri, title) tuples for the guide element of content.opf. 405 | # 406 | # epub_guide = () 407 | 408 | # HTML files that should be inserted before the pages created by sphinx. 409 | # The format is a list of tuples containing the path and title. 410 | # 411 | # epub_pre_files = [] 412 | 413 | # HTML files that should be inserted after the pages created by sphinx. 414 | # The format is a list of tuples containing the path and title. 415 | # 416 | # epub_post_files = [] 417 | 418 | # A list of files that should not be packed into the epub file. 419 | epub_exclude_files = ['search.html'] 420 | 421 | # The depth of the table of contents in toc.ncx. 422 | # 423 | # epub_tocdepth = 3 424 | 425 | # Allow duplicate toc entries. 426 | # 427 | # epub_tocdup = True 428 | 429 | # Choose between 'default' and 'includehidden'. 430 | # 431 | # epub_tocscope = 'default' 432 | 433 | # Fix unsupported image types using the Pillow. 434 | # 435 | # epub_fix_images = False 436 | 437 | # Scale large images. 438 | # 439 | # epub_max_image_width = 0 440 | 441 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 442 | # 443 | # epub_show_urls = 'inline' 444 | 445 | # If false, no index is generated. 446 | # 447 | # epub_use_index = True 448 | -------------------------------------------------------------------------------- /src/04_morecomplex.rst: -------------------------------------------------------------------------------- 1 | Implementing More Complex Programs 2 | ================================== 3 | 4 | At this point, you've written some Cryptol at the command-line, but if 5 | you had to leave your machine, reboot, or whatever, you had to start 6 | from scratch. "That's no good", I hear you say, "there must be another 7 | way!" Indeed there is. 8 | 9 | Storing Cryptol programs in files 10 | --------------------------------- 11 | 12 | In addition to typing commands at the Cryptol interpreter, Cryptol can 13 | load files that have programs in them. Programs are slightly different 14 | from the commands you've been typing so far. The main difference is that 15 | you don't need ``let`` when you're defining a variable (like 16 | ``alphabet``) or a function (like ``encrypt``). 17 | 18 | Creating a text file in a project directory 19 | ------------------------------------------- 20 | 21 | .. index:: text file, text editors 22 | 23 | The next thing you'll want to do is create a directory (or folder) to 24 | keep your project files for this book. You'll need to figure out how to 25 | edit *text files* on your computer. Text files are different from, say, 26 | word processing documents, in that they do not have any formatting (no 27 | **bold** or *italics*, for example). They're literally just sequences of 28 | ASCII characters (or UTF-8 if you have a fancy editor). The command-line 29 | programs ``vim`` and ``emacs`` are still popular, even though they look 30 | like Wargames-era technology\ [#]_. More modern text editors include 31 | *Sublime Text* (``https://www.sublimetext.com/``), *nano* 32 | (``https://www.nano-editor.org/``), and many others. If you're on 33 | Windows, and are in a pinch, both *Notepad* and *Wordpad* can "Save As" 34 | *plain text*. 35 | 36 | .. [#] no coincidence, either: the original versions of these programs 37 | were written almost 10 years before Wargames came out. They're still 38 | popular because they're very powerful, but that's a lesson for another 39 | book. 40 | 41 | Exercise: rewriting our Caesar cipher program 42 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 43 | 44 | Start this exercise by creating your project directory. On a Unix 45 | systems (like Linux or MacOS), you'll want to start up a Terminal 46 | window, on Windows start a shell window (type ``cmd`` in the search 47 | bar), and type something like this: 48 | 49 | .. code-block:: console 50 | 51 | $ mkdir CryptoBook 52 | $ cd CryptoBook 53 | 54 | Then, using whichever text editor you choose, create a file called 55 | ``caesar.cry`` inside that directory. It should contain the following: 56 | 57 | .. code-block:: cryptol 58 | 59 | // Caesar cipher 60 | alphabet = ['a' .. 'z'] 61 | toLower c = if c < 'a' then c + 0x20 else c 62 | asciiToIndex c = (toLower c) - 'a' 63 | 64 | encryptChar wheel c = if c == ' ' 65 | then c 66 | else wheel @ (asciiToIndex c) 67 | 68 | codeWheel key = reverse alphabet >>> key 69 | 70 | encrypt key message = 71 | [ encryptChar (codeWheel key) c | c <- message ] 72 | 73 | decrypt key message = encrypt key message 74 | 75 | The first line (``// Caesar cipher``) is a comment: it's text to remind 76 | you what's in the file. With our more complex programs, we'll add more 77 | comments. They'll help remind us what's going on. 78 | 79 | Running Cryptol with ``caesar.cry`` 80 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 81 | 82 | Now that we have a file with our Caesar cipher in it. To run that 83 | program, launch Cryptol from inside your project directory but include 84 | the name of the file you want it to load, like this: 85 | 86 | 87 | .. code-block:: console 88 | 89 | $ cryptol caesar.cry 90 | _ _ 91 | ___ _ __ _ _ _ __ | |_ ___ | | 92 | / __| '__| | | | '_ \| __/ _ \| | 93 | | (__| | | |_| | |_) | || (_) | | 94 | \___|_| \__, | .__/ \__\___/|_| 95 | |___/|_| version 2.4.0 96 | 97 | Loading module Cryptol 98 | Loading module Main 99 | 100 | Main> encrypt 11 "using files now" 101 | 102 | [warning] at :1:1--1:28: 103 | Defaulting type parameter 'bits' 104 | of literal or demoted expression 105 | at :1:9--1:10 106 | to 3 107 | [0x6a, 0x6c, 0x76, 0x71, 0x78, 0x20, 0x79, 0x76, 108 | 0x73, 0x7a, 0x6c, 0x20, 0x71, 0x70, 0x68] 109 | 110 | Whoops, we still have to turn on ASCII output. If you got 111 | ``[error] can't find file: caesar.cry`` instead, then you need to use a 112 | shell command to move into your CryptoBook directory. If that's proving 113 | difficult, ask a partner or Google for *command line navigating files* 114 | for the operating system you're running on. 115 | 116 | Let's see our encrypted string: 117 | 118 | .. code-block:: console 119 | 120 | Main> :set ascii=on 121 | Main> encrypt 4 "using files now" 122 | "jlvqx yvszl qph" 123 | 124 | Hooray! You'll never have to type the Caesar cipher again. 125 | 126 | Exercise: motivating stronger encryption 127 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 128 | 129 | Now that you can have a program perform the Caesar cipher for you, it's 130 | a simple thing to write a program that cracks a message that has been 131 | encoded with the Caesar cipher: just try all possible keys, and see 132 | which one decodes into an intelligible message. 133 | 134 | But before using brute force, let's look at the following encoded 135 | message, and see if there are any clues to decryption: 136 | 137 | :: 138 | 139 | "seh zldy wuxkahz pdse seh jlhtlu jdwehu dt sehuh 140 | luh xyan sphysn tdo wxttdkah bhnt" 141 | 142 | Before reading further, come up with two approaches you'd take to 143 | decrypting this message, and try them out. 144 | 145 | Now that you've done that approach, use brute force to crack this 146 | message: 147 | 148 | :: 149 | 150 | "wlszknzlosgeyfzueyalknzqlsfmoaosqlhozzob" 151 | 152 | If you don't know how to start, think about using a sequence 153 | comprehension, where each element of the sequence is a decryption of 154 | the message using a different key. For the Caesar cipher, the keys to 155 | try would be ``[ 1 .. 25 ]``, right? 156 | 157 | Implementing our next cipher: Vigenère 158 | -------------------------------------- 159 | 160 | .. index:: Vigenère cipher 161 | 162 | Given the previous exercise (please actually do it -- it's a lot of fun, 163 | and very informative), it's probably occurred to you that the Caesar 164 | cipher leaves a lot of room for improvement. You may have even thought 165 | of some changes to the Caesar cipher that would make it harder to crack, 166 | given the tools you've already developed. 167 | 168 | Since we have brute force as an option, the main way to combat that 169 | attack is to greatly increase the number of guesses a brute force 170 | attacker will have to try. A simple approach to doing this is to have 171 | the key be a sequence of shift amounts. This is essentially the idea 172 | behind the Vigenère cipher. It was so successful at thwarting 173 | decryption, it was used for almost 300 years - from the 1500's through 174 | the 1800's, and was known for a lot of that time as "the unbreakable 175 | cipher". 176 | 177 | Here's how it works: 178 | 179 | Take a plaintext message, like "how do you like my fancy new cipher" and 180 | a key, like "thisismyfancykey", and to encrypt the i\ :sup:`th` 181 | character, use the Caesar cipher with the i\ :sup:`th` character of the 182 | key to specify the shift amount. To translate an ASCII key into a shift 183 | amount, we do the classic "subtract the ASCII value of ``a`` from the 184 | ASCII value of the key character". 185 | 186 | .. index:: 187 | single: ! modulo arithmetic 188 | 189 | The last detail is what to do if the message is longer than the key. 190 | What the Vigenère cipher does in this case is to "wrap around" to the 191 | first character of the key, and so on. In mathematical terms, this is 192 | known as *modulo arithmetic*. You're already familiar with modulo 193 | arithmetic from how we read clocks: there are 24 hours in a day, but our 194 | clocks only go to 12. For the hour past noon (or midnight) we "wrap 195 | around" to 1, and the next hour is 2, and so on. 196 | 197 | .. index:: 198 | single: key expansion 199 | single: infinite sequences 200 | 201 | Cryptol offers us a couple ways of expressing this notion of wrapping 202 | around the key. The first one is to use modulo arithmetic on the index. 203 | The second one is to create an *infinite sequence*, which consists of 204 | the key appended to itself over and over. Using this infinite sequence, 205 | we never have to worry about running out of key. This latter technique 206 | is a simple version of what we call *key expansion* in more 207 | sophisticated ciphers. Here's one way to implement the Vigenère key 208 | expansion in Cryptol: 209 | 210 | ``expandKey key = key # expandKey key`` 211 | 212 | .. index:: recursion 213 | 214 | In that one line of code, there are a number of things to explain! 215 | First, it seems a bit magic (or cheating) that we're using ``expandKey`` 216 | in the definition of ``expandKey``. This trick is a technique in 217 | programming called *recursion*. (POINT AT A RECURSION SECTION / 218 | RESOURCE) 219 | 220 | The second thing we need to explain is "how / why this doesn't run 221 | forever, as soon as you expand any key - we haven't told Cryptol ever to 222 | stop!" That's right, we haven't, but let's give it a try anyway. First, 223 | copy your ``caesar.cry`` into a new file called ``vigenere.cry`` 224 | (because we'd like to reuse a lot of the code in ``caesar.cry``, and I 225 | promised you wouldn't have to type it in again). Second, add the above 226 | definition of ``expandKey`` to the end of your ``vigenere.cry`` Finally, 227 | start up Cryptol: 228 | 229 | .. code-block:: console 230 | 231 | $ cryptol vigenere.cry 232 | _ _ 233 | ___ _ __ _ _ _ __ | |_ ___ | | 234 | / __| '__| | | | '_ \| __/ _ \| | 235 | | (__| | | |_| | |_) | || (_) | | 236 | \___|_| \__, | .__/ \__\___/|_| 237 | |___/|_| version 2.4.0 238 | 239 | Loading module Cryptol 240 | Loading module Main 241 | 242 | Main> :set ascii=on 243 | Main> let myXkey = expandKey "HELLO" 244 | Main> myXkey 245 | ['H', 'E', 'L', 'L', 'O', ...] 246 | Main> myXkey@1000 247 | 'H' 248 | Main> myXkey@1001 249 | 'E' 250 | 251 | Let's go through that line-by-line. First, we ``:set ascii=on`` so we can 252 | see the ASCII key strings. Second, we defined a temporary variable 253 | ``myXkey`` to be the result of expanding ``"HELLO"``. Next we asked 254 | Cryptol to show it to us. But rather uninterestingly, it just showed us 255 | the first five characters, but at the end it shows "...", signifying the 256 | list goes on. So, we decide to test Cryptol's expansion by indexing our 257 | ``myXkey`` at index 1000, which happens to be an ``'H'``, and then the 258 | next one, 1001, which is the expected ``'E'``. So far, so good! 259 | 260 | .. index:: 261 | single: parallel comprehension 262 | single: sequence comprehension 263 | 264 | The last Cryptol feature you'll need to learn in order to implement the 265 | Vigenère cipher is how to access two sequences at once in a sequence 266 | comprehension. We need this because we need to access both the next 267 | character of the expanded key stream and of the message in order to 268 | produce the next character of the ciphertext. Cryptol's way of doing 269 | this is called a *parallel comprehension*, and it looks like this:\ [#]_ 270 | 271 | .. [#] Note the \\'s - you can either type this all on one line, or 272 | use \\'s and include newlines where they appear here. 273 | 274 | :: 275 | 276 | Main> [ encryptChar (codeWheel k) c \ 277 | | c <- "hi there" \ 278 | | k <- expandKey [0 .. 10] ] 279 | "ss jwaoc" 280 | 281 | One way to think of how parallel comprehensions work is like a zipper, 282 | When you zip up your jacket, the pull joins the elements (teeth) from 283 | each side and combines them (zips the teeth together). The length of the 284 | resulting sequence is the shorter of the two lengths of the sides of the 285 | zipper. In this case, it's the length of our message, "hi there", 286 | because our expanded key has infinite length. 287 | 288 | :: 289 | 290 | h i t h e r e 291 | 0 1 2 3 4 5 6 7 8 9 10 0 1 ... 292 | -> zip along the elements (TODO: make this pretty) 293 | 294 | .. index:: lazy evaluation 295 | 296 | This also explains how Cryptol doesn't have to run forever when you ask 297 | it to define an infinitely expanded key: it only evaluates elements of a 298 | list as you ask for them. As long as you ask for only a finite number of 299 | them, Cryptol only evaluates that many of them. This way of approaching 300 | infinite sequences and "evaluate on-demand" is called *lazy evaluation*; 301 | it's a really powerful feature of Cryptol, and you'll see it's used 302 | quite a bit. 303 | 304 | This is *almost* the Vigenère cipher: we're shifting our plaintext a 305 | different amount each time, but we're getting the shift amount from 306 | ``[0 .. 10]`` repeated, instead of a key string turned into indexes. 307 | 308 | See if you can finish the implementation of the Vigenère cipher based on 309 | what you know about Cryptol now. 310 | 311 | It should start like this: 312 | 313 | :: 314 | 315 | vigenere key message = 316 | ... you fill in the rest 317 | 318 | Exercises 319 | ~~~~~~~~~ 320 | 321 | 1. Use your implementation of the Vigenère cipher to encode and decode 322 | some messages. Notice some of the improvements using longer keys 323 | makes. 324 | 325 | 2. Decrypt the following message using the key: ``"thisphraseismykey"`` 326 | 327 | ``"qrucuvso dtoezje yzspd yordwt llsarvnij jzrwyam"`` 328 | 329 | .. index: known plaintext attack 330 | 331 | 3. One kind of attack against a code is when you know what some or all 332 | of a message is, and use that knowledge to learn something about the 333 | key. This was used during World War II when the Allied cryptanalysts 334 | guessed the word "weather" would appear in a German message that was 335 | encrypted with the Enigma machine. This technique is called a *known 336 | plaintext attack*. 337 | 338 | Think about how you could learn the key used in a Vigenère-encrypted 339 | message if you knew that a message started with the plaintext 340 | ``"At the tone the time will be...".`` started with the following 341 | ciphertext: ``"gg njc fyjg doa joec jyfv xi"``. 342 | 343 | What we learned this chapter 344 | ---------------------------- 345 | 346 | We started by learning how to program in Cryptol using files, and how to 347 | run Cryptol using a file you wrote. Next, we discussed some of the 348 | weaknesses of the Caesar cipher, and even did some codebreaking that 349 | uses those weaknesses. This lead to a discussion of increasing key 350 | length, which is exactly what the Vigenère cipher does. We learned about 351 | *key expansion*, and did it in Cryptol using *recursion*. We combined 352 | the expanded key with the message using *parallel comprehensions*, and 353 | learned that Cryptol uses *lazy evaluation* to avoid infinite loops when 354 | sequences are infinitely long. Finally, you used the techniques learned 355 | in this chapter to implement your own Vigenère cipher. The exercises 356 | gave you a chance to exercise your new code, and learn about the *known 357 | plaintext* technique to learn a key from an encoded message. 358 | -------------------------------------------------------------------------------- /src/06_enigmacomplete.rst: -------------------------------------------------------------------------------- 1 | Completing the Enigma in Cryptol 2 | ================================ 3 | 4 | .. maybe-note: *This chapter can be skipped the first time through if you're 5 | impatient. The Enigma is really cool, though, and there are some 6 | neat programming techniques in here, so make sure you come back to 7 | this chapter later on.* 8 | 9 | Compared to our paper Enigma (and the real thing), our Cryptol version 10 | lacks: 11 | 12 | #) Multiple rotors, 13 | 14 | #) *pins* that control stepping the rotors, 15 | 16 | #) the *rings* that control where the pins start, and 17 | 18 | #) the *plugboard,* which modifies the I/O ring. 19 | 20 | Let's implement them! 21 | 22 | Combining multiple rotors 23 | -------------------------- 24 | 25 | Get our your paper Enigma and set Rotor II and Rotor 26 | III to ``A``. Then for each of them, trace, from the right towards the left, each 27 | letter from ``A .. Z`` just like we did for Rotor I in the 28 | previous chapter. Starting with Rotor II (the middle one), you'll 29 | see that the line from ``A`` goes straight across to ``A``, so 30 | the first letter in that rotor is just ``A``. 31 | 32 | As a starting point, here are the first few entries for rotors ``II`` 33 | and ``III``: 34 | 35 | .. code-block:: console 36 | 37 | rotorIIchars = "AJD ..." 38 | rotorIIIchars = "BDF ..." 39 | 40 | Once you complete the rotor strings, the next job is to combine them 41 | in the encryption function. One annoying thing that you may have noticed in our 42 | ``encryptOneRotor`` function is when we had to individually rotate the 43 | ``rotorOff`` and ``rotorRevOff`` sequences. Let's create a data 44 | structure that lets us deal with an entire rotor (and its reverse) at 45 | the same time: 46 | 47 | .. literalinclude:: cryptol/threeRotors.cry 48 | :language: cryptol 49 | :start-after: BeginRotorType 50 | :end-before: EndRotorType 51 | 52 | .. index:: 53 | single: tuple 54 | 55 | This declares ``RotorElement`` to be a *tuple*, which is a 56 | comma-separated list of items inside parentheses. Unlike a sequence, 57 | whose elements all have to be the same type, the elements of a tuple 58 | can have different types--in this case, ``Offset`` and ``Bit``. The ``Bit`` at the 59 | end is for the Rings, which we'll deal with in the next section. 60 | To create a rotor from the characters we carefully traced, we need a helper function, 61 | ``buildRotor``: 62 | 63 | .. literalinclude:: cryptol/threeRotors.cry 64 | :language: cryptol 65 | :start-after: BeginRotorDef 66 | :end-before: EndRotorDef 67 | 68 | .. index:: 69 | single: refactor 70 | 71 | Returning to how the multi-rotor Enigma works, and thinking about 72 | what we've written so far, our one-rotor Enigma is the left-hand half 73 | of the 3-ring Enigma: the Reflector and first Rotor. We need to add 74 | two more rotors to it. It's not quite as simple as that, though, 75 | because our ``encryptOneRotor`` function takes a Char as input, and 76 | returns a Char as output, but if we want to connect our rotors 77 | together, the type of data that flows between them is ``Index``, not 78 | ``Char``. So we'll need to *refactor* our code a bit so that it's more 79 | modular. 80 | 81 | .. literalinclude:: cryptol/threeRotors.cry 82 | :language: cryptol 83 | :start-after: BeginReflectorDef 84 | :end-before: EndReflectorDef 85 | 86 | Let's start with 87 | our function that implements one rotor and the reflector. 88 | If we want to add another rotor to our Enigma, we can call our 89 | ``doOneRotor`` function as a helper. First we go through our new 90 | rotor forwards, then call the ``doOneRotor`` function, then use the 91 | output of that, and go through our rotor backwards. 92 | 93 | Exercise: write the three rotor function 94 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 95 | Follow the pattern established above, and write ``doThreeRotors``. 96 | It should start off like this: 97 | 98 | .. code-block:: console 99 | 100 | doThreeRotors refl r1 r2 r3 c = 101 | 102 | Make sure you use ``doTwoRotors``, and keep track of how many 103 | arguments it takes and what they are. 104 | 105 | .. answer: 106 | doThreeRotors refl r1 r2 r3 i = 107 | doRotorRev r3 (doTwoRotors refl r1 r2 108 | (doRotorFwd r3 i)) 109 | 110 | We can wrap this function with another function that translates a 111 | ``Char`` to ``Index`` and back again so that we can test our code: 112 | 113 | .. code-block:: cryptol 114 | 115 | doOneChar c refl r1 r2 r3 = 116 | indexToChar ( doThreeRotors refl r1 r2 r3 (charToIndex c)) 117 | 118 | Now we can encode single characters with the three rotor Enigma code, 119 | and compare it to our cardboard Enigma. 120 | As a test, set all three rotors to ``A``, and make sure 121 | that encoding ``A`` results in ``U``, and ``B`` goes to ``E``. If you 122 | don't get those results, or if your program loads with errors, see if 123 | you can figure out what's wrong with your version. 124 | 125 | .. code-block:: console 126 | 127 | Enigma> doOneChar 'A' reflB rotorI rotorII rotorIII 128 | 'U' 129 | Enigma> doOneChar 'B' reflB rotorI rotorII rotorIII 130 | 'E' 131 | 132 | Creating an Enigma state structure 133 | ---------------------------------- 134 | 135 | .. index:: 136 | single: record 137 | 138 | Since the Enigma state consists of a number of different things, it's 139 | going to be convenient to create a *record* to describe it. A record 140 | is like a tuple but with named elements. Here's the declaration of our 141 | Enigma state record: 142 | 143 | .. literalinclude:: cryptol/threeRotors.cry 144 | :language: cryptol 145 | :start-after: BeginEnigmaStateDef 146 | :end-before: EndEnigmaStateDef 147 | 148 | The ``EnigmaState`` record type combines all three rotors and the reflector 149 | into a single *object*. If we had a variable of this type named 150 | ``enigmaState``, we could access its rotors with this syntax: 151 | ``enigmaState.rotors``. Similarly for ``plugboard``. 152 | The part about the ``plugboard`` will be explained near the end of 153 | this chapter. 154 | 155 | Stepping the rotors 156 | ------------------- 157 | 158 | Now that we have all three rotors going, our next step is to advance 159 | them before encoding each character. Let's start by describing in a 160 | bit more detail what the *advance rotors* function needs to do: 161 | 162 | First, there are pins attached to each rotor. We're representing the pins 163 | as the ``Bit`` in the ``Rotor`` data type. When the pin at 164 | position 0 of the rotor is True, we need to 165 | follow these rules: 166 | 167 | * If the middle rotor's pin is True, we advance all three 168 | rotors, otherwise 169 | * if the pin furthest from the reflector (rotor 3) is True 170 | we advance rotors 2 and 3, otherwise 171 | * just advance rotor 3. 172 | 173 | Here's code that implements these rules, along with the helper 174 | function ``getPins``: 175 | 176 | .. literalinclude:: cryptol/threeRotors.cry 177 | :language: cryptol 178 | :start-after: BeginRotationsDef 179 | :end-before: EndRotationsDef 180 | 181 | The function ``getPins`` has some tricky indexing, so here's an 182 | explanation, step by step: 183 | 184 | #) ``rs@0`` is the first rotor (type: ``[26](Char,Bit)``) 185 | #) ``(rs@0)@0`` is the first element of the first rotor, type: ``(Char,Bit)`` 186 | #) ``((rs@0)@0).0`` is the character part of that first element, type: ``Char`` 187 | #) ``((rs@0)@0).1`` is the Pin part of that first element, type: ``Bit`` 188 | 189 | Now we can write ``advanceRotors`` that applies these rules to our 190 | rotors: 191 | 192 | .. literalinclude:: cryptol/threeRotors.cry 193 | :language: cryptol 194 | :start-after: BeginAdvanceDef 195 | :end-before: EndAdvanceDef 196 | 197 | Before we can test the function, we need to have some pins in 198 | our rotors. Looking at the cardboard Enigma, each rotor's pin is at the 199 | position where the letter has a grey background. So Rotor I's pin is 200 | at ``'Q'``, Rotor II's pin is at ``'E'`` and Rotor III's pin is at 201 | ``'V'``. So all we need to do is pass to ``buildRotor`` a sequence of 202 | bit's with the bit set accordingly. Here's a helper function that will 203 | make that easy: 204 | 205 | .. literalinclude:: cryptol/threeRotors.cry 206 | :language: cryptol 207 | :start-after: BeginPinsDef 208 | :end-before: EndPinsDef 209 | 210 | .. index:: 211 | single: zero 212 | single: or operator 213 | 214 | You might be surprised by the definition of ``setBit``. Our goal is to 215 | take a ``1`` in position 0, and use the *shift* operation (``>> b``), 216 | to move it ``b`` spots to the right. So we first need a ``1`` in the 217 | first position. There are many ways to achieve this\ [#]_. The way 218 | this function does it is by taking a ``1`` in the least significant 219 | position, and rotating it one position to the right (``>>> 1``), which 220 | wraps it around to the most significant place, which we then shift 221 | ``b`` positions to the right. Finally we use the *or* operator, 222 | ``||``, to overlay our newly set bit with our input ``n``. 223 | 224 | .. [#] 225 | 226 | Another way to achieve it would be to write ``(0b1 # zero)``. Since 227 | Cryptol knows how many bits the result needs to have, it will 228 | stretch ``zero`` to have the right number of ``0`` bits after the 229 | ``0b1`` to work out. 230 | 231 | The other interesting thing about this code is the use of ``zero``. 232 | It's a built-in Cryptol ``0`` constant that can have any type. In this 233 | case, it's a sequence of as many ``False`` bits as we need to 234 | initialize our empty pins. 235 | 236 | Now we have enough functions to build a sequence of rotor positions that follow 237 | the Enigma's rules: 238 | 239 | .. literalinclude:: cryptol/threeRotors.cry 240 | :language: cryptol 241 | :start-after: BeginRotorStates 242 | :end-before: EndRotorStates 243 | 244 | Exercise 245 | ~~~~~~~~ 246 | 247 | You can now build most of an Enigma state, including rotors with the 248 | pins. We can feed that starting state to ``enigmaStates`` to get an 249 | infinite sequence of states, which are the states after following the 250 | ``advanceRotors`` rules for each step. If drop the first 99 states of 251 | that sequence, you'll see the sequence of states just before and after 252 | a pin shows up in position 0 of Rotor II, so run this: 253 | 254 | .. code-block:: console 255 | 256 | Enigma> let startState = buildEnigmaState rotorI rotorII rotorIII reflB zero 257 | Enigma> drop`{99} (enigmaStates startState) 258 | [{rotors = [[(0x04, 0x14, False), (0x09, 0x15, False), 259 | ... 260 | 261 | Explain how the sequence of ``Rotor`` states do, or do not, follow the 262 | rules for rotor advancement. 263 | 264 | Implementing the plugboard 265 | -------------------------- 266 | 267 | .. figure:: figures/Enigma-plugboard.jpg 268 | :alt: The Enigma Plugboard 269 | :figclass: align-center 270 | :width: 7cm 271 | 272 | Here's how the plugboard works on the cardboard Enigma: 273 | to configure the plugboard, you're given pairs of letters, like 274 | ``"AP"`` and ``"BR"``. In the little boxes on the I/O Ring, you write 275 | a ``P`` next to the ``A`` and write an ``A`` next to the ``P``, and so 276 | on. Then, when you're about to encode a letter, you first check if 277 | there's a letter in the box, and if there is, you hop over to the 278 | corresponding letter on the ring, and start encoding from there. 279 | Similarly on the way back after the reflector and the rotors, you 280 | return the letter in the box (if there is one) when you finish 281 | following the lines. 282 | 283 | It's easiest to construct the plugboard as a 284 | string that starts out as the alphabet in order (which is the same 285 | as a *empty plugboard*), and for each pair of letters in the 286 | plugboard's definition, swap those letters in the string. Here's a 287 | helper function that does that: 288 | 289 | .. literalinclude:: cryptol/threeRotors.cry 290 | :language: cryptol 291 | :start-after: BeginPlugboardDef 292 | :end-before: EndPlugboardDef 293 | 294 | .. index:: 295 | single: recursion 296 | 297 | This function uses a different kind of recursion than we've used 298 | before. Rather than recursion based on elements of a sequence, 299 | we're calling our ``buildPlugboard`` function in its own definition, 300 | but with a bigger value for ``i`` each time around. Finally it ends 301 | when ``i`` is greater than or equal to the number of elements in our 302 | ``swaps`` sequence. Cryptol's built-in ``width`` function tells us how 303 | many elements there are in ``swaps``. 304 | 305 | Finally, to use the plugboard, even though its operation is simple, 306 | it's also subtle: in the forward direction, its input is a ``Char``, 307 | but its output is an ``Index``. In the reverse direction, its input is 308 | an ``Index``, but its output is a ``Char``. 309 | 310 | Exercise: Testing the plugboard 311 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 312 | 313 | Implement the ``doPlugFwd`` and ``doPlugRev`` functions, which have 314 | these types: 315 | 316 | .. code-block:: cryptol 317 | 318 | doPlugFwd : CharPerm -> Char -> Index 319 | 320 | doPlugRev : CharPerm -> Index -> Char 321 | 322 | It's subtle, but all you should need are the *indexing operator* ``@`` 323 | and our helper function from before, ``charToIndex``. 324 | 325 | As an aside, you've probably noticed the Cryptol prompt always says 326 | ``Main>``. If you want, you can start your ``enigma.cry`` file with 327 | the following line, which will change the prompt to ``Enigma>``, which 328 | is pleasing (to me, at least): 329 | 330 | .. code-block:: cryptol 331 | 332 | module Enigma where 333 | 334 | When you're done, test your function with an empty plugboard, as well 335 | as with the cardboardEnigma example plugboard, which is defined by 336 | this sequence of character pairs: 337 | 338 | .. code-block:: cryptol 339 | 340 | franklinHeathPlugboard = buildPlugboard 341 | ["AP","BR","CM","FZ","GJ", 342 | "IL","NT","OV","QS","WX"] 343 | alphabet 0 344 | 345 | // save the above to your enigma.cry, 346 | // and then in Cryptol: 347 | 348 | Enigma> set ascii=off 349 | Enigma> doPlugFwd franklinHeathPlugboard 'A' 350 | 0x0f 351 | Enigma> doPlugFwd franklinHeathPlugboard 'X' 352 | 0x16 353 | Enigma> set ascii=on 354 | Enigma> doPlugRev franklinHeathPlugboard 0 355 | 'P' 356 | Enigma> doPlugRev franklinHeathPlugboard 25 357 | 'F' 358 | 359 | Assembling our parts into an Enigma 360 | ----------------------------------- 361 | 362 | We now have the components required to write a function that encrypts 363 | a single character, by going through the plugboard, then the three 364 | rotors and reflector, and back through the plugboard: 365 | 366 | .. literalinclude:: cryptol/threeRotors.cry 367 | :language: cryptol 368 | :start-after: BeginDoOneChar 369 | :end-before: EndDoOneChar 370 | 371 | And now we can use our well-worn technique of constructing a sequence 372 | of encrypted characters by applying ``doOneChar`` to each character of 373 | the input, in parallel with each state of the Enigma machine: 374 | 375 | .. literalinclude:: cryptol/threeRotors.cry 376 | :language: cryptol 377 | :start-after: BeginDoEnigma 378 | :end-before: EndDoEnigma 379 | 380 | The reason we drop the first state of our ``enigmaStates`` is that 381 | when you use the Enigma, you're supposed to advance the rotors *before* 382 | encrypting each character. 383 | 384 | Exercise: Testing the plugboard, three rotors and reflector 385 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 386 | 387 | We can now test the basic 388 | functions of the Enigma. First, we'll create a start state 389 | corresponding to the initial rotor positions ``AAA``: 390 | 391 | .. code-block:: cryptol 392 | 393 | aaaEnigmaState = buildEnigmaState 394 | rotorI rotorII rotorIII reflB 395 | franklinHeathPlugboard 396 | 397 | // and another state with an empty plugboard: 398 | noPlugboardState = buildEnigmaState 399 | rotorI rotorII rotorIII reflB 400 | alphabet 401 | 402 | Then, in Cryptol, we can encrypt and decrypt a test message: 403 | 404 | .. code-block:: console 405 | 406 | Enigma> doEnigma aaaEnigmaState "WOWITWORKS" 407 | "JLBDMQCLQZ" 408 | Enigma> doEnigma aaaEnigmaState "JLBDMQCLQZ" 409 | "WOWITWORKS" 410 | 411 | If it works, congratulations! If it doesn't, it's most likely your 412 | plugboard, and you can test things with 413 | an empty plugboard like this: 414 | 415 | .. code-block:: console 416 | 417 | Enigma> doEnigma noPlugboardState "WOWITWORKS" 418 | "KIYQXAMTSO" 419 | 420 | If that doesn't work, manually check your ``doOneRotor`` and 421 | ``doTwoRotor`` functions against your cardboard Enigma, to make sure 422 | things are working that far. 423 | 424 | Finishing touches 425 | ----------------- 426 | 427 | All we have left before our Enigma is complete is to implement 428 | adjustable rings, and being able to set the initial rotor positions 429 | according to a three-letter *key*. Let's do it! 430 | 431 | Implementing adjustable rings 432 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 433 | 434 | Install the rings on your cardboard Enigma. Some descriptions of the 435 | Enigma describe a ring position by which letter on the ring covers up 436 | the ``A`` on the rotor underneath. Other descriptions specify the 437 | index\ [#]_ of the character covering the rotor's ``A``. Fortunately, 438 | it's easy for us to do either. Let's look at a very simple ring 439 | adjustment: set Rotor III's ring so that the ring's ``A`` covers the 440 | rotor's ``B``. Look at what they do, and think about how to implement 441 | that in your program. Here are some attributes of the rings that you 442 | might notice: 443 | 444 | #) They repeat the alphabet that's on the rotor underneath, 445 | #) which *character* has a gray background is fixed, per rotor, and 446 | #) when you slide the ring around, the characters and the pin move 447 | relative to the lines on the rotor. 448 | 449 | .. [#] 450 | 451 | Usually instead of specifying the 0-based index, they specify the 452 | 1-based "which letter of the alphabet" (A :math:`\rightarrow` 1), which is just the 453 | *index plus 1*. Which is also easy for us to compute. 454 | 455 | From these observations, it that setting the rings should consist of rotating 456 | the offsets and the pins in one direction or the other. Let's 457 | figure out which direction the offsets get rotated 458 | according to a ring position. 459 | 460 | Start by creating a new version of ``buildRotor`` that includes 461 | a ``ring`` parameter: 462 | 463 | .. code-block:: cryptol 464 | 465 | buildRotorRing rChars pins ring = [ (of, ob, p) 466 | | of <- fwd 467 | | ob <- rev 468 | | p <- pins 469 | ] where 470 | fwd = (stringToOffsets rChars) ??? ring 471 | revChars = invertPermutation rChars 472 | rev = (stringToOffsets revChars) ??? ring 473 | // ^^^ 474 | // should these be >>> or << :set ascii=on 505 | Enigma> doEnigma testState "ALMOSTDONE" 506 | "YXRJLPTZWS" 507 | 508 | If you don't get that result, check the output of one rotor: 509 | 510 | .. code-block:: console 511 | 512 | Enigma> :set ascii=off 513 | Enigma> doRotorFwd rotorIII 0 514 | 0x01 515 | 516 | Setting the key 517 | ~~~~~~~~~~~~~~~ 518 | 519 | The configuration of the Enigma corresponding to a *key* 520 | consists of rotating each rotor in the start state so that the key's 521 | letter is in position 0. We can pretty easily do that, again using the 522 | rotate operator (``<<<``), an amount corresponding to the difference 523 | between the key's index and ``'A'``. So, let's write a function that 524 | takes an Enigma state and a key (``[3]Char``), and produces a new 525 | Enigma state with the rotors set appropriately: 526 | 527 | .. literalinclude:: cryptol/threeRotors.cry 528 | :language: cryptol 529 | :start-after: BeginSetKey 530 | :end-before: EndSetKey 531 | 532 | Decoding some real Enigma messages 533 | ---------------------------------- 534 | 535 | Reviewing what we've done: 536 | 537 | #) we can build an ``EnigmaState`` corresponding to a sequence of 538 | rings, a reflector and plugboard using ``buildEnigmaState``, 539 | #) to change the key of a state from ``"AAA"`` to something else, we 540 | use ``setKey``, which takes a state and a key, and returns a new 541 | state. 542 | 543 | The Franklin Heath website has an example Enigma message that has been 544 | encoded with the Ring and Plugboard we've already created. All that's 545 | left is to create the state and set the key, which you can do in your 546 | ``enigma.cry`` or at the Cryptol command line, like this: 547 | 548 | .. code-block:: console 549 | 550 | Enigma> let state = buildEnigmaState rotorI rotorII rotorIII reflB franklinHeathPlugboard 551 | Enigma> let vqqKey = setKey state "VQQ" 552 | Enigma> doEnigma vqqKey "HABHVHLYDFNADZY" 553 | 554 | What do you get? It should be four words smooshed together. If that's 555 | not what you get, go back through the various checkpoints in this 556 | chapter to make sure you have the correct setup. 557 | 558 | If it did work, try decrypting the following message, with the same 559 | key as before: ``FONUGETQBLRQKHFESDSUFTEAHVZP`` 560 | 561 | Finally, if you've been working with a partner, each one of you come 562 | up with a message (and maybe even a different key, plugboard, or rotor 563 | orders), and describe the configuration to them sufficiently that they 564 | can decode your message. 565 | 566 | You may note that, just as in Chapter 1, the challenge with secure 567 | communication has been transformed into a *key distribution* challenge. 568 | 569 | -------------------------------------------------------------------------------- /src/02_encoding.rst: -------------------------------------------------------------------------------- 1 | Encoding data into bits 2 | ======================= 3 | 4 | *"There are 10 kinds of people in the world: those who understand binary and 5 | those who don't."* 6 | 7 | Now that you've seen encryption and decryption at work, it's time to 8 | learn how computers do it. Our Caesar cipher wheel is a paper computer 9 | which has an alphabet of 26 elements. You've heard (most likely) that 10 | computers work with ones and zeros. Ones and zeros are not very helpful 11 | by themselves, so people figured out how to represent integers, floating 12 | point numbers and all of the letters in all of the languages around the 13 | world using only ones and zeros 14 | 15 | .. index:: !encoding, !decoding 16 | 17 | The process of representing one set of things (integers, for example) 18 | using another set of things (sequences of ones and zeros) is called 19 | *encoding*. *Decoding* is reversing the process; getting back the 20 | original information from the new representation. In this chapter, we'll 21 | learn how to encode and decode unsigned and signed integers, simple 22 | Latin alphabets, as well as the rest of the alphabets in the world. 23 | 24 | Encoding integers 25 | ----------------- 26 | 27 | .. index:: !number bases 28 | 29 | If the joke at the beginning of this chapter makes sense, and you know 30 | about *number bases*, encoding integers using ones and zeros is simply 31 | converting to base 2, and you can skip to the next section. To learn 32 | what this means, and why that joke isn't leaving out eight kinds of 33 | people, read on\ [#]_. 34 | 35 | .. [#] Note that we didn't promise we'd convince you this joke is funny, only 36 | that you'll understand what it's getting at. 37 | 38 | We're so used to seeing a number like 533 and understanding it to mean 39 | "five hundred and thirty-three" that we forget that it's an encoding of 40 | a numeric value into the symbols 0, 1, 2 ... 8, 9. Reading from right to 41 | left, the n\ :sup:`th` digit is the :math:`10^{n-1}`-place\ [#]_. So 42 | deconstructing our example number we get: 43 | 44 | +---------------+----------------+----------------+----------------+----------------+ 45 | | Exponent | 10\ :sup:`3` | 10\ :sup:`2` | 10\ :sup:`1` | 10\ :sup:`0` | 46 | +---------------+----------------+----------------+----------------+----------------+ 47 | | Value | 1000 | 100 | 10 | 1 | 48 | +---------------+----------------+----------------+----------------+----------------+ 49 | | Digit | 0 | 5 | 3 | 3 | 50 | +---------------+----------------+----------------+----------------+----------------+ 51 | | Digit value | 0 | 500 | 30 | 3 | 52 | +---------------+----------------+----------------+----------------+----------------+ 53 | 54 | So finally we get :math:`0 + 500 + 30 + 3 =` 533. 55 | 56 | .. [#] Remember that :math:`10^0 = 1`, and in fact anything to the 0th 57 | power is 1 58 | 59 | Binary representations of numbers 60 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 61 | 62 | .. index:: binary, decimal 63 | 64 | Encoding numbers in binary is the same recipe, but with 2 as the base of 65 | the exponent instead of 10. Each place (digit) can either have a 1 or a 66 | zero in it. As a result, you need more digits to represent the same 67 | values, but it works out. 68 | 69 | +---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+ 70 | | Exponent | :math:`2^9` | :math:`2^8` | :math:`2^7` | :math:`2^6` | :math:`2^5` | :math:`2^4` | :math:`2^3` | :math:`2^2` | :math:`2^1` | :math:`2^0` | 71 | +---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+ 72 | | Value | 512 | 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | 73 | +---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+ 74 | | Digit | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 75 | +---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+ 76 | | Digit value | 512 | 0 | 0 | 0 | 0 | 16 | 0 | 4 | 0 | 1 | 77 | +---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+ 78 | 79 | In this case we get :math:`512 + 16 + 4 + 1` = 533. 80 | 81 | To convert a number into binary, take the largest digit that isn't 82 | bigger than your value, and set it to 1, then subtract that digit's 83 | value from your value and repeat down the line, not forgetting to put in 84 | 0s for the values you don't want to add. 85 | 86 | Adding binary numbers is super-easy. It's a lot like the addition you're 87 | used to, with carrying and everything, except simpler. If both places 88 | are 0, the sum is 0. If either is 1, the sum is 1. If both are 1, the 89 | sum is 0, and you carry 1. When you include the carry, the rule is the 90 | same, except sometimes you have both 1 along with the carry, in which 91 | case the sum is 1 and the carry is 1. 92 | 93 | .. index:: binary addition 94 | 95 | Here's a four-bit addition of 2 and 3: 96 | 97 | :: 98 | 99 | 1 <- carry 100 | 0010 101 | + 0011 102 | ------ 103 | 0101 104 | 105 | If you're talking about numbers in different bases, and it's not clear 106 | which one you're referring to, it's common to include the base in the 107 | subscript after the number. So the joke at the beginning of the chapter 108 | would be "There are 10\ :sub:`2` types of people..."\ [#]_. 109 | 110 | .. [#] But that way kind of ruins the joke, doesn't it? 111 | 112 | Working from the right, :math:`0+1 = 1` with no carry, then 113 | :math:`1+1 = 0` with carry, and finally we have a carry with 114 | :math:`0+0`, so that's 1. 101\ :sub:`2` is 5, which is what we're hoping 115 | for. 116 | 117 | Representing negative numbers: 118 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 119 | 120 | *This section is a deep-dive. You can skip it the first time through 121 | - but if you get bored or ever get curious, come back here for some 122 | cool stuff.* 123 | 124 | The encodings we've discussed so far are only for positive numbers. If 125 | you want to represent negative numbers, there are a few options, but one 126 | fairly universally agreed-on best way to go. 127 | 128 | The obvious (but not best) way is to reserve the top-most bit to 129 | represent negation. If the bit is 0, the rest of the bits are a positive 130 | number, if it's 1, the rest of the bits are interpreted as a negative 131 | number. This encoding makes sense, but it makes arithmetic difficult. 132 | For example if you had 4-bit signed numbers, and wanted to add -1 and 3, 133 | you'd get 134 | 135 | :: 136 | 137 | 11 <- carry 138 | 1001 139 | + 0011 140 | ------ 141 | 1100 142 | 143 | .. index:: two's complement 144 | 145 | This shows that if we apply our naive addition to :math:`-1 + 3`, we get 146 | the unfortunate answer -4. Wouldn't it be cool if there were a way to 147 | store negative numbers in a way that the addition process we already 148 | know would just work out? It turns out that if you represent negative 149 | numbers by flipping the bits and adding one, you can do arithmetic using 150 | simple unsigned operations and have the answers work out right. This 151 | method of encoding signed numbers is called *two's complement*. 152 | 153 | For example, to get a four-bit -1 in two's complement, here's the 154 | process: 155 | 156 | :: 157 | 158 | Step 1: 0001 <- +1 159 | Step 2: 1110 <- flipped 160 | Step 3: 1111 <- add 1 is -1 in two's complement 161 | 162 | Here's :math:`-1 + 3` again, in two's complement: 163 | 164 | :: 165 | 166 | 111 <- carry 167 | 1111 <- -1 (from above) 168 | + 0011 <- 3 169 | ------ 170 | 0010 171 | 172 | In the ones place, :math:`1+1=0` carry 1, then we have :math:`1+1` + 173 | carry = 1 carry 1, then we have 1 + carry = 0 with carry, and the last 174 | digit is also 1 + carry = 0 (and the carry goes away). You'll see the 175 | answer, :math:`0010`\ :sub:`2` = 2, which is what we're hoping for. 176 | 177 | .. raw:: html 178 | 179 | 184 | 185 | Things to think about 186 | ~~~~~~~~~~~~~~~~~~~~~ 187 | 188 | 1. What's the largest value you can represent with one base-ten digit? 189 | Two digits? :math:`n`-digits? 190 | 191 | 2. What's the largest value you can represent with one binary digit? 192 | Eight digits? :math:`n`-digits? 193 | 194 | .. index:: overflow 195 | 196 | 3. When we did :math:`-1 + 3`, the carry bit got carried off the end of 197 | the addition. This is called overflow. In some cases (like this one), 198 | it's not a problem, but in other cases, it means that you get the 199 | wrong answer. Think about whether you can check whether overflow 200 | that results in a wrong answer has 201 | occurred either before or after the addition has happened. 202 | Hint: think about the various possible cases separately. 203 | 204 | .. index:: ones' complement 205 | 206 | 4. Two's complement is a slight change from *ones' complement*, in which 207 | negative numbers just have their bits flipped, but you don't add a 1 208 | afterwards. A big advantage of two's complement is that there are two 209 | ways to write 0 in ones complement: 10000... and 0000.... 210 | Essentially you have a positive and a negative zero. Think about what 211 | problems this might cause. 212 | 213 | 5. What's the largest value you can represent in a two's complement 214 | 8-bit number? What's the smallest? 215 | 216 | Why ones and zeros? 217 | ------------------- 218 | 219 | .. index:: performance 220 | 221 | It's a reasonable question - *why do computers only use ones and zeros*? 222 | The oversimplified, but essentially correct answer is performance and 223 | simplicity. Making computers faster has been a goal since they were 224 | first invented. *Simplicity enables speed* is a common theme in computer 225 | engineering, and binary code is a great example. To represent values the 226 | voltage on a wire is either *high* (representing a 1) or *low* 227 | (representing 0). What exact voltage corresponds to high and low can 228 | vary. As systems get faster, the voltages that make a "1" tend to 229 | decrease. In current Intel CPUs, for example, it's common for a "1" to 230 | be as low as 1 volt. On older systems, it can be as high as 13 volts. 231 | 232 | .. index:: transistors 233 | 234 | *Transistors* are the building blocks that work with the voltages inside 235 | computers. They're essentially just switches that can be controlled by a 236 | voltage level. A transistor has an input, an output, and a controlling 237 | switch. It's easy to tell when a transistor is all the way "on" or 238 | "off", but measuring values in between is much more complex and 239 | error-prone, so modern computers don't bother with those, and instead 240 | just deal with "high" voltages and "low" voltages. Taking this approach 241 | has allowed us to create computers that can switch many *billions of 242 | times per second*. 243 | 244 | .. Comment - There was a ternary computer built in Russia. That it 245 | didn't have any follow-ons backs up the thesis of this section. 246 | http://hackaday.com/2016/12/16/building-the-first-ternary-microprocessor/ 247 | 248 | Encoding text into ones and zeros 249 | --------------------------------- 250 | 251 | Now that you understand how numbers can be represented as ones and 252 | zeros, we can explain how text can be represented as sequences of 253 | numbers, and you can convert those numbers into bits. 254 | 255 | It turns out that how to assign numbers to letters is pretty arbitrary. 256 | Until the early 1960's there were a number of competing text 257 | :math:`\rightarrow` bits encoding systems. People realized early on that 258 | deciding on one system would let them communicate more easily between 259 | different machines. The most common text encoding, called ASCII, was 260 | agreed on in 1963, and was in wide use through the mid 1990's. 261 | 262 | .. index:: ASCII 263 | 264 | The table below show how ASCII represents the basic letters, numbers and 265 | punctuation. Each character is followed by its decimal ASCII code. There 266 | are two "special" characters in the table, ``sp`` is the space character, 267 | and ``del`` is delete\ [#]_. 268 | 269 | .. [#] delete is more of an un-character, but it has an ASCII code. So 270 | does "ring a bell" (which is ASCII 7). Kinda weird, isn't it? 271 | 272 | :: 273 | 274 | sp 32 ! 33 " 34 # 35 $ 36 % 37 & 38 ' 39 275 | ( 40 ) 41 * 42 + 43 , 44 - 45 . 46 / 47 276 | 0 48 1 49 2 50 3 51 4 52 5 53 6 54 7 55 277 | 8 56 9 57 : 58 ; 59 < 60 = 61 > 62 ? 63 278 | @ 64 A 65 B 66 C 67 D 68 E 69 F 70 G 71 279 | H 72 I 73 J 74 K 75 L 76 M 77 N 78 O 79 280 | P 80 Q 81 R 82 S 83 T 84 U 85 V 86 W 87 281 | X 88 Y 89 Z 90 [ 91 \ 92 ] 93 ^ 94 _ 95 282 | ` 96 a 97 b 98 c 99 d 100 e 101 f 102 g 103 283 | h 104 i 105 j 106 k 107 l 108 m 109 n 110 o 111 284 | p 112 q 113 r 114 s 115 t 116 u 117 v 118 w 119 285 | x 120 y 121 z 122 { 123 | 124 } 125 ~ 126 del 127 286 | 287 | So the string "Hi there" in ASCII is: 72, 105, 32, 116, 104, 101, 114, 288 | 101. 289 | 290 | Some exercises 291 | ~~~~~~~~~~~~~~ 292 | 293 | 1. Encode your name in ASCII. 294 | 295 | ASCII has some clever design features. Here are some questions that may 296 | uncover some of that cleverness: 297 | 298 | 2. Is there an easy way to convert between upper and lower-case in 299 | ASCII? Think about the binary representations. 300 | 301 | 3. Is there an easy way to convert between a digit and its ASCII 302 | representation? Does the binary representation help here? What 303 | aspects of the ASCII encoding make this easy/difficult? 304 | 305 | Encoding *all* languages: Unicode 306 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 307 | 308 | *This section is a deep-dive: you can do the rest of the book 309 | knowing only ASCII. On the other hand, if you like to know how 310 | things work under the hood, you'll enjoy learning how non-Latin web 311 | pages are encoded and transmitted.* 312 | 313 | .. index:: Unicode, UTF-8 314 | 315 | Up until the mid 1990's, computer systems that needed to process 316 | languages whose characters are not in the ASCII tables each used their 317 | own encodings. When the Internet and World Wide Web started to gain 318 | adoption, people realized that they would have to standardize how these 319 | other languages encoded their alphabets into bits. The Unicode 320 | Consortium was the group founded to make those standards. They took the 321 | sensible approach of splitting the problem into two stages: 322 | 323 | 1. Enumerating all of the symbols that can be represented. This includes 324 | accents, special glyphs, and now also includes emoji. As of 2016, 325 | there are over 1.1 million different "code points" in the master 326 | Unicode table. 327 | 328 | 2. Devising efficient ways of representing sequences of those symbols as 329 | bits. 330 | 331 | The hard work of the first stage is to come to agreement on which 332 | symbols go in (and which to leave out), what to call them, and how to 333 | organize them. The folks working on stage two have come up with a number 334 | of encodings, but the one that is most common on the Internet is UTF-8. 335 | The genius of UTF-8\ [#]_ is that it's *backwards compatible* with ASCII. 336 | What that means is that if your text *does* fit in the ASCII table, the 337 | ASCII representation of it is also the UTF-8 representation of it. The 338 | key to making that work is that while ASCII is an 8-bit representation, 339 | the top-most bit of the ASCII table is always 0. 340 | 341 | .. [#] UTF-8 was invented at Bell Labs by Ken Thompson, who 342 | co-invented Unix, and Rob Pike, who subsequently moved to Google 343 | where he invented the Go programming language (among other 344 | accomplishments). 345 | 346 | If you're decoding a UTF-8 stream of bytes, and you encounter any byte 347 | with its top bit off (i.e., its decimal value is <= 127), decode it as 348 | ASCII. If the top bit is on (the number is > 127), follow this 349 | procedure: 350 | 351 | 1. The first byte tells you how many bytes are in this character. Count 352 | the number of bits set before the first "0"-bit. That number is the 353 | number of bytes in this character. The remaining bits after the 0 are 354 | data. UTF-8 supports up to 4 bytes, so the longest (4-byte) UTF-8 355 | character will start ``11110...`` 356 | 357 | 2. The remaining bytes are tagged with a leading "10" (so you can tell 358 | they aren't beginnings of characters), and the remaining 6-bits are 359 | data. 360 | 361 | 3. Concatenate the data bits into one binary number. 362 | 363 | 4. Look up that number in the Big Unicode Table. 364 | 365 | Pretty cool! 366 | 367 | An aside: Hexadecimal 368 | ~~~~~~~~~~~~~~~~~~~~~ 369 | 370 | .. index:: hexadecimal 371 | 372 | Writing numbers in binary is tedious for mere humans\ [#]_. It takes 373 | eight digits to count up to 128, after all! Writing them in decimal is 374 | convenient for us humans, but a downside is that there's no easy way to 375 | tell how many bits a decimal number has. Computer scientists have 376 | settled on *hexadecimal*, or base 16, to write numbers when the number 377 | of bits matters. How does one write a hexadecimal number? After all, 378 | we've only got ten digits, 0 -> 9, right? Well, as a convention we use 379 | the first six letters of the alphabet to represent the digits past 9. So 380 | counting to 16 in hexadecimal (or "hex" for short), looks like this: 381 | 382 | .. [#] computers, on the other hand, seem to thrive on tedium. 383 | 384 | :: 385 | 386 | 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10 387 | 388 | Hex, just like decimal and binary, has a *ones place*, but the next 389 | bigger digit in hex is the *sixteens place*\ [#]_, so 10 in hex is 16 390 | in decimal (also written as 10\ :sub:`16` == 16\ :sub:`10`). A in hex is 391 | 10 in decimal. This means that one hex digit holds exactly four bits, 392 | and it takes two hex digits to hold a byte. 393 | 394 | .. [#] and the next digit is the 256ths place! 395 | 396 | Finally, there are a number of ways of indicating what base a number is 397 | in. In addition to using the subscript of the base, like spoiling the 398 | joke with 10\ :sub:`2`, when you are writing numbers in ASCII and 399 | there's no way to write subscripts, instead we prefix binary numbers 400 | with ``0b``, and prefix hexadecimal numbers with ``0x``. If a number has 401 | no prefix or subscript, it's usually safe\ [#]_ to assume the number is 402 | in base 10. Learning what hexadecimal looks like is important right now, 403 | because Unicode tables are all written in hex, as you're about to see. 404 | 405 | .. [#] except when telling nerdy jokes 406 | 407 | Back to Unicode 408 | ~~~~~~~~~~~~~~~ 409 | 410 | Below is a table with three sample Unicode symbols. Each symbol has a 411 | long, boring unambiguous name, its graphical symbol (which can vary from 412 | font to font), its global numeric code in the master Unicode table, and 413 | finally how that number is encoded in UTF-8. 414 | 415 | .. figure:: figures/UnicodeFunnyFigure.pdf 416 | :alt: Some example Unicode glyphs, their official Unicode name, number and UTF-8 encodings 417 | :figclass: align-center 418 | 419 | Some example Unicode glyphs, their official Unicode name, number and UTF-8 encodings 420 | 421 | In the table above, the "U+" lets you know that the hex number that 422 | follows is the location in the Unicode table, and you see that the UTF-8 423 | encoding is also written in hex. There's a cool web page at 424 | ``http://unicode-table.com/en/`` that 425 | has the whole table in one page. On the right of the page there is a 426 | live map with dots in the parts of the world where the characters 427 | visible on the current screen are used. 428 | 429 | Let's look at the UTF-8 for the Bicycle symbol: ``F0 9F 9A B2``. In 430 | binary the F0 is 11110000. The four 1s let us know that this UTF-8 code 431 | has four bytes total (this one and the next 3). The remaining 3 bytes 432 | are: 433 | 434 | :: 435 | 436 | 9 F 9 A B 2 437 | 10011111 10011010 10110010 438 | 439 | Remember that the beginning ``10`` in each byte lets us know these are 440 | the rest of this one symbol. If we take those off and concatenate the 441 | bits like this: 442 | 443 | :: 444 | 445 | 011111011010110010 446 | 447 | Then breaking that up into 4-bit hunks (starting from the right), then 448 | converting each chunk into its Hex digit, we get: 449 | 450 | :: 451 | 452 | Binary chunk: 01 1111 0110 1011 0010 453 | Hex digit: 1 F 6 B 2 454 | 455 | If you look at the Unicode Numeric code part of the table above, you'll 456 | see that 0x1F6B2 is the code for Bicycle! 457 | 458 | Independent study questions 459 | --------------------------- 460 | 461 | If you're interested into learning more about how information can be 462 | digitally encoded, here are some questions you can research the answers 463 | to. 464 | 465 | .. index:: vector graphics, bitmaps, pixels, metadata 466 | 467 | 1. Two common ways of **encoding images** are pixel-based (or bitmap) 468 | and vector-based: 469 | 470 | a. The main aspects of **pixel-based**, or **bitmap** encoding are resolution (how 471 | many pixels there are in the image), how to encode colors (the 472 | value at each pixel), and compression (e.g., to reduce the storage 473 | for simple scenes like a plain blue sky). Common pixel-based 474 | formats are PNG, JPEG, and GIF. 475 | 476 | b. The main aspects of **vector graphics** are what *primitives* to 477 | provide, which are the shapes that are supported built-in (lines, 478 | curves, circles, rectangles) vs. which ones need to be assembled 479 | from sequences of primitives, what the *coordinate system* for 480 | describing shapes is, and what the *syntax* is. Vector graphics 481 | formats tend to more-resemble programming languages, and are often 482 | in human- readable ASCII. Common vector-based formats are PDF, 483 | SVG, and PostScript. 484 | 485 | What's an image encoding method you know about? Use Google to find a 486 | specification for that format, and Write down how files in that 487 | format are structured. Most formats have a *header* which provides 488 | *metadata* about the file\ [#]_. 489 | 490 | .. [#] The word *metadata* literally means "data about data", which 491 | particularly makes sense in this context. 492 | 493 | .. index:: archives, file archives, tar file, zip file, dmg file, rpm file 494 | 495 | 2. **File archives** are encodings that combine a bunch of files and 496 | folders into one file that can be sent by email, or downloaded from a 497 | web site, etc., and then *unpacked* at the other end. Archive formats 498 | often include the ability to compress the files as well. It's often 499 | surprising which file formats are archives. For example, most word 500 | processing document formats are file archives, to allow you to 501 | include graphics. Installers for most systems are also archives, such 502 | as Windows MSI files, MacOS DMG files, and Linux RPM files. Early 503 | archive formats include TAR and ZIP, which were invented more than 30 504 | years ago, but are still used every day. 505 | 506 | If you know a particular file archive format, look it up on the 507 | Internet and write it up in a page or so. 508 | 509 | Take-aways 510 | ---------- 511 | 512 | You've learned about how to encode data of different types (numbers, 513 | characters) into binary representations. You've learned some binary 514 | arithmetic, and why 10\ :sub:`2` happens to be equal to 2\ :sub:`10`. 515 | Finally you've learned that nerds (the author included) can have a 516 | terrible sense of humor. 517 | -------------------------------------------------------------------------------- /src/05_enigma.rst: -------------------------------------------------------------------------------- 1 | The Enigma 2 | =========== 3 | 4 | .. figure:: figures/Enigma_Milano.jpg 5 | :alt: The Enigma Machine 6 | :figclass: align-center 7 | :width: 6cm 8 | 9 | .. index:: 10 | single: Alan Turing 11 | single: Enigma 12 | single: World War II 13 | single: Bletchley Park 14 | 15 | *Enigma*\ [#]_ was the name of a typewriter-like cryptographic machine that 16 | was used by Germany before and during World War II. German military 17 | commanders used the Enigma to encrypt instructions sent by radio to 18 | their commanders across Europe and the Atlantic ocean. The Allies 19 | could eavesdrop on the radio transmissions and hear the encrypted 20 | messages, but without the key used for that day, they couldn't decrypt 21 | them. A top-secret team of mathematicians were gathered in Bletchley 22 | Park, England, with the task of breaking the Enigma. The team's 23 | intellectual leader was a young man named Alan Turing. The story of 24 | how the Enigma was broken is told pretty well in the movie *The 25 | Imitation Game*, and even better (but without Benedict Cumberbatch) in 26 | the book *Alan Turing: The Enigma* by Alan Hodges. Alan Turing's life 27 | ended tragically due to how homosexual people were treated at the time\ [#]_. 28 | In addition to ending WWII early, Alan Turing is credited with inventing 29 | the modern computer and artificial intelligence. 30 | 31 | .. [#] Photo by Alessandro Nassiri of the Enigma machine located at 32 | the Museo scienza e tecnologia in Milano, Italy, from 33 | Wikipedia. 34 | 35 | .. [#] The British government issued a formal pardon and apology in 2013. 36 | 37 | In the next two chapters you will learn how to build and use a cardboard model of the 38 | Enigma that is compatible with the original. Then, step by step, we'll 39 | implement the Enigma in Cryptol, and use it to encode and decode 40 | messages. 41 | 42 | .. TODO: finally, we'll use Cryptol's advanced features to break the enigma code. 43 | 44 | Using a real Enigma 45 | ------------------- 46 | 47 | If you ever get a chance to visit the National Cryptologic Museum\ [#]_, you 48 | can use a real Enigma machine. Here's what you would do to encrypt 49 | something with a real Enigma machine. 50 | 51 | .. [#] The National Cryptologic Museum is next to Fort Meade, in 52 | Maryland, where the US National Security Agency is located. It's well worth 53 | visiting. It's about halfway between Washington D.C, and 54 | Baltimore. 55 | 56 | First, the key is the combination of two things: the *rotor settings* 57 | and the *plugboard settings*. The rotors are the wheels at the top of 58 | the machine. Choose a set of initial positions and write them down. 59 | You probably will not be able to change the plugboard settings, but 60 | write them down (or take a photo) if you can. After you configure the key, then you 61 | start typing your message. As you type, the machinery moves, and 62 | lights up letters in the area above the keyboard. As you type the 63 | message, a partner writes down the sequences of lit-up letters. This 64 | is the encrypted message. As you type, the rotors change positions, so 65 | if you want to immediately decode the message, you'll need to reset 66 | the rotor, then you start typing in the ciphertext. If things are 67 | working right, the plaintext of your message will show up in the 68 | lights. 69 | 70 | Making and using your own Enigma 71 | --------------------------------- 72 | 73 | Franklin Heath, a cybersecurity company in the UK, released an 74 | excellent cardboard model of the Enigma\ [#]_. It is similar to a 75 | pen-and-paper version of the Enigma designed by Alan Turing while he 76 | was at Bletchley Park, and can be used to encrypt and decrypt messages 77 | interchangeably with real Enigma machines. 78 | 79 | .. [#] You can download it from http://wiki.franklinheath.co.uk/index.php/ Enigma/Paper_Enigma 80 | 81 | The first thing you'll need to assemble your own paper Enigma is a 82 | tube that has a diameter of 75mm. One source of such tubes is 83 | Pringles cans (they call them "crisp tubes" in Britain). If you don't 84 | want to buy a can of Pringles, you can make your own tube from 85 | cereal box cardboard. 86 | 87 | Let's build our paper Enigma step by step, and write Cryptol code that 88 | simulates the system at each step. 89 | 90 | Following the directions on the Franklin Heath paper Enigma wiki, 91 | build the most simple Enigma, which has three paper bands: the 92 | Input/Output band, Rotor I, and Reflector B. Make sure to line up the 93 | gray bar on the Reflector and the I/O band, and tape those bands 94 | stationary, while allowing the rotor to move. The key in this Simple 95 | Enigma is the letter between the gray bars when you start. Before 96 | decoding each character, slide the rotor toward you one position, so 97 | the next higher letter in the alphabet is between the grey bars. 98 | 99 | .. figure:: figures/OneRotorPaperEnigma.jpg 100 | :alt: Paper Enigma with one rotor 101 | :figclass: align-center 102 | :width: 6cm 103 | 104 | Paper Enigma with one rotor 105 | 106 | Using this one-rotor setup, set the key to A, and decode the following 107 | message: 108 | 109 | .. 110 | 111 | ``YMXOVPE`` 112 | 113 | I'll walk you through decoding the first letter: 114 | 115 | #. First, advance the rotor so that ``B`` is between the grey bars. 116 | 117 | #. Next, start at the ``Y`` on the INPUT/OUTPUT ring on the right. 118 | 119 | #. Trace from the ``Y`` along the blue line to the ``J`` on the rotor. 120 | 121 | #. Along the reflector, go from the ``J`` along the blue line up to the 122 | ``Q``. 123 | 124 | #. From the ``Q``, follow the red line across and down to the ``G``. 125 | 126 | #. ``G`` is the first decoded character! Now advance the rotor so that 127 | ``C`` is between the grey bars, and decode the next letter. 128 | 129 | .. GOODJOB is the decoded message 130 | 131 | The result should be two English words. If it isn't, make sure you're 132 | advancing the rotor between each character. When you're done, ``H`` 133 | should be the character between the grey bars. 134 | 135 | Implementing the Enigma in Cryptol 136 | ----------------------------------- 137 | 138 | The Enigma is way more complicated than the Caesar or 139 | Vigenere ciphers. We can't just implement it in one go - instead we 140 | have to break it up into the various components and test each step as 141 | we go. We'll start by implementing just the rotor, then the reflector, 142 | then combine them into a one-rotor Enigma, and so on. Let's go! 143 | 144 | Implementing Enigma rotors in Cryptol 145 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 146 | 147 | If you look at what the Enigma rotor does, it takes a letter as input 148 | and shifts that letter to another location on the cylinder. The figure 149 | below shows a part of Rotor I. If you put the rotor's ``A`` 150 | between the grey bars, you can trace out what each letter gets 151 | transformed to. For example, ``A`` from the I/O band goes up four 152 | positions to ``E``, and ``D`` goes up two positions to ``F``. 153 | Because the rotors rotate\ [#]_, it makes sense to think about the 154 | rotors in terms of offsets, or *relative* translations instead of 155 | letters, or *absolute* addresses, like we did with the Caesar 156 | cipher. 157 | 158 | .. [#] 159 | 160 | Rotors were well-named, weren't they? 161 | 162 | .. figure:: figures/EnigmaOffsetsFwd.pdf 163 | :figclass: align-center 164 | :width: 7cm 165 | 166 | Tracing rotor offsets in the forward direction. 167 | 168 | Already we're now talking about three different kinds of numbers: the 169 | *ASCII code* for each letter, the *indexes* within the alphabet those 170 | letters have, and now *offsets*, which is what we're calling the 171 | distance between two letters. They're all numbers, but they have 172 | different meanings, and we need to be careful that we don't mix them 173 | up in the code. Here's an example of each of them: 174 | 175 | +-------+-------+--------+--------------------------------------------+ 176 | | Char | ASCII | Index | Offset from Char :math:`\rightarrow` | 177 | + + + +----------+---------+------+-------+--------+ 178 | | | | | ``A`` | ``B`` | ... | ``Y`` | ``Z`` | 179 | +=======+=======+========+==========+=========+======+=======+========+ 180 | | ``A`` | 65 | 0 | 0 | 1 | | 24 | 25 | 181 | +-------+-------+--------+----------+---------+------+-------+--------+ 182 | | ``B`` | 66 | 1 | 25 | 0 | | 23 | 24 | 183 | +-------+-------+--------+----------+---------+------+-------+--------+ 184 | | ``C`` | 67 | 2 | 24 | 25 | | 22 | 23 | 185 | +-------+-------+--------+----------+---------+------+-------+--------+ 186 | | ... | 187 | +-------+-------+--------+----------+---------+------+-------+--------+ 188 | | ``X`` | 88 | 23 | 3 | 4 | | 1 | 2 | 189 | +-------+-------+--------+----------+---------+------+-------+--------+ 190 | | ``Y`` | 89 | 24 | 2 | 3 | | 0 | 1 | 191 | +-------+-------+--------+----------+---------+------+-------+--------+ 192 | | ``Z`` | 90 | 25 | 1 | 2 | | 25 | 0 | 193 | +-------+-------+--------+----------+---------+------+-------+--------+ 194 | 195 | 196 | The offset representation is how we'll describe what each rotor does 197 | in the code. To create the offsets for a rotor it's 198 | convenient to trace the lines on our cardboard Enigma 199 | and write down which *letter* each line goes to, 200 | then write a *helper function* to take that representation and turn it 201 | into the sequence of *offsets* we want. 202 | 203 | To express this in Cryptol, we start with by tracing the lines for 204 | each character in the alphabet. We write them down in the same order, 205 | so the first character is what the line from ``A`` goes to, which is 206 | ``E``. ``B``'s line goes further up, to ``K``, and so on. In your 207 | ``enigma.cry`` file, create a variable called ``rotorIchars`` like 208 | this: 209 | 210 | .. code-block:: console 211 | 212 | rotorIchars = "EK ..." 213 | 214 | .. answer rotorIchars = "EKMFLGDQVZNTOWYHXUSPAIBRCJ" 215 | 216 | Where you fill in the rest of the string. 217 | 218 | Our next job is to write a helper function that 219 | computes each offset. We also choose to represent offsets with a 220 | different number of bits than characters, so we (and Cryptol) 221 | can tell them apart from each other. We *could* use 8 bits for 222 | characters, indexes and offsets, but using different numbers of bits 223 | for each of them makes it easier for Cryptol to help prevent 224 | us from getting them confused, by giving us an error when we provide 225 | one kind of number when a function expects another. 226 | 227 | .. literalinclude:: cryptol/threeRotors.cry 228 | :language: cryptol 229 | :start-after: BeginBasicTypes 230 | :end-before: EndBasicTypes 231 | 232 | The main tricky bit in this part of the program is that we need to 233 | avoid negative numbers, because they won't work with Cryptol's modulo 234 | arithmetic [#]_. Fortunately, that's easy to do. Let's work through how to 235 | compute offsets using only positive numbers. First, as we're marching 236 | through the ``chars`` sequence, the offset between each character 237 | ``c`` and its position in the alphabet ``a`` is ``c - a``. This is a 238 | positive number when the line goes up on our rotor. For example, 239 | computing the very first entry, ``'E' - 'A'`` equals 4, just like we'd 240 | hope. 241 | 242 | .. [#] if you type ``-3 % 26`` in Cryptol, you get ``3`` instead of 243 | ``23`` like we'd hope. Python gets this right, but C, Java and 244 | many other languages get it wrong (they usually say -3). 245 | It's always safe to keep things positive like we're doing here. 246 | 247 | .. index:: 248 | single: modulo arithmetic 249 | 250 | However, looking up the rotor at ``G``, we get ``'D' - 'G'`` 251 | which is -3. How do we fix this? Well, it's always safe to add 0 to 252 | something -- doing that doesn't change the result, right? In modulo 253 | arithmetic, there are a *bunch* of numbers whose values are 0. For 254 | example, ``26 % 26`` is ``0``, and so is ``52 % 26``. So if we add 255 | ``26`` to our element of ``chars`` before subtracting, that's the same 256 | as adding zero, and we also know that the result will be positive. 257 | 258 | So, our final expression for computing the offset from our array is 259 | ``c + 26 - a``. We do ``drop`{2}`` of that to take the 8 bit number 260 | and drop the two leading ``0``'s from it. Think about whether it's 261 | always safe to assume there will be at least two leading ``0``'s in 262 | this number. 263 | 264 | To test your function, try loading your program and running it, like 265 | this: 266 | 267 | .. code-block:: console 268 | 269 | % cryptol enigma.cry 270 | ... (Cryptol talking to you) 271 | Main> :set base=10 272 | Main> stringToOffsets rotorIchars 273 | [4, 9, 10, 2, 7, 1, 23, ... ] 274 | 275 | If you get a different sequence of numbers, first decide if you agree 276 | with the offsets above, and if you do, figure out why your function 277 | doesn't do the same thing. 278 | 279 | Exercise: write ``applyOffsetToIndex`` 280 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 281 | 282 | To apply an offset to an index *i*, we use this recipe: first, look 283 | up the offset in the offset sequence using the ``@ i`` indexing 284 | operator. To add two numbers, they need to have the same number of bits, 285 | so prepend a ``0b0`` to the front of the offset using the ``#`` operator. 286 | Then we add the result to ``i`` and apply ``% 26`` to get the new index. 287 | 288 | Following this recipe, write a function called ``applyOffsetToIndex`` that has the following 289 | type: 290 | 291 | .. code-block:: cryptol 292 | 293 | applyOffsetToIndex : [26]Offset -> Index -> Index 294 | applyOffsetToIndex offsets i = 295 | 296 | Main> let rIoffs = stringToOffsets rotorIchars 297 | Main> applyOffsetToIndex rIoffs (charToIndex 'A') 298 | Main> applyOffsetToIndex rIoffs (charToIndex 'Z') 299 | Main> applyOffsetToIndex rIoffs (charToIndex 'Y') 300 | 301 | Does your code agree with the cardboard Enigma? 302 | 303 | .. TODO - ANSWER:: 304 | 305 | applyOffsetToIndex o i = (i + (0b0 # o@i)) % 26 306 | 307 | Enigma> applyOffsetToIndex rIoffs (charToIndex 'A') 308 | 0x04 309 | Enigma> applyOffsetToIndex rIoffs (charToIndex 'Z') 310 | 0x09 311 | Enigma> applyOffsetToIndex rIoffs (charToIndex 'Y') 312 | 0x02 313 | 314 | Implementing the reflector in Cryptol 315 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 316 | 317 | Now let's look at the Reflector. The main thing different between this 318 | and the rotor is that the lines loop back to the edge they start from. 319 | 320 | .. figure:: figures/ReflectorOffsets.pdf 321 | :figclass: align-center 322 | :scale: 40% 323 | 324 | A portion of Reflector B. 325 | 326 | Here, we see that ``I`` goes to ``P``, ``K`` goes to ``N`` and so on. 327 | Just as we did for the rotor, follow the lines and come up with the 328 | Cryptol string that represents the Reflector's actions. It should 329 | start like this: 330 | 331 | .. code-block:: console 332 | 333 | reflectorBchars = "YRU // ... finish the rest 334 | 335 | .. answer: "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 336 | -> "YRUHQSLDPXNGOKMIEBFZCWVJAT" 337 | 338 | We can now reuse our code from the rotors to compute the offsets in 339 | the reflector, like this: 340 | 341 | .. code-block:: console 342 | 343 | reflectorBoff = stringToOffsets reflectorBchars 344 | 345 | Now test your reflector and your ``applyOffsetToIndex`` function: 346 | 347 | .. code-block:: console 348 | 349 | Main> indexToChar (applyOffsetToIndex reflectorBoff (charToIndex 'P')) 350 | 'I' 351 | Main> indexToChar (applyOffsetToIndex reflectorBoff (charToIndex 'O')) 352 | 'M' 353 | Main> indexToChar (applyOffsetToIndex reflectorBoff (charToIndex 'K')) 354 | 'N' 355 | 356 | 357 | Looking at the figure, indeed ``P`` :math:`\rightarrow` ``I``, 358 | ``O`` :math:`\rightarrow` ``M`` and ``K`` :math:`\rightarrow` ``N``. 359 | Go ahead and test it on ``A``, ``B`` and ``C`` and compare it with 360 | your Enigma to increase your confidence. 361 | 362 | Going reverse through the rotor 363 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 364 | 365 | .. index:: 366 | single: self-inverting function 367 | 368 | Because of the way the reflector works, if ``I`` :math:`\rightarrow` 369 | ``P``, we know the reverse is also true: ``P`` :math:`\rightarrow` 370 | ``I``. This kind of transformation is called a *self-inverting 371 | function*. You may have already noticed that the rotors are *not* 372 | self-inverting. Looking at Rotor I, going in the forward direction, 373 | ``A`` :math:`\rightarrow` ``E``, but going from left-to-right, ``E`` goes off the top of the 374 | figure to ``L``. So towards the goal of implementing a one-rotor Enigma, 375 | we're 2/3rds of the way there: we can go forward through the rotor, 376 | then through the reflector, and now what we need to do is go backwards 377 | through the rotor. Since the rotor is *not* self-inverting, we'll have 378 | to compute the backwards function. 379 | 380 | We could go through, one by one, and produce another string that 381 | represents the backwards transformation. However, we already have the 382 | information we want in the previous ``rotorIchars`` string. Look at 383 | this: 384 | 385 | .. code-block:: console 386 | 387 | alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 388 | rotorIchars = "EKMFLGDQVZNTOWYHXUSPAIBRCJ" 389 | ^- shows E -> A ^- shows A -> U 390 | 391 | In the forward direction, this shows us ``A`` :math:`\rightarrow` 392 | ``E``. It also tells us the backwards-mapping too: because ``E`` is 393 | in the first position, that tells us that in the reverse direction 394 | ``E`` :math:`\rightarrow` ``A``. Because ``K`` is in the second 395 | position, we know ``K`` :math:`\rightarrow` ``B``. We can follow this 396 | pattern to automate the process of reversing this operation in 397 | Cryptol! It's a bit tricky, so we'll go carefully: 398 | 399 | .. literalinclude:: cryptol/threeRotors.cry 400 | :language: cryptol 401 | :start-after: BeginIndexOf 402 | :end-before: EndIndexOf 403 | :linenos: 404 | 405 | .. index:: 406 | single: recursion 407 | single: permutation 408 | single: sequence comprehension 409 | single: where 410 | 411 | The first function we want is one that gives us the index of a 412 | character in a permutation. Line 1 defines our function, and says 413 | that it returns the last item of a sequence called ``candidates``. The 414 | ``where`` says we're about to define some variables (in this case only 415 | one). Line 2 says that ``candidates`` is a sequence that starts off by 416 | concatenating the sequence of one element (``[-1]``) with a *sequence 417 | comprehension* (remember those from Chapter 3?). Each element of the 418 | sequence is the result of an if statement: if ``c == s`` it's ``i`` 419 | otherwise it's ``p``. We don't yet know what any of those variables 420 | (except ``c``) is yet, but fear not: they're defined right below. Line 421 | 3 says that ``s`` *is drawn from the elements of permutation*. So each 422 | time through the loop, ``s`` is the next element of the permutation. Line 423 | 4 says that ``p`` is drawn from the elements of the ``candidates`` 424 | sequence. Interesting: We're using the sequence in the definition of 425 | itself! Just like in Chapter 3, this is an instance of *recursion*. 426 | Finally, line 5 says that ``i`` is drawn from the sequence ``[0..25]``. 427 | 428 | When this function runs, it builds up the ``candidates`` sequence, 429 | starting with ``-1``, each element keeps being set to ``p`` (which 430 | starts out with ``-1``) until the letter from permutation being examined, 431 | called ``s`` is equal to ``c``, the letter we're searching for. When 432 | that happens, the new element of ``candidates`` gets set to ``i``, 433 | which is the index of the match, because the numbers ``0 .. 25`` are the 434 | indexes of the elements of shuffled sequence. 435 | 436 | Here are the values of candidates as it proceeds through the 437 | string, with the call ``findIndex 'L' rotorI``: 438 | 439 | .. code-block:: console 440 | 441 | c: 'L' 442 | i: [ 0, 1, 2, 3, 4, 5, 6, .., 25 ] 443 | candidates = [-1, -1, -1, -1, 4, 4, 4, .., 4 ] 444 | s: E K M F L G D ... J 445 | note: s == 'L' here: ^ so the index i 446 | (4) is saved to candidates 447 | 448 | With this function, we can create the left-to-right version of a rotor 449 | given its right-to-left version: 450 | 451 | .. literalinclude:: cryptol/threeRotors.cry 452 | :language: cryptol 453 | :start-after: BeginInvertPermutation 454 | :end-before: EndInvertPermutation 455 | 456 | Save these functions and the definition of ``rotorIchars``, ``reflectorBchars`` and 457 | ``alphabet`` to a file called ``enigma.cry``, and run Cryptol on it: 458 | 459 | .. code-block:: console 460 | 461 | $ cryptol enigma.cry 462 | _ _ 463 | ___ _ __ _ _ _ __ | |_ ___ | | 464 | / __| '__| | | | '_ \| __/ _ \| | 465 | | (__| | | |_| | |_) | || (_) | | 466 | \___|_| \__, | .__/ \__\___/|_| 467 | |___/|_| version 2.4.0 468 | 469 | Loading module Cryptol 470 | Loading module Main 471 | Main> :set ascii=on 472 | Main> let rotorIrev = invertPermutation rotorIchars 473 | Assuming a = 7 474 | "UWYGADFPVZBECKMTHXSLRINQOJ" 475 | Main> rotorIrev @ asciiToIndex 'C' 476 | 'Y' 477 | Main> invertPermutation reflBchars == reflBchars 478 | True 479 | 480 | Indeed, going from left-to-right (backwards), ``C`` goes to ``Y``. 481 | Pretty cool, isn't it? We worked hard to write this code to save us the hassle of 482 | manually tracing the letters backwards. The benefit of doing it this 483 | way instead of by hand is that we have confidence that the 484 | backwards version of the rotors is actually correct. A single typo in 485 | the string would result in an error that would be really hard to track 486 | down. Finally, at the end, we tested whether the reflector is 487 | its own inverse permutation, and indeed it is. 488 | 489 | .. TODO: In a future chapter, we'll learn how to use Cryptol to prove 490 | properties about our rotors, such as that they are permutations of the 491 | alphabet, and the inverse rotor actually does invert its input. 492 | 493 | aside: add a discussion about permutations/shuffles vs. 494 | sequences of random numbers. Key point: invertability 495 | 496 | Combining the Rotor and Reflector 497 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 498 | 499 | Now we can combine the functions you've written so far 500 | into an implementation of a one-rotor Enigma: 501 | 502 | .. literalinclude:: cryptol/threeRotors.cry 503 | :language: cryptol 504 | :start-after: BeginOneChar 505 | :end-before: EndOneChar 506 | :linenos: 507 | 508 | There's a lot of code here, so let's go through it line by line: 509 | Lines 5 and 6 define the type of 510 | ``encryptOneChar``, and lines 7 and 8 define the name of the function 511 | and its arguments. We say here that the output of the function is 512 | ``outputChar``, but the ``where`` means we're defining ``outputChar`` 513 | and other variables in the following indented lines. Line 9 defines 514 | ``inputIndex`` to be the index of our input character (e.g., ``A`` 515 | would be 0). Next we define ``afterRI`` to be the index of the 516 | character after passing through Rotor I. Similarly, ``afterRefl`` is 517 | the index after passing through the Reflector. Finally, 518 | ``outputIndex`` is the index after going through ``rotorRev``. 519 | Finally, we convert ``outputIndex`` into our ``outputChar`` by using 520 | the well-named ``indexToChar`` function. 521 | 522 | Moving down to the ``encryptOneRotor`` function, it returns a sequence 523 | comprehension, which applies ``encryptOneChar`` to all of 524 | the characters of ``message``. In parallel with those characters, we 525 | have an index variable ``i`` go from ``1 .. 100``, and we rotate the 526 | ``rotorOff`` and ``rotorRevOff`` by that many steps, to simulate how 527 | we rotate the rotors before encrypting each character. The ``where`` 528 | at the end of the comprehension says we define the various sequences 529 | afterwards. The most tricky bit here is that we compute the 530 | ``rotorRev`` from ``rotor`` by using the ``invertPermutation`` 531 | function we wrote earlier. The rest of the variables are just the 532 | result of applying ``stringToOffsets`` to create the offset versions 533 | of the rotors, which are what our ``encryptOneChar`` function needs. 534 | 535 | Now we can test it with the exercise from Section 5.2: 536 | 537 | .. code-block:: console 538 | 539 | Main> encryptOneRotor rotorIchars reflBchars "YMXOVPE" 540 | Assuming a = 7 541 | "GOODJOB" 542 | 543 | Pretty amazing! One limitation of this implementation is that it can 544 | only handle messages up to 100 characters long. That, and it's missing 545 | a few features from our paper Enigma. We'll take care of those in the 546 | next chapter. 547 | 548 | What we learned this chapter 549 | ---------------------------- 550 | 551 | You learned some history about the Enigma machine, you built a 552 | simplified one out of cardboard and paper, and used it to decome some 553 | encrypted messages. Next, you learned how to represent Enigma's 554 | *rotors* and *reflector* in Cryptol, and used different types to 555 | separate the notions of *index*, *offset*, and *character*. Finally, 556 | you wrote a Cryptol implementation of a one-rotor Enigma, and used it 557 | to decrypt and encrypt messages. 558 | -------------------------------------------------------------------------------- /src/03_cryptol.rst: -------------------------------------------------------------------------------- 1 | Introducing Cryptol 2 | =================== 3 | 4 | .. TODO 5 | first "|" in a comprehension is pronounced "where" 6 | 7 | .. index:: algorithm, Cryptol 8 | 9 | Now that you understand how data can be represented in bits and have 10 | been introduced to cryptography using a paper computer, you're ready to 11 | learn a computer language that was designed for implementing 12 | cryptographic *algorithms*. An algorithm is a careful description of the 13 | steps for doing something. Algorithms themselves are math, but when you 14 | implement them, they're programs. The Caesar cipher from chapter one is 15 | a simple cryptographic algorithm. In this chapter, you'll learn about 16 | the programming language *Cryptol*, which was designed to make 17 | cryptographic implementations look as much like their mathematical 18 | algorithm description as possible. By the end of this chapter, you'll 19 | understand how to read and write simple cryptographic programs using 20 | Cryptol, and will be ready for the more complicated algorithms in the 21 | next chapter. 22 | 23 | Installing and running Cryptol on your computer 24 | ----------------------------------------------- 25 | 26 | How exactly to install and run Cryptol depends on whether your computer 27 | is running MacOS, Windows or Linux. Instructions for all three are 28 | provided on the Cryptol web site, which is ``http://cryptol.org`` 29 | 30 | You're ready to go with the rest of the chapter (and book) if you can 31 | run Cryptol, and follow along with the session below. 32 | 33 | .. (stick this back in once I've written a Cryptol-Console pygment) 34 | In the examples below, **``what you type will be in bold``**, and 35 | ``what the computer types will be in non-bold (like this)``. 36 | 37 | *start cryptol, however you're supposed to on your system* 38 | 39 | .. code-block:: console 40 | 41 | % cryptol 42 | _ _ 43 | ___ _ __ _ _ _ __ | |_ ___ | | 44 | / __| '__| | | | '_ \| __/ _ \| | 45 | | (__| | | |_| | |_) | || (_) | | 46 | \___|_| \__, | .__/ \__\___/|_| 47 | |___/|_| version 2.4.0 48 | 49 | Loading module Cryptol 50 | Cryptol> 4 + 2 51 | Assuming a = 3 52 | 0x6 53 | Cryptol> :q // <- to quit Cryptol 54 | % 55 | 56 | 57 | Here you've asked Cryptol to evaluate :math:`4 + 2`, and it responded 58 | with ``0x6``, which is a hexadecimal answer, but it's still just 6. 59 | Finally, we used ``:q`` to quit Cryptol. 60 | 61 | Types of data in Cryptol 62 | ------------------------ 63 | 64 | .. index:: type 65 | 66 | One of Cryptol's main features is that it is very careful about how data 67 | is represented. How data is laid out in bits is an example of a *type* in 68 | Cryptol. When you're talking about the type of something, often you'll 69 | see the thing, a colon (:) and then a description of its type 70 | 71 | For example, the type of the hex number ``0xFAB`` would be written: 72 | 73 | :: 74 | 75 | 0xFAB : [12]Bit 76 | 77 | You could read the above as "the type of the hex number ``FAB`` is a 78 | sequence of twelve bits." Cryptol can also talk about sequences of 79 | sequences. For example: 80 | 81 | :: 82 | 83 | [ 0xA, 0xB, 0xC, 0xD, 0xE ] : [5][4]Bit 84 | 85 | .. index:: sequence 86 | 87 | I would call this "a sequence of five elements, each having four bits". 88 | It turns out that the ``Bit`` at the end is optional: if the last 89 | thing in a type is a length (``[4]`` for example), you are supposed to 90 | add the ``Bit`` in your understanding of the type. 91 | 92 | You can ask Cryptol what the type of something is with the ``:t`` 93 | command, like this: 94 | 95 | .. code-block:: console 96 | 97 | Cryptol> :t 0xAB 98 | 0xab : [8] 99 | 100 | Here we've said "Hey, Cryptol: what's the type of Hex AB?" and Cryptol 101 | replied (in a friendly robotic voice) "Hex AB has the type *a sequence 102 | of length 8 of bits*". 103 | 104 | What do you think the type of a string of text should be? For example, 105 | what should the type of ``"hello cryptol"`` be? Stop reading for a 106 | minute and think about it. 107 | 108 | Really, don't just read ahead, think about the type of the string 109 | ``"hello cryptol"``. 110 | 111 | Okay, did you think about it? What did you come up with? One way to 112 | start answering questions like this one is outside in. By that I mean 113 | start by counting how many elements there are. In this case the length 114 | of ``"hello cryptol"`` is 13 characters. So, the start of the Cryptol 115 | type would be ``[13]``. Next, think about the type of each character. 116 | Remember that ASCII characters are 8-bits each, so the rest of the type 117 | is [8]. To check your answer you can just ask Cryptol: 118 | 119 | .. code-block:: console 120 | 121 | Cryptol> :t "hello cryptol" 122 | "hello cryptol" : [13][8] 123 | 124 | Enumerations: sequence shortcuts 125 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 126 | 127 | .. index:: enumeration 128 | 129 | Cryptol has some fancy ways of creating sequences other than just having 130 | you type them in. One way is called *enumerations*. They're a short-hand 131 | way of writing sequences of numbers that increment in a predictable way. 132 | Here are some examples: 133 | 134 | .. code-block:: console 135 | 136 | Cryptol> [1 .. 10] 137 | Assuming a = 4 138 | [0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa] 139 | 140 | The ``Assuming a = 4`` is Cryptol helpfully telling you that it decided to 141 | use 4 bits per element of the sequence, because we weren't specific. 142 | From here on out, I'll leave out the ``Assuming...`` messages, unless 143 | they matter. Cryptol used 1 as the lower bound, 10 as the upper bound 144 | (which is ``0xa`` in hex) and it incremented by one for each of the 145 | elements in between. 146 | 147 | You can increment by a different amount by providing two starting 148 | elements. The step-value is the difference between them. For example: 149 | 150 | .. code-block:: console 151 | 152 | Cryptol> [1, 3 .. 10] // the step here is 2 (because 3-1=2) 153 | [0x1, 0x3, 0x5, 0x7, 0x9] 154 | Cryptol> [10, 9 .. 1] // counting down (step = -1) 155 | [0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1]`` 156 | 157 | Comprehensions: manipulating sequences 158 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 159 | 160 | .. index:: 161 | single: ! sequence comprehension 162 | single: variable 163 | 164 | In addition to shortcuts for creating sequences, Cryptol has powerful 165 | ways of manipulating them, called *sequence comprehensions*. The way you 166 | write them in Cryptol is based on mathematical notation, so once you get 167 | used to them, you'll know some advanced math notation, too! 168 | 169 | Here's how it works: a sequence comprehension is inside of square 170 | brackets, just like the sequences we've seen already. Then inside of 171 | that, there are two parts: first is a formula for building each element 172 | of the sequence The formula is a mathematical expression that can have 173 | one or more *variables* in it. The second part is to define the values 174 | of the variables as being *extracted* from other sequences. This will 175 | make more sense with some examples: 176 | 177 | .. code-block:: console 178 | 179 | Cryptol> [ 2 * x | x <- [1 .. 10]] 180 | Assuming a = 4 181 | [0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe, 0x0, 0x2, 0x4] 182 | 183 | Reading the line we typed in goes like this: "Construct a sequence whose 184 | elements are two times x, where x is drawn from the list one to ten." 185 | 186 | Cryptol helpfully told us that it decided the elements of the list are 187 | four bits each. Without being told otherwise, that's also the size of 188 | the elements of the new list, which is why our numbers wrap around to 189 | 0x0, 0x2, 0x4 at the end. If we want Cryptol to keep track of more bits 190 | in our output sequence, we can specify the type of the comprehension, 191 | like this: 192 | 193 | .. code-block:: console 194 | 195 | Cryptol> [ 2 * x | x <- [1 .. 10]]:[10][8] 196 | [0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14] 197 | 198 | Here we've asked for the comprehension's type to be ten elements of 199 | eight bits each, and the result doesn't wrap around. 200 | 201 | Defining functions 202 | ------------------ 203 | 204 | .. index:: 205 | single: function 206 | single: parameters 207 | single: defining functions 208 | single: function definition 209 | 210 | In math, *functions* describe a way of creating an *output* from one or 211 | more *inputs*. Functions in Cryptol are almost exactly the same, and you can give 212 | them names if you want. Here's a picture example of a functioned named 213 | :math:`f`, which takes two *parameters*, :math:`x` and :math:`y` and 214 | returns their sum: 215 | 216 | :: 217 | 218 | Inputs Function Output 219 | _________________ 220 | 7 ---------> x | | 221 | | f(x,y) = x + y |---------> 12 222 | 5 ---------> y |_________________| 223 | 224 | (TODO: make this pretty) 225 | 226 | One way to define a function is with the ``let`` command, like this: 227 | 228 | .. code-block:: console 229 | 230 | Cryptol> let double x = x + x 231 | Cryptol> double 4 232 | Assuming a = 3 233 | 0x0 234 | 235 | What? :math:`4+4=0`? Oh, yeah, Cryptol let us know it was working with 3 236 | bits, because that's how many you need for 4, but 4+4 is 8 which needs 4 237 | bits, and the remainder is 0. The quickest way to get Cryptol to work 238 | with more bits is to use hex and add a leading 0\ [#]_: 239 | 240 | .. code-block:: console 241 | 242 | Cryptol> double 0x04 243 | 0x08 244 | 245 | .. [#] 246 | another way to do this is use decimal numbers, which are friendly, 247 | but specify the width of the output, like this: ``4 + 4 :[8]``. 248 | 249 | Whew. That's better. Here's a definition of our function :math:`f`, 250 | which has two parameters: 251 | 252 | .. code-block:: console 253 | 254 | Cryptol> let f x y = x + y 255 | Cryptol> f 0x07 0x05 256 | 0x0c 257 | 258 | If you're tired of reading hex, you can ask Cryptol to speak back to you 259 | in decimal: 260 | 261 | .. code-block:: console 262 | 263 | Cryptol> :set base=10 // <- use base 10 output 264 | Cryptol> f 0x07 0x05 265 | 12 266 | 267 | You can also call functions inside a sequence comprehension, like this: 268 | 269 | .. code-block:: console 270 | 271 | Cryptol> [ double x | x <- [ 0 .. 10 ]] 272 | Assuming a = 4 273 | [0x0, 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe, 0x0, 0x2, 0x4] 274 | 275 | And it should be no surprise that you can call functions from inside 276 | functions: 277 | 278 | .. code-block:: console 279 | 280 | Cryptol> let quadruple x = double (double x) 281 | Cryptol> quadruple 0x04 282 | 16 <- we still have output set to base 10 283 | 284 | 285 | Exercises: exploring Cryptol 286 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 287 | 288 | You'll probably have noticed that computers are very picky when you're 289 | programming. If you get even one letter wrong in a function's name (a misspelling like 290 | ``duoble``), Cryptol will complain. Computers are also very patient. 291 | You can try again. And again. One thing that's really handy is that 292 | you can press the up arrow (:math:`\uparrow`) key to recall earlier 293 | things you've typed, and you can use the left arrow, backspace and 294 | delete keys to fix things you've typed. Super-handy! 295 | 296 | #) You've defined a function, *f*, which takes two arguments *x* and 297 | *y*. Use this pattern to define a new function, *g*, and takes 298 | three arguments (maybe add a *z*?) and adds them. 299 | 300 | #) Experiment with ``:set base=10`` and ``:set base=16`` and run your 301 | *f* and *g* functions on different arguments. Also experiment with 302 | ``:set ascii=on`` and ``:set ascii=off`` and use sequence 303 | comprehensions with ``x <- [ 0 .. 10 ]`` as well as 304 | ``x <- [ 'a' .. 'Z']``. 305 | 306 | #) Crytpol supports Really Big Numbers. For example, it's 307 | estimated that the number of atoms in the Earth is about :math:`10^{50}`. 308 | You can enter that number in Cryptol (specifying that it uses a 309 | lot of bits) like this: ``10^^50:[200]``. How many Earth's worth 310 | of atoms can you store in 200 bits? 311 | 312 | Functions on sequences 313 | ---------------------- 314 | 315 | Now that you know about functions and sequences, it's time to learn 316 | about some functions that operate on sequences. 317 | 318 | Extracting elements from sequences 319 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 320 | 321 | .. index:: index operator 322 | 323 | The first one is called the *index operator*. That's a fancy way of 324 | saying getting the n\ :sup:`th` element out of a sequence. It works 325 | like this: 326 | 327 | .. code-block:: console 328 | :linenos: 329 | 330 | Cryptol> let alphabet=['a' .. 'z'] 331 | Cryptol> alphabet @ 5 332 | 102 333 | Cryptol> :set ascii=on 334 | Cryptol> alphabet @ 5 335 | 'f' 336 | 337 | .. index:: zero-based indexing 338 | 339 | On line 1, we created a variable called *alphabet*, which is a sequence 340 | of 8-bit integers that are the ASCII values of the letters of the 341 | alphabet. On line 2 we used the *index operator*, which is the ``@`` 342 | symbol, to extract the element at location 5 of that sequence, which is 343 | 102. Since wanted to see it as a character, on line 4 we used 344 | ``:set ascii=on``, which tells Cryptol to print 8-bit numbers as 345 | characters. Finally, on line 5 we re-did the ``@`` operation, which gave 346 | us ``f``, which is the 6\ :sup:`th` letter of the alphabet. Why the 6th 347 | character and not the 5th? Cryptol, like most programming languages, 348 | uses *zero-based indexing*, which means that ``alphabet @ 0`` is the first 349 | element of the sequence, ``alphabet @ 1`` is the second element and so 350 | on. 351 | 352 | .. index:: reverse index operator 353 | 354 | Cryptol also provides a *reverse index operator*, which counts backwards 355 | from the end of the sequence, like this: 356 | 357 | .. code-block:: console 358 | 359 | Cryptol> alphabet!25 360 | 'a' 361 | Cryptol> alphabet!0 362 | 'z' 363 | 364 | What happens if you try to go off the end (or past the beginning) of a 365 | sequence? Let's try: 366 | 367 | .. code-block:: console 368 | 369 | Cryptol> alphabet@26 370 | invalid sequence index: 26 371 | 372 | .. index:: infix operators 373 | 374 | One more thing: ``@`` and ``!`` act a lot like functions, but they're 375 | called *infix operators*. The only difference between a function and an 376 | operator is that when you call a function, its name comes first followed 377 | by the values you want the function to operate on (we call those its 378 | *arguments*). Operators only work with two arguments, and the operator 379 | name comes *between* the two arguments. All of the normal math operators 380 | you're familiar with are infix operators, like: :math:`5 + 2 - 3`. 381 | 382 | .. index:: 383 | single: arguments 384 | single: parameters 385 | single: arguments vs. parameters 386 | 387 | **Arguments vs. parameters**: when we talk about defining and calling 388 | functions, we've talked about both *arguments* and *parameters*, so you 389 | may wonder "what's the difference?" The answer is that *parameters are 390 | in a function's definition*, and *arguments are what you pass to a 391 | function when you call it*. So: 392 | 393 | .. code-block:: console 394 | 395 | let foo x y = x - y // x and y are the parameters of *f* 396 | f 5 3 // here we've passed 5 and 3 as arguments to f 397 | 398 | Reversing a sequence 399 | ~~~~~~~~~~~~~~~~~~~~ 400 | 401 | Cryptol provides a function called ``reverse``. Let's try it: 402 | 403 | .. code-block:: console 404 | 405 | Cryptol> reverse ['a' .. 'z'] 406 | "zyxwvutsrqponmlkjihgfedcba"` 407 | 408 | Pretty handy! 409 | 410 | Concatenating sequences 411 | ~~~~~~~~~~~~~~~~~~~~~~~ 412 | 413 | The ``#`` operator combines two sequences into one sequence, like this: 414 | 415 | .. code-block:: console 416 | 417 | Cryptol> ['a' .. 'z'] # ['0' .. '9'] 418 | "abcdefghijklmnopqrstuvwxyz0123456789" 419 | 420 | "Rotating" elements of a sequence 421 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 422 | 423 | The ``>>>`` and ``<<<`` operators *rotate* the elements of a sequence 424 | :math:`n` places. For example, 425 | 426 | ``['a' .. 'z'] >>> 1`` returns ``"zabcdefghijklmnop qrstuvwxy"``. All of 427 | the elements get shifted 1 place to the right, but the ones that fall 428 | off the end *rotate* back to the beginning. 429 | 430 | ``['a' .. 'z'] <<< 2`` returns ``"cdefghijklmnopqrs tuvwxyzab"``. 431 | Everything moves to the left two places, but the first two, which fall 432 | off the front, rotate around to the end. 433 | 434 | Functions have types, too 435 | ~~~~~~~~~~~~~~~~~~~~~~~~~ 436 | 437 | *This section is a deep-dive into Cryptol's fancy type system. You 438 | don't need to know this to complete the first few exercises, but 439 | it's really neat, and will help you understand some of the things 440 | Cryptol says to you.* 441 | 442 | We mentioned earlier in this chapter that Cryptol is very careful about 443 | the types of things. In addition to data, functions in Cryptol have a 444 | type. The type tells you how many arguments a function takes as input, 445 | and what type each of those arguments needs to have, as well as the type 446 | of the output. Just like for data, you can ask Cryptol what the type of 447 | a function is by using ``:t``, like this: 448 | 449 | .. code-block:: console 450 | 451 | Cryptol> :t double 452 | double : {a} (Arith a) => a -> a 453 | 454 | The way you read a function-type in Cryptol has two parts, which are 455 | separated by a "fat arrow" (``=>``). Before the fat arrow is a 456 | description of the types, and after the fat arrow is the description of 457 | the inputs and the output. Each of them is separated by a "normal arrow" 458 | (``->``). The last one is always the output. The ones before that are 459 | the parameters. 460 | 461 | Looking at our type of ``double``, we see that it operates on things 462 | that you can perform arithmetic on ``(Arith a)``, it takes one argument 463 | and produces output of the same type. 464 | 465 | You can ask Cryptol about the types of an *infix operator* by 466 | surrounding it with parentheses, like this: 467 | 468 | .. code-block:: console 469 | 470 | Cryptol> :t (+) 471 | (+) : {a} (Arith a) => a -> a -> a 472 | 473 | This says that plus takes two inputs, and produces one output, all of 474 | which are *Arithmetic*. 475 | 476 | What's an example of an input type that isn't Arithmetic? Concatenation 477 | is one. Check this out: 478 | 479 | .. code-block:: console 480 | 481 | Cryptol> :t (#) 482 | (#) : {front, back, a} (fin front) => 483 | [front]a -> [back]a -> [front + back]a 484 | 485 | This is a bit complex: What is says is that ``front`` and ``back`` are 486 | both sequence-lengths, and that ``front`` is of finite length ``(fin)``. 487 | After the ``=>``, it lets us know that the first argument has ``front`` 488 | elements, the second argument has ``back`` elements, and the output has 489 | ``front + back`` elements. The ``a`` everywhere lets us know that the 490 | sequence could be of anything: a single ``Bit``, or another sequence, or 491 | whatever. They do all have to be the same thing, though. 492 | 493 | Implementing the Caesar cipher in Cryptol 494 | ----------------------------------------- 495 | 496 | Using what you've learned so far, let's implement the Caesar cipher in 497 | Cryptol. Let's start by breaking down the process of encrypting and 498 | decrypting data using the Caesar cipher. 499 | 500 | Let's figure out what the function declaration should look like. We know that 501 | the encrypt operation takes a key and a message, so the function 502 | declaration probably looks something like: 503 | 504 | ``caesarEncrypt key message =`` 505 | 506 | Let's talk about how we can represent the key. In Chapter 1, we talked 507 | about settings of the key being something like K\ :math:`\leftrightarrow`\ D, but 508 | that's hard to represent mathematically. If we straighten out our Caesar 509 | Cipher wheels into a line, it looks something like this: 510 | 511 | :: 512 | 513 | abcdefghijklmnopqrstuvwxyz <- outer wheel 514 | zyxwvutsrqponmlkjihgfedcba <- inner wheel 515 | 516 | To use the code wheel in this arrangement, look up a character from the 517 | top line, and the character directly below it is the encoded / decoded 518 | translation of that character. 519 | 520 | .. index:: rotate operator (>>>) 521 | 522 | If we think about the *rotate* operator (``>>>``), we see that it does 523 | something really useful. For example, let's rotate the inner wheel by 4: 524 | 525 | :: 526 | 527 | abcdefghijklmnopqrstuvwxyz <- outer wheel 528 | dcbazyxwvutsrqponmlkjihgfe <- inner wheel >>> 4 529 | 530 | This corresponds to the ``A``\ :math:`\leftrightarrow`\ ``D`` key in the 531 | ``HELLO`` example in Chapter 1. It even makes sense: the description 532 | (rotating the inner wheel by 4 positions) *sounds* like what we did with 533 | the paper Caesar cipher. 534 | 535 | At this point we'd *like to use* the index operator (``@``) to get the 536 | ciphertext from the inner wheel that corresponds to the plaintext on the 537 | outer wheel. The indexing operator needs to be a number, not a letter. 538 | For the index operator to do what we want, plaintext 'a' should be '0', 539 | 'b' should be '1', all the way up to 'z' should be 25. Let's pause to 540 | think about how to achieve that in Cryptol. First, remember that a 541 | character in Cryptol is already a number: its ASCII code. So, what if we 542 | subtract the ASCII code for 'a' from our plaintext character? 543 | 544 | In ASCII, ``'a'`` is 0x61, so ``'a'`` - ``'a'`` is 0, which is a good 545 | start. ``'b'`` is 0x62, so ``'b'`` - ``'a'`` is 1, which is also what 546 | we're after. Finally, ``'z'`` - ``'a'`` is 25, so for that range of 547 | characters, it's good! Here's a simple function that takes an ASCII 548 | character and returns its index in the alphabet: 549 | 550 | .. code-block:: console 551 | 552 | Cryptol> let asciiToIndex c = c - 'a' 553 | 554 | Using this function to encrypt one letter would look like this: 555 | 556 | .. code-block:: console 557 | 558 | Cryptol> let encryptChar wheel c = wheel @ (asciiToIndex c) 559 | Cryptol> let codeWheel key = reverse alphabet >>> key 560 | Cryptol> encryptChar (codeWheel 4) 'h' 561 | 'w' 562 | 563 | The ``encryptChar`` function takes a shifted wheel and a character 564 | ``c``. It uses the index operator to extract the element from the wheel 565 | corresponding to the index value of the character. On the next line we 566 | defined ``codeWheel`` to be the reversed-alphabet shifted by our key. 567 | Finally we called our function. The first argument is our ``codeWheel`` 568 | with ``4`` as the key, and the second argument is our plaintext ``h``. 569 | The output is ``w`` as we hoped. 570 | 571 | Now we're ready to have Cryptol do this for every character in a string. 572 | Remember our sequence comprehensions? Here's how that comes together\ [#]_: 573 | 574 | .. [#] Some examples have backslashes (\\) in them: it's 575 | because they're on more than one line: if you type the \\, Cryptol 576 | will let you continue typing on the next line. Alternatively you can 577 | type it all on one line (and skip typing the \\). 578 | 579 | .. code-block:: console 580 | 581 | Cryptol> let encrypt key message = \ 582 | [ encryptChar (codeWheel key) c | c <- message ] 583 | Cryptol> encrypt 4 "hello" 584 | "wzssp" 585 | 586 | Hooray! 587 | 588 | Now, what about decryption? 589 | 590 | If you recall from Chapter 1, encryption and decryption are the same 591 | process. Let's test if that works: 592 | 593 | :: 594 | 595 | Cryptol> encrypt 4 "wzssp" 596 | "hello" 597 | 598 | Since that's not a satisfying name for a decryption routine, we can 599 | define ``decrypt`` in terms of our ``encrypt`` function: 600 | 601 | .. code-block:: console 602 | 603 | Cryptol> let decrypt k m = encrypt k m 604 | Cryptol> decrypt 4 "wzssp" 605 | "hello" 606 | 607 | Ah, much better. One thing to note here: in our definition of encrypt, 608 | the parameters were called ``key`` and ``message``, but here we called 609 | them ``k`` and ``m``. The reason that's not a problem is that when 610 | you're defining a function, you are free to name the parameters whatever 611 | you want - the only thing you have to remember is to use those same 612 | names in the body of your function. 613 | 614 | This has been a huge chapter. If anything didn't make sense, go back and 615 | read it again, or ask a partner for help. We shouldn't go much further 616 | without really understanding what we've done so far. If Cryptol gives 617 | you mysterious errors instead of the output you expect, check what 618 | you've typed very carefully - we'll learn more about the errors Cryptol 619 | prints, and what you can learn from them. 620 | 621 | Handling unexpected inputs 622 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 623 | 624 | Let's try encrypting something new: 625 | 626 | .. code-block:: console 627 | 628 | Cryptol> encrypt 7 "I LOVE PUZZLES" 629 | 630 | [warning] at :1:1--1:30: 631 | Defaulting type parameter 'bits' 632 | of literal or demoted expression 633 | at :1:8--1:9 634 | to 3 635 | Assuming a = 7 636 | 637 | invalid sequence index: 232 638 | 639 | Egads - what just happened? When I see something like this happen, I 640 | first read the error message, then I think about what I did that could 641 | cause it. Starting at the top, the ``[warning]...`` tells you advisory 642 | things, not errors. That warning goes on for four lines, ending in 643 | ``to 3``. The line after that is the normal helpful Cryptol telling you 644 | it's decided to use 7 bits for your ASCII string. 645 | 646 | The problem is in that last line ``invalid sequence index: 232``. We've 647 | tried to use the index operator (``@``) with an invalid argument. 648 | ``232`` is way bigger than 25 - where did that come from? We subtracted 649 | ``'a'`` to make sure our indexes were all between 0 and 25, right? 650 | 651 | At this point, it's time to start thinking about what we did wrong to 652 | cause this. Comparing this message to the one that worked, ``"hello"``, 653 | there are two main differences: our new message is in ALL CAPS, and it 654 | also has spaces in it. It turns out those are both problems we need to 655 | fix. 656 | 657 | Let's start by handling upper case input. There are (at least) two ways 658 | we could do it. One is to have upper case input produce upper case 659 | output, and the other is to just make everything lower case. I think the 660 | second option is simpler, so let's do that. 661 | 662 | Recall from Chapter 2's discussion about ASCII's clever design, that 663 | there's a simple way to convert between upper and lower case. Here are 664 | the Hex values of the ASCII codes for ``a``, ``A``, ``z`` and ``Z`` 665 | 666 | +-----------+-------+-------+-------+-------+ 667 | | Character | A | a | Z | z | 668 | +-----------+-------+-------+-------+-------+ 669 | | Hex ASCII | 0x41 | 0x61 | 0x5a | 0x7a | 670 | +-----------+-------+-------+-------+-------+ 671 | 672 | .. index:: conditional statements 673 | 674 | Hey, the difference between the upper and lower case values is exactly 675 | 0x20! If we want everything in lower case (WHO LIKES SHOUTING, REALLY?), 676 | if a character's ASCII value is less than 0x61, we can add 0x20 to make it lower 677 | case. We use *conditional statements* to do that in Cryptol: 678 | 679 | .. code-block:: console 680 | 681 | Cryptol> let toLower c = if c < 'a' then c + 0x20 else c 682 | Cryptol> toLower 'I' 683 | 'i' 684 | 685 | and just to make sure we didn't break already lower case input: 686 | 687 | .. code-block:: console 688 | 689 | Cryptol> toLower 'i' 690 | 'i' 691 | 692 | As you can see, a conditional statement has three parts: the 693 | *condition*, the *if-expression* and the *else-expression*. 694 | 695 | Now we can use ``toLower`` to improve ``asciiToIndex``, then use our 696 | up-arrow trick to re-enter the definitions of ``encryptChar`` and 697 | ``encrypt`` without having to retype them\ [#]_. 698 | 699 | .. code-block:: console 700 | 701 | Cryptol> let asciiToIndex c = toLower c - 'a' 702 | Cryptol> let encryptChar wheel c = wheel @ (asciiToIndex c) 703 | Cryptol> let encrypt key message = \ 704 | [ encryptChar (codeWheel key) c | c <- message ] 705 | 706 | .. [#] For the functions you entered on multiple lines, you'll have to use 707 | the up-arrow to fetch each line after you press Enter. It works! If you 708 | somehow mess up, just try again: the computer won't mind. 709 | 710 | And now we can encrypt text with upper and lower case (but without 711 | spaces): 712 | 713 | .. code-block:: console 714 | 715 | Cryptol> encrypt 7 "iLOVEpuzzles" 716 | "yvslcrmhhvco" 717 | Cryptol> decrypt 7 "yvslcrmhhvco" 718 | "ilovepuzzles" 719 | 720 | Now, how to handle spaces. The usual way to handle spaces with the 721 | Caesar cipher (not in cryptography in general) is to pass them through. 722 | Sure, it makes the code weaker (you can see the length of words), but 723 | this part of the lesson isn't about good codes. To pass spaces through 724 | from the input to the output, the best place to do that is with a 725 | conditional in the encryptChar function: 726 | 727 | .. code-block:: console 728 | 729 | Cryptol> let encryptChar wheel c = \ 730 | if c == ' ' then c else wheel @ (asciiToIndex c) 731 | 732 | Let's test it, first on a space (since that's our new feature), then on 733 | an uppercase letter, and then on a lowercase letter: 734 | 735 | .. code-block:: console 736 | 737 | Cryptol> encryptChar (codeWheel 7) ' ' 738 | ' ' 739 | Cryptol> encryptChar (codeWheel 7) 'I' 740 | 'y' 741 | Cryptol> encryptChar (codeWheel 7) 'i' 742 | 'y' 743 | 744 | Yay, it looks like it'll work. Now let's use up-arrow to re-define the 745 | ``encrypt`` function that calls it, and encrypt and decrypt our 746 | original message: 747 | 748 | .. code-block:: console 749 | 750 | Cryptol> let encrypt key message = \ 751 | [ encryptChar (codeWheel key) c | c <- message ] 752 | Cryptol> encrypt 7 "I LOVE PUZZLES" 753 | "y vslc rmhhvco" 754 | Cryptol> decrypt 7 "y vslc rmhhvco" 755 | "i love puzzles" 756 | 757 | Wow - it all worked! If it didn't, go through the error messages, and 758 | see if you can figure out what happened. 759 | 760 | What we learned this chapter 761 | ---------------------------- 762 | 763 | We covered a lot of ground this chapter: 764 | 765 | - Launching Cryptol and asking about *types* of data with the ``:t`` 766 | command, 767 | - *enumerations* are shortcuts for creating sequences, like 768 | ``[1 .. 10]``, 769 | - *comprehensions* are ways of manipulating elements of sequences, 770 | - *functions* define how to create an output value from one or more 771 | inputs (called *arguments*), 772 | - a number of functions that operate on sequences, like *indexing*, 773 | *reversing*, *concatenating*, 774 | - finally, we implemented the Caesar cipher in Cryptol, step by step: 775 | 776 | 1. converting ASCII characters to indexes, 777 | 2. rotating the alphabet to make an encryption sequence, 778 | 3. indexing the encryption sequence to encrypt one character, 779 | 4. using a *comprehension* to encrypt a whole string, 780 | 5. using *conditional expressions* to convert uppercase to lowercase, 781 | 6. and handling the space character, ``' '``, by passing it through. 782 | 783 | That's a lot of stuff - congratulations! 784 | 785 | --------------------------------------------------------------------------------