About the Technical Reviewers
{8}————————————————
Brief Contents
| Acknowledgments | xix |
|---|---|
| Introduction | xx |
| Chapter 1: Making Paper Cryptography Tools | 1 |
| Chapter 2: Programming in the Interactive Shell | 11 |
| Chapter 3: Strings and Writing Programs | 21 |
| Chapter 4: The Reverse Cipher | 39 |
| Chapter 5: The Caesar Cipher | 53 |
| Chapter 6: Hacking the Caesar Cipher with Brute-Force | 69 |
| Chapter 7: Encrypting with the Transposition Cipher | 77 |
| Chapter 8: Decrypting with the Transposition Cipher | 99 |
| Chapter 9: Programming a Program to Test Your Program | 113 |
| Chapter 10: Encrypting and Decrypting Files | 127 |
| Chapter 11: Detecting English Programmatically | 141 |
| Chapter 12: Hacking the Transposition Cipher | 161 |
| Chapter 13: A Modular Arithmetic Module for the Affine Cipher | 171 |
| Chapter 14: Programming the Affine Cipher | 185 |
| Chapter 15: Hacking the Affine Cipher | 197 |
| Chapter 16: Programming the Simple Substitution Cipher | 207 |
| Chapter 17: Hacking the Simple Substitution Cipher | 221 |
| Chapter 18: Programming the Vigenère Cipher | 247 |
| Chapter 19: Frequency Analysis | 259 |
| Chapter 20: Hacking the Vigenère Cipher | 279 |
| Chapter 21: The One-Time Pad Cipher | 315 |
| Chapter 22: Finding and Generating Prime Numbers |
321 |
| Chapter 23: Generating Keys for the Public Key Cipher | 335 |
| Chapter 24: Programming the Public Key Cipher | 349 |
| Appendix: Debugging Python Code | 375 |
| Index | 381 |
{9}————————————————
{10}————————————————
Contents in Detail
| ACKNOWLEDGMENTS | xix | ||
|---|---|---|---|
| INTRODUCTION | xxi | ||
| Who Should Read This Book? | xxii | ||
| What’s in This Book? | xxiii | ||
| How to Use This Book. | xxiv | ||
| Typing Source Code | xxiv | ||
| Checking for Typos | xxv | ||
| Coding Conventions in This Book | xxv | ||
| Online Resources | xxv | ||
| Downloading and Installing Python | xxv | ||
| Windows Instructions. | xxvi | ||
| macOS Instructions | xxvi | ||
| Ubuntu Instructions | xxvi | ||
| Downloading pyperclip.py | xxvi | ||
| Starting IDLE | xxvii | ||
| Summary | xxvii | ||
| 1 | |||
| MAKING PAPER CRYPTOGRAPHY TOOLS | 1 | ||
| What Is Cryptography? | 2 | ||
| Codes vs. Ciphers | 3 | ||
| The Caesar Cipher | 4 | ||
| The Cipher Wheel | 4 | ||
| Encrypting with the Cipher Wheel | 5 | ||
| Decrypting with the Cipher Wheel | 6 | ||
| Encrypting and Decrypting with Arithmetic | 7 | ||
| Why Double Encryption Doesn’t Work | 8 | ||
| Summary | 8 | ||
| Practice Questions | 9 | ||
| 2 | |||
| PROGRAMMING IN THE INTERACTIVE SHELL | 11 | ||
| Some Simple Math Expressions | 12 | ||
| Integers and Floating-Point Values | 13 | ||
| Expressions | 13 | ||
| Order of Operations | 14 | ||
| Evaluating Expressions | 14 | ||
| Storing Values with Variables | 15 | ||
| Overwriting Variables | 17 | ||
| Variable Names | 18 | ||
| Summary | 18 | ||
| Practice Questions | 19 | ||
| 3 | |||
| STRINGS AND WRITING PROGRAMS | 21 | ||
| Working with Text Using String Values | 22 | ||
| String Concatenation with the + Operator | 23 | ||
| String Replication with the * Operator | 24 | ||
| Getting Characters from Strings Using Indexes | 24 | ||
| Printing Values with the print() Function | 27 | ||
| Printing Escape Characters | 28 | ||
| Quotes and Double Quotes | 29 | ||
| Writing Programs in IDLE’s File Editor | 30 | ||
| Source Code for the “Hello, World!” Program | 31 | ||
| Checking Your Source Code with the Online Diff Tool | 31 | ||
| Using IDLE to Access Your Program Later | 32 | ||
| Saving Your Program | 32 | ||
| Running Your Program | 33 | ||
| Opening the Programs You’ve Saved | 34 | ||
| How the “Hello, World!” Program Works | 34 | ||
| Comments | 34 | ||
| Printing Directions to the User | 34 | ||
| Taking a User’s Input | 35 | ||
| Ending the Program | 35 | ||
| Summary | 36 | ||
| Practice Questions | 37 | ||
| 4 | |||
| THE REVERSE CIPHER | 39 | ||
| Source Code for the Reverse Cipher Program | 40 | ||
| Sample Run of the Reverse Cipher Program | 40 | ||
| Setting Up Comments and Variables | 41 | ||
| Finding the Length of a String | 41 | ||
| Introducing the while Loop | 42 | ||
| The Boolean Data Type | 43 | ||
| Comparison Operators | 43 | ||
| Blocks | 45 | ||
| The while Loop Statement | 46 | ||
| “Growing” a String | 47 | ||
| Improving the Program with an input() Prompt | 50 | ||
| Summary | 50 | ||
| Practice Questions | 51 | ||
| 5 | |||
| THE CAESAR CIPHER | 53 | ||
| Source Code for the Caesar Cipher Program | 54 | ||
| Sample Run of the Caesar Cipher Program | 55 | ||
| Importing Modules and Setting Up Variables | 56 | ||
| Constants and Variables | 57 | ||
| The for Loop Statement | 57 | ||
| An Example for Loop | 58 | ||
| A while Loop Equivalent of a for Loop | 59 | ||
| The if Statement | 59 | ||
| An Example if Statement | 60 | ||
| The else Statement | 60 | ||
| The elif Statement | 61 | ||
| The in and not in Operators | 61 | ||
| The find() String Method | 62 | ||
| Encrypting and Decrypting Symbols | 63 | ||
| Handling Wraparound | 64 | ||
| Handling Symbols Outside of the Symbol Set | 65 | ||
| Displaying and Copying the Translated String | 65 | ||
| Encrypting Other Symbols | 66 | ||
| Summary | 66 | ||
| Practice Questions | 67 | ||
| 6 HACKING THE CAESAR CIPHER WITH BRUTE-FORCE |
69 | ||
| Source Code for the Caesar Cipher Hacker Program | 70 | ||
| Sample Run of the Caesar Cipher Hacker Program | 71 | ||
| Setting Up Variables | 72 | ||
| Looping with the range() Function | 72 | ||
| Decrypting the Message | 73 | ||
| Using String Formatting to Display the Key and Decrypted Messages |
75 | ||
| Summary | 76 | ||
| Practice Question | 76 | ||
| 7 ENCRYPTING WITH THE TRANSPOSITION CIPHER |
77 | ||
| How the Transposition Cipher Works | 78 | ||
| Encrypting a Message by Hand | 79 | ||
| Creating the Encryption Program | 80 | ||
| Source Code for the Transposition Cipher Encryption Program | 81 | ||
| Sample Run of the Transposition Cipher Encryption Program | 82 | ||
| Creating Your Own Functions with def Statements | 82 | ||
| Defining a Function that Takes Arguments with Parameters | 83 | ||
| Changes to Parameters Exist Only Inside the Function | 84 | ||
| Defining the main() Function | 85 | ||
| Passing the Key and Message As Arguments | 86 | ||
| The List Data Type | 86 | ||
| Reassigning the Items in Lists | 87 | ||
| Lists of Lists | 88 | ||
| Using len() and the in Operator with Lists | 89 | ||
| List Concatenation and Replication with the + and * Operators | 89 | ||
| The Transposition Encryption Algorithm | 90 | ||
| Augmented Assignment Operators | 91 | ||
| Moving currentIndex Through the Message | 92 | ||
| The join() String Method | 93 | ||
| Return Values and return Statements | 94 | ||
| A return Statement Example | 94 | ||
| Returning the Encrypted Ciphertext | 95 | ||
| The name Variable | 95 | ||
| Summary | 96 | ||
| Practice Questions | 97 | ||
| 8 | |||
| DECRYPTING WITH THE TRANSPOSITION CIPHER 99 |
|||
| How to Decrypt with the Transposition Cipher on Paper 100 |
|||
| Source Code for the Transposition Cipher Decryption Program 101 |
|||
| Sample Run of the Transposition Cipher Decryption Program 102 |
|||
| Importing Modules and Setting Up the main() Function 102 |
|||
| Decrypting the Message with the Key 103 |
|||
| The round(), math.ceil(), and math.floor() Functions 103 |
|||
| The decryptMessage() Function 104 |
|||
| Boolean Operators 106 |
|||
| Adjusting the column and row Variables 109 |
|||
| Calling the main() Function 110 |
|||
| Summary 110 |
|||
| Practice Questions 111 |
|||
| 9 | |||
| PROGRAMMING A PROGRAM TO TEST YOUR PROGRAM 113 |
|||
| Source Code for the Transposition Cipher Tester Program 114 |
|||
| Sample Run of the Transposition Cipher Tester Program 115 |
|||
| Importing the Modules 116 |
|||
| Creating Pseudorandom Numbers 116 |
|||
| Creating a Random String 118 |
|||
| Duplicating a String a Random Number of Times 118 |
|||
| List Variables Use References 119 |
|||
| Passing References 121 |
|||
| Using copy.deepcopy() to Duplicate a List 122 |
|||
| The random.shuffle() Function 122 |
|||
| Randomly Scrambling a String 123 |
|||
| Testing Each Message 123 |
|||
| Checking Whether the Cipher Worked and Ending the Program 124 |
|||
| Calling the main() Function 124 |
|||
| Testing the Test Program 125 |
|||
| Summary 125 |
|||
| Practice Questions 126 |
|||
| 10 | |||
| ENCRYPTING AND DECRYPTING FILES 127 |
|||
| Plain Text Files 128 |
|||
| Source Code for the Transposition File Cipher Program 128 |
|||
| Sample Run of the Transposition File Cipher Program 130 |
|||
| Working with Files 130 |
|||
| Opening Files 131 |
|||
| Writing to and Closing Files 131 |
|||
| Reading from a File 132 |
|||
| Setting Up the main() Function 132 |
|||
| Checking Whether a File Exists 133 |
|||
| The os.path.exists() Function 133 |
|||
| Checking Whether the Input File Exists with the os.path.exists() Function 134 |
|||
| Using String Methods to Make User Input More Flexible 134 |
|||
| The upper(), lower(), and title() String Methods 134 |
|||
| The startswith() and endswith() String Methods 135 |
|||
| Using These String Methods in the Program 135 |
|||
| Reading the Input File | 136 | ||
| Measuring the Time It Took to Encrypt or Decrypt | 136 | ||
| The time Module and time.time() Function | 136 | ||
| Using the time.time() Function in the Program | 137 | ||
| Writing the Output File | 137 | ||
| Calling the main() Function | 138 | ||
| Summary | 138 | ||
| Practice Questions | 139 | ||
| 11 | |||
| DETECTING ENGLISH PROGRAMMATICALLY | |||
| How Can a Computer Understand English? | 142 | ||
| Source Code for the Detect English Module | 143 | ||
| Sample Run of the Detect English Module | 145 | ||
| Instructions and Setting Up Constants | 145 | ||
| The Dictionary Data Type | 146 | ||
| The Difference Between Dictionaries and Lists | 147 | ||
| Adding or Changing Items in a Dictionary | 147 | ||
| Using the len() Function with Dictionaries | 148 | ||
| Using the in Operator with Dictionaries | 148 | ||
| Finding Items Is Faster with Dictionaries than with Lists | 149 | ||
| Using for Loops with Dictionaries | 149 | ||
| Implementing the Dictionary File | 150 | ||
| The split() Method | 150 | ||
| Splitting the Dictionary File into Individual Words | 151 | ||
| Returning the Dictionary Data | 151 | ||
| Counting the Number of English Words in message | 152 | ||
| Divide-by-Zero Errors | 152 | ||
| Counting the English Word Matches | 153 | ||
| The float(), int(), and str() Functions and Integer Division | 154 | ||
| Finding the Ratio of English Words in the Message | 154 | ||
| Removing Non-Letter Characters | 155 | ||
| The append() List Method | 155 | ||
| Creating a String of Letters | 156 | ||
| Detecting English Words | 156 | ||
| Using Default Arguments | 157 | ||
| Calculating Percentages | 157 | ||
| Summary | 159 | ||
| Practice Questions | 160 | ||
| 12 | |||
| HACKING THE TRANSPOSITION CIPHER | |||
| Source Code of the Transposition Cipher Hacker Program | 162 | ||
| Sample Run of the Transposition Cipher Hacker Program | 163 | ||
| Importing the Modules | 164 | ||
| Multiline Strings with Triple Quotes | 164 | ||
| Displaying the Results of Hacking the Message | 165 | ||
| Getting the Hacked Message | 166 | ||
| The strip() String Method | 167 | ||
| Applying the strip() String Method | 168 | ||
| Failing to Hack the Message | 168 | ||
| Calling the main() Function | 169 | ||
| Summary | 169 | ||
| Practice Questions | 169 | ||
| 13 | 171 | ||
| A MODULAR ARITHMETIC MODULE FOR THE AFFINE CIPHER | |||
| Modular Arithmetic. | 172 | ||
| The Modulo Operator. | 173 | ||
| Finding Factors to Calculate the Greatest Common Divisor | 173 | ||
| Multiple Assignment | 175 | ||
| Euclid’s Algorithm for Finding the GCD. | 176 | ||
| Understanding How the Multiplicative and Affine Ciphers Work | 177 | ||
| Choosing Valid Multiplicative Keys | 178 | ||
| Encrypting with the Affine Cipher | 179 | ||
| Decrypting with the Affine Cipher | 179 | ||
| Finding Modular Inverses. | 181 | ||
| The Integer Division Operator. | 181 | ||
| Source Code for the Cryptomath Module | 182 | ||
| Summary | 183 | ||
| Practice Questions | 183 | ||
| 14 | 185 | ||
| PROGRAMMING THE AFFINE CIPHER | |||
| Source Code for the Affine Cipher Program. | 186 | ||
| Sample Run of the Affine Cipher Program | 188 | ||
| Setting Up Modules, Constants, and the main() Function | 188 | ||
| Calculating and Validating the Keys | 189 | ||
| The Tuple Data Type | 190 | ||
| Checking for Weak Keys | 190 | ||
| How Many Keys Can the Affine Cipher Have? | 191 | ||
| Writing the Encryption Function | 193 | ||
| Writing the Decryption Function | 194 | ||
| Generating Random Keys | 195 | ||
| Calling the main() Function | 196 | ||
| Summary | 196 | ||
| Practice Questions | 196 | ||
| 15 | 197 | ||
| HACKING THE AFFINE CIPHER | |||
| Source Code for the Affine Cipher Hacker Program | 198 | ||
| Sample Run of the Affine Cipher Hacker Program | 199 | ||
| Setting Up Modules, Constants, and the main() Function | 200 | ||
| The Affine Cipher Hacking Function | 201 | ||
| The Exponent Operator | 201 | ||
| Calculating the Total Number of Possible Keys | 201 | ||
| The continue Statement | 202 | ||
| Using continue to Skip Code | 203 | ||
| Calling the main() Function | 204 | ||
| Summary | 205 | ||
| Practice Questions | 16 | 205 | |
| Programming the Simple Substitution Cipher | 207 | ||
| How the Simple Substitution Cipher Works | 208 | ||
| Source Code for the Simple Substitution Cipher Program | 209 | ||
| Sample Run of the Simple Substitution Cipher Program | 210 | ||
| Setting Up Modules, Constants, and the main() Function | 211 | ||
| The sort() List Method | 212 | ||
| Wrapper Functions | 213 | ||
| The translateMessage() Function | 215 | ||
| The isupper() and islower() String Methods | 216 | ||
| Preserving Cases with isupper() | 217 | ||
| Generating a Random Key | 218 | ||
| Calling the main() Function | 219 | ||
| Summary | 219 | ||
| Practice Questions | 219 | ||
| 17 | |||
| Hacking the Simple Substitution Cipher | 221 | ||
| Using Word Patterns to Decrypt | 222 | ||
| Finding Word Patterns | 222 | ||
| Finding Potential Decryption Letters | 223 | ||
| Overview of the Hacking Process | 225 | ||
| The Word Pattern Modules | 225 | ||
| Source Code for the Simple Substitution Hacking Program | 226 | ||
| Sample Run of the Simple Substitution Hacking Program | 229 | ||
| Setting Up Modules and Constants | 230 | ||
| Finding Characters with Regular Expressions | 230 | ||
| Setting Up the main() Function | 231 | ||
| Displaying Hacking Results to the User | 232 | ||
| Creating a Cipherletter Mapping | 232 | ||
| Creating a Blank Mapping | 232 | ||
| Adding Letters to a Mapping | 233 | ||
| Intersecting Two Mappings | 234 | ||
| How the Letter-Mapping Helper Functions Work | 235 | ||
| Identifying Solved Letters in Mappings | 238 | ||
| Testing the removeSolvedLetterFromMapping() Function | 240 | ||
| The hackSimpleSub() Function | 241 | ||
| The replace() String Method | 243 | ||
| Decrypting the Message | 243 | ||
| Decrypting in the Interactive Shell | 244 | ||
| Calling the main() Function | 245 | ||
| Summary | 246 | ||
| Practice Questions | 246 | ||
| 18 | |||
| Programming the Vigenère Cipher | 247 | ||
| Using Multiple Letter Keys in the Vigenère Cipher | 248 | ||
| Longer Vigenère Keys Are More Secure | 249 | ||
| Choosing a Key That Prevents Dictionary Attacks | 250 | ||
| Source Code for the Vigenère Cipher Program | 251 | ||
| Sample Run of the Vigenère Cipher Program | 252 |
{11}————————————————
{12}————————————————
{13}————————————————
{14}————————————————
{15}————————————————
{16}————————————————
{17}————————————————
| Setting Up Modules, Constants, and the main() Function | 252 |
|---|---|
| Building Strings with the List-Append-Join Process | 253 |
| Encrypting and Decrypting the Message | 255 |
| Calling the main() Function | 257 |
| Summary | 257 |
| Practice Questions | 258 |
| 19 FREQUENCY ANALYSIS | 259 |
| Analyzing the Frequency of Letters in Text | 260 |
| Matching Letter Frequencies | 262 |
| Calculating the Frequency Match Score for the Simple Substitution Cipher | 262 |
| Calculating the Frequency Match Score for the Transposition Cipher | 263 |
| Using Frequency Analysis on the Vigenère Cipher | 264 |
| Source Code for Matching Letter Frequencies | 265 |
| Storing the Letters in ETAOIN Order | 266 |
| Counting the Letters in a Message | 267 |
| Getting the First Member of a Tuple | 268 |
| Ordering the Letters in the Message by Frequency | 268 |
| Counting the Letters with getLetterCount() | 269 |
| Creating a Dictionary of Frequency Counts and Letter Lists | 269 |
| Sorting the Letter Lists in Reverse ETAOIN Order | 270 |
| Sorting the Dictionary Lists by Frequency | 274 |
| Creating a List of the Sorted Letters | 276 |
| Calculating the Frequency Match Score of the Message | 276 |
| Summary | 277 |
| Practice Questions | 278 |
| 20 HACKING THE VIGENÈRE CIPHER | 279 |
| Using a Dictionary Attack to Brute-Force the Vigenère Cipher | 280 |
| Source Code for the Vigenère Dictionary Hacker Program | 280 |
| Sample Run of the Vigenère Dictionary Hacker Program | 281 |
| About the Vigenère Dictionary Hacker Program | 281 |
| Using Kasiski Examination to Find the Key’s Length | 282 |
| Finding Repeated Sequences | 282 |
| Getting Factors of Spacings | 283 |
| Getting Every Nth Letters from a String | 284 |
| Using Frequency Analysis to Break Each Subkey | 285 |
| Brute-Forcing Through the Possible Keys | 287 |
| Source Code for the Vigenère Hacking Program | 287 |
| Sample Run of the Vigenère Hacking Program | 293 |
| Importing Modules and Setting Up the main() Function | 294 |
| Finding Repeated Sequences | 294 |
| Calculating the Factors of the Spacings | 297 |
| Removing Duplicates with the set() Function | 298 |
| Removing Duplicate Factors and Sorting the List | 298 |
| Finding the Most Common Factors | 298 |
| Finding the Most Likely Key Lengths | 300 |
| The extend() List Method | 301 |
| Extending the repeatedSeqSpacings Dictionary | 301 |
| Getting the Factors from factorsByCount | 302 |
| Getting Letters Encrypted with the Same Subkey | 302 |
| Attempting Decryption with a Likely Key Length | 303 |
| The end Keyword Argument for print() | 306 |
| Running the Program in Silent Mode or Printing Information to the User | 306 |
| Finding Possible Combinations of Subkeys | 306 |
| Printing the Decrypted Text with the Correct Casing | 310 |
| Returning the Hacked Message | 311 |
| Breaking Out of the Loop When a Potential Key Is Found | 311 |
| Brute-Forcing All Other Key Lengths | 312 |
| Calling the main() Function | 313 |
| Modifying the Constants of the Hacking Program | 313 |
| Summary | 314 |
| Practice Questions | 314 |
| 21 | 315 |
| THE ONE-TIME PAD CIPHER | |
| The Unbreakable One-Time Pad Cipher | 316 |
| Making Key Length Equal Message Length | 316 |
| Making the Key Truly Random | 318 |
| Avoiding the Two-Time Pad | 319 |
| Why the Two-Time Pad Is the Vigenère Cipher | 319 |
| Summary | 320 |
| Practice Questions | 320 |
| 22 | 321 |
| FINDING AND GENERATING PRIME NUMBERS | |
| What Is a Prime Number? | 322 |
| Source Code for the Prime Numbers Module | 324 |
| Sample Run of the Prime Numbers Module | 326 |
| How the Trial Division Algorithm Works | 326 |
| Implementing the Trial Division Algorithm Test | 328 |
| The Sieve of Eratosthenes | 328 |
| Generating Prime Numbers with the Sieve of Eratosthenes | 330 |
| The Rabin-Miller Primality Algorithm | 331 |
| Finding Large Prime Numbers | 332 |
| Generating Large Prime Numbers | 333 |
| Summary | 334 |
| Practice Questions | 334 |
| 23 | 335 |
| GENERATING KEYS FOR THE PUBLIC KEY CIPHER | |
| Generating Keys with the generateKey() Function | 343 |
| Calculating an e Value | 344 |
| Calculating a d Value | 344 |
| Returning the Keys | 345 |
| Creating Key Files with the makeKeyFiles() Function | 345 |
| Calling the main() Function | 347 |
| Hybrid Cryptosystems | 347 |
| Summary | 348 |
| Practice Questions | 348 |
| 24 | |
| PROGRAMMING THE PUBLIC KEY CIPHER |
349 |
| How the Public Key Cipher Works | 350 |
| Creating Blocks | 350 |
| Converting a String into a Block | 350 |
| The Mathematics of Public Key Cipher Encryption and Decryption | 353 |
| Converting a Block to a String | 354 |
| Why We Can’t Hack the Public Key Cipher | 355 |
| Source Code for the Public Key Cipher Program | 357 |
| Sample Run of the Public Key Cipher Program | 360 |
| Setting Up the Program | 362 |
| How the Program Determines Whether to Encrypt or Decrypt | 362 |
| Converting Strings to Blocks with getBlocksFromText() | 363 |
| The min() and max() Functions | 364 |
| Storing Blocks in blockInt | 364 |
| Using getTextFromBlocks() to Decrypt | 366 |
| Using the insert() List Method | 367 |
| Merging the Message List into One String | 367 |
| Writing the encryptMessage() Function | 367 |
| Writing the decryptMessage() Function | 368 |
| Reading in the Public and Private Keys from Their Key Files | 369 |
| Writing the Encryption to a File | 369 |
| Decrypting from a File | 371 |
| Calling the main() Function | 373 |
| Summary | 373 |
| APPENDIX | |
| DEBUGGING PYTHON CODE | 375 |
| How the Debugger Works | 375 |
| Debugging the Reverse Cipher Program | 377 |
| Setting Breakpoints | 379 |
| Summary | 380 |
| INDEX | 381 |
{18}————————————————
{19}————————————————
{20}————————————————
Ac knowledgments
This book would not have been possible without the exceptional work of the No Starch Press team. Thanks to my publisher, Bill Pollock; thanks to my editors, Riley Hoffman, Jan Cash, Annie Choi, Anne Marie Walker, and Laurel Chun, for their incredible help throughout the process; thanks to my technical editor, Ari Lacenski, for her help in this edition and back when it was just a stack of printouts I showed her at Shotwell’s; thanks to JP Aumasson for lending his expertise in the public key chapters; and thanks to Josh Ellingson for a great cover.
{21}————————————————
{22}————————————————
I ntrodu c tion
“I couldn’t help but overhear, probably because I was eavesdropping.” —Anonymous
If you could travel back to the early 1990s with this book, the contents of Chapter 23 that implement part of the RSA cipher would be illegal to export out of the United States.
Because messages encrypted with RSA are impossible to hack, the export of encryption software like RSA
was deemed a matter of national security and required State Department approval. In fact, strong cryptography was regulated at the same level as tanks, missiles, and flamethrowers.
In 1990, Daniel J. Bernstein, a student at the University of California, Berkeley, wanted to publish an academic paper that featured source code of his Snuffle encryption system. The US government informed him that he would need to become a licensed arms dealer before he could post his source code on the internet. The government also told him that it would deny him an export license if he applied for one because his technology was too secure.
{23}————————————————
The Electronic Frontier Foundation, a young digital civil liberties organization, represented Bernstein in Bernstein v. United States. For the first time ever, the courts ruled that written software code was speech protected by the First Amendment and that the export control laws on encryption violated Bernstein’s First Amendment rights.
Now, strong cryptography is at the foundation of a large part of the global economy, safeguarding businesses and e-commerce sites used by millions of internet shoppers every day. The intelligence community’s predictions that encryption software would become a grave national security threat were unfounded.
But as recently as the 1990s, spreading this knowledge freely (as this book does) would have landed you in prison for arms trafficking. For a more detailed history of the legal battle for freedom of cryptography, read Steven Levy’s book Crypto: How the Code Rebels Beat the Government, Saving Privacy in the Digital Age (Penguin, 2001).
Who Should Read This Book?
Many books teach beginners how to write secret messages using ciphers. A couple of books teach beginners how to hack ciphers. But no books teach beginners how to program computers to hack ciphers. This book fills that gap.
This book is for those who are curious about encryption, hacking, or cryptography. The ciphers in this book (except for the public key cipher in Chapters 23 and 24) are all centuries old, but any laptop has the computational power to hack them. No modern organizations or individuals use these ciphers anymore, but by learning them, you’ll learn the foundations cryptography was built on and how hackers can break weak encryption.
NOTE
N ote The ciphers you’ll learn in this book are fun to play with, but they don’t provide true security. Don’t use any of the encryption programs in this book to secure your actual files. As a general rule, you shouldn’t trust the ciphers that you create. Real-world ciphers are subject to years of analysis by professional cryptographers before being put into use.
This book is also for people who have never programmed before. It teaches basic programming concepts using the Python programming language, which is one of the best languages for beginners. It has a gentle learning curve that novices of all ages can master, yet it’s also a powerful language used by professional software developers. Python runs on Windows, macOS, Linux, and even the Raspberry Pi, and it’s free to download and use. (See “Downloading and Installing Python” on page xxv for instructions.)
In this book, I’ll use the term hacker often. The word has two definitions. A hacker can be a person who studies a system (such as the rules of a cipher or a piece of software) to understand it so well that they’re not limited by that system’s original rules and can modify it in creative ways.
{24}————————————————
A hacker can also be a criminal who breaks into computer systems, violates people’s privacy, and causes damage. This book uses the term in the first sense. Hackers are cool. Criminals are just people who think they’re being clever by breaking stuff.
What’s in This Book?
The first few chapters introduce basic Python and cryptography concepts. Thereafter, chapters generally alternate between explaining a program for a cipher and then explaining a program that hacks that cipher. Each chapter also includes practice questions to help you review what you’ve learned.
- • Chapter 1: Making Paper Cryptography Tools covers some simple paper tools, showing how encryption was done before computers.
- • Chapter 2: Programming in the Interactive Shell explains how to use Python’s interactive shell to play around with code one line at a time.
- • Chapter 3: Strings and Writing Programs covers writing full programs and introduces the string data type used in all programs in this book.
- • Chapter 4: The Reverse Cipher explains how to write a simple program for your first cipher.
- • Chapter 5: The Caesar Cipher covers a basic cipher first invented thousands of years ago.
- • Chapter 6: Hacking the Caesar Cipher with Brute-Force explains the brute-force hacking technique and how to use it to decrypt messages without the encryption key.
- • Chapter 7: Encrypting with the Transposition Cipher introduces the transposition cipher and a program that encrypts messages with it.
- • Chapter 8: Decrypting with the Transposition Cipher covers the second half of the transposition cipher: being able to decrypt messages with a key.
- • Chapter 9: Programming a Program to Test Your Program introduces the programming technique of testing programs with other programs.
- • Chapter 10: Encrypting and Decrypting Files explains how to write programs that read files from and write files to the hard drive.
- • Chapter 11: Detecting English Programmatically describes how to make the computer detect English sentences.
- • Chapter 12: Hacking the Transposition Cipher combines the concepts from previous chapters to hack the transposition cipher.
- • Chapter 13: A Modular Arithmetic Module for the Affine Cipher explains the math concepts behind the affine cipher.
- • Chapter 14: Programming the Affine Cipher covers writing an affine cipher encryption program.
- • Chapter 15: Hacking the Affine Cipher explains how to write a program to hack the affine cipher.
{25}————————————————
- • Chapter 16: Programming the Simple Substitution Cipher covers writing a simple substitution cipher encryption program.
- • Chapter 17: Hacking the Simple Substitution Cipher explains how to write a program to hack the simple substitution cipher.
- • Chapter 18: Programming the Vigenère Cipher explains a program for the Vigenère cipher, a more complex substitution cipher.
- • Chapter 19: Frequency Analysis explores the structure of English words and how to use it to hack the Vigenère cipher.
- • Chapter 20: Hacking the Vigenère Cipher covers a program for hacking the Vigenère cipher.
- • Chapter 21: The One-Time Pad Cipher explains the one-time pad cipher and why it’s mathematically impossible to hack.
- • Chapter 22: Finding and Generating Prime Numbers covers how to write a program that quickly determines whether a number is prime.
- • Chapter 23: Generating Keys for the Public Key Cipher describes public key cryptography and how to write a program that generates public and private keys.
- • Chapter 24: Programming the Public Key Cipher explains how to write a program for a public key cipher, which you can’t hack using a mere laptop.
- • The appendix, Debugging Python Code, shows you how to use IDLE’s debugger to find and fix bugs in your programs.