If you've ever dabbled with cryptography you've probably done the basics - something like a Caesar cipher - where you increment the letters of the alphabet by some value. We won't spend too much time doing that, nor will we dive into the various encryption algorithms out there. Instead, we'll come to understand that protecting your key is the name of the game when it comes to secure cryptography.
To that end, we'll create a one-time pad to see how disposable keys can help accomplish this. We'll then create our very own Diffie-Hellman key exchange to see how this groundbreaking algorithm changed cryptography forever.
The Code
Here's the code used in the video. There's always room for improvement - feel free to suggest! Your comments, as always, are welcome and you can drop me an email or, when the code is published, feel free to leave an issue on GitHub.
This is our alphabet for the one-time pad:
class Alphabet { constructor(){ this.chars = [ "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", " ", "?", "!" ]; } getOffsetChar({char, offsetChar, encrypting=true}){ const charPosition = this.chars.indexOf(char); const keyPosition = this.chars.indexOf(offsetChar); const offsetPosition = encrypting ? (charPosition + keyPosition) : (charPosition - keyPosition); let idx = (offsetPosition) % this.chars.length; if(offsetPosition < 0 ) idx = this.chars.length - -idx; return this.chars[idx] }}module.exports = new Alphabet();
Here's super-simple Caesar cipher:
const offsetChars = (text, offset=1) => { const out = []; for(let i=0; i < text.length; i++){ const offsetIndex = text.charCodeAt(i) + offset; out.push(String.fromCharCode(offsetIndex)) } return out.join("");}class Caesar { constructor(offset=5){ this.offset=offset; } encrypt(plainText){ return offsetChars(plainText, this.offset); } decrypt(cipherText){ return offsetChars(cipherText, -this.offset); }}module.exports = Caesar;
The famous one-time pad that is theoretically unbreakable:
const alphabet = require("./alphabet");const pads = require("../data/pads");const offsets = function(text, pad, encrypting=true){ const out = [], chars=text.split(""), keys=pad.split(""); for(let i=0; i < text.length; i++){ const offsetChar = alphabet.getOffsetChar({char: chars[i], offsetChar: keys[i], encrypting: encrypting}) out.push(offsetChar) } return out.join("");}class OneTimePad{ constructor(padNumber){ this.pad = pads[padNumber]; this.alphabetLength = alphabet.length; } encrypt(plainText){ return offsets(plainText,this.pad,true); } decrypt(cipherText){ return offsets(cipherText,this.pad,false); }}module.exports = OneTimePad;
Finally, the Diffie-Hellman key exchange:
class DiffieHellman{ constructor({generator, secret, modulus}={}){ this.generator = generator; this.secret = secret; this.modulus = modulus; this.publicKey = Math.pow(this.generator,this.secret) % this.modulus; } encryptionKey(receiverPublicKey){ return Math.pow(receiverPublicKey, this.secret) % this.modulus; }}module.exports = DiffieHellman;
I'll have this code up on GitHub when the videos are completed.