Public
Edited
Jan 16, 2023
Insert cell
Insert cell
// Encrypt
encryptAes128Ebc = (plaintext, key) => {
const encKey = CryptoJS.enc.Utf8.parse(key);

// The challenge input includes newlines, but we want to ignore them.
// It's a PEM like encoding
//const fixedCipher = cipher.replaceAll("\n", "");

return CryptoJS.enc.Base64.stringify(CryptoJS.AES.encrypt(plaintext, encKey, {mode: CryptoJS.mode.ECB }).ciphertext)//.toString(CryptoJS.enc.Utf8)
}
Insert cell
import {decryptAes128Ebc} from "e06c7d85a5552a65"
Insert cell
ebcTest1 = encryptAes128Ebc("hello hello there", "yellow submarine")
Insert cell
decryptAes128Ebc(ebcTest1, "yellow submarine")
Insert cell
CryptoJS = require('https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js')
Insert cell
import {lib} from "@pcarleton/cryptopals-helpers"
Insert cell
iv = Array(16).fill(0)
Insert cell
pad1 = lib.padBlock(lib.stob("abcdef"), 16)
Insert cell
dePad(pad1)
Insert cell
dePad = (arr, size) => {
const lastIdx = arr.length - 1
const last = arr[lastIdx];

if (last > size || arr.length < size) {
return arr;
}

for (let i = 1; i < last; i += 1) {
if (arr[lastIdx - i] != last) {
return arr;
}
}

// If we've gotten through that, we know we have a padded block, so we can truncate it.
return arr.slice(0, arr.length - last);
}
Insert cell
encrypt1 = encryptAes128Cbc("yellow submarineyellow submarine", iv, "yellow submarine")
Insert cell
new CryptoJS.lib.WordArray.init([1, 2])
Insert cell
encryptAes128Cbc = (plaintext, iv, key) => {
const BLOCK_SIZE = 16;
// first start with IV, XOR it with cipher text
const ptBytes = lib.stob(plaintext)
const encKey = CryptoJS.enc.Utf8.parse(key);

//return encKey;

// Pad it
const padded = lib.padBlock(ptBytes, BLOCK_SIZE);

// Split it into blocks
const blocks = lib.chunkArr(padded, BLOCK_SIZE);

const xorZip = (a1, a2) => {
return a1.map((d, i) => d ^ a2[i]);
};

let lastBlock = iv; // assume iv is arr
let results = [];
for (let i = 0; i < blocks.length; i += 1) {
let prepped = xorZip(blocks[i], lastBlock);
let words = CryptoJS.enc.Base64.parse(lib.tob64(prepped));
//return words;
//let prepped64 = lib.tob64(prepped);

// I'm doing some real janky extra base64ing here
let cipher = CryptoJS.AES.encrypt(words, encKey, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.NoPadding,
});

//return cipher;

let cipherArr = lib.fromb64(CryptoJS.enc.Base64.stringify(cipher.ciphertext));
results.push(cipherArr);
lastBlock = cipherArr;
}
// count IV as "block -1"
// XOR block against block -1, then encrypt it.
// concat the blocks together again
// return base64 encoded

return lib.tob64(results.flat());
}
Insert cell
Insert cell
decryptAes128Cbc = (cipher, iv, key) => {
const BLOCK_SIZE = 16;
// first start with IV, XOR it with cipher text
//const ptBytes = lib.stob(plaintext)
const encKey = CryptoJS.enc.Utf8.parse(key);
// Split it into blocks
const blocks = lib.chunkArr(lib.fromb64(cipher), BLOCK_SIZE);

const xorZip = (a1, a2) => {
return a1.map((d, i) => d ^ a2[i]);
};

let lastBlock = iv; // assume iv is arr
let results = [];
for (let i = 0; i < blocks.length; i += 1) {
//let words = CryptoJS.lib.WordArray.init(blocks[i]);
//return words;
let words = lib.tob64(blocks[i]);
//let prepped64 = lib.tob64(prepped);

// I'm doing some real janky extra base64ing here
let plainText = CryptoJS.AES.decrypt(words, encKey, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });

// this is weird, I don't know what's happening
plainText = new CryptoJS.lib.WordArray.init(plainText.words);

let ptArr = lib.fromb64(CryptoJS.enc.Base64.stringify(plainText));

//return words;
let dexord = xorZip(ptArr, lastBlock);

results.push(dexord);
lastBlock = blocks[i];
}
// count IV as "block -1"
// XOR block against block -1, then encrypt it.
// concat the blocks together again
// return base64 encoded

return lib.tob64(dePad(results.flat(), 16))
}
Insert cell
foo = decryptAes128Cbc(encrypt1, iv, "yellow submarine")
Insert cell
lib.btos(foo)
Insert cell
new CryptoJS.lib.WordArray.init(foo.words)
Insert cell
// Very confusing things are happening on later blocks. For some reason each block of input is converted into 2 blocks of output.
Insert cell
iv2 = Array(16).fill(2)
Insert cell
"hi there, this is longer than 1 block".length
Insert cell
t1 = encryptAes128Cbc("hi there, this is longer than 1 block", iv2, "yellow submarine")
Insert cell
lib.btos(lib.fromb64(decryptAes128Cbc(t1, iv2, "yellow submarine")))
Insert cell

ok1 = {
const key = "yellow submarine";
const encKey = CryptoJS.enc.Utf8.parse(key);

const words = "hi there";
const encWords = CryptoJS.enc.Utf8.parse(words);

//return encWords;
return CryptoJS.AES.encrypt(encWords, encKey, {mode: CryptoJS.mode.ECB }).ciphertext.toString(CryptoJS.enc.Base64)

}
Insert cell
encryptAes128Cbc("hi there", iv, "yellow submarine");
Insert cell
decryptAes128Ebc(ok1, "yellow submarine");
Insert cell

weird = {
const key = "yellow submarine";
const encKey = CryptoJS.enc.Utf8.parse(key);

const words = "hi there my name is paul";
const bs = lib.padBlock(lib.stob(words), 16);
const encWords = CryptoJS.enc.Base64.parse(lib.tob64(bs));
//return encWords;
return CryptoJS.AES.encrypt(encWords, encKey, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding }).ciphertext.toString(CryptoJS.enc.Base64)

}
Insert cell
{
const key = "yellow submarine";
const encKey = CryptoJS.enc.Utf8.parse(key);

return CryptoJS.AES.decrypt(weird, encKey, {mode: CryptoJS.mode.ECB }).toString(CryptoJS.enc.Utf8)
}
Insert cell
test1 = (await FileAttachment("10.txt").text()).replace("\n", "")
Insert cell
lib.btos(lib.fromb64(decryptAes128Cbc(test1, iv, "YELLOW SUBMARINE")))
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more