Skip to content

Commit

Permalink
Add compression
Browse files Browse the repository at this point in the history
  • Loading branch information
dscheg committed Feb 27, 2024
1 parent 169a8f2 commit 736d22c
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 30 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# AES Crypto Playground  [![License](https://img.shields.io/github/license/dscheg/aes.svg)](https://raw.githubusercontent.com/dscheg/aes/main/LICENSE)

Play around with AES encryption and decryption to learn about the different complexities of symmetric encryption implementations. This page uses only client-side cryptography and does not send data anywhere. But still, do not play with sensitive data. The playground provided "AS IS" without any warranties
Play around with AES encryption and decryption to learn about the different complexities of symmetric encryption implementations. This page uses only client-side cryptography and does not send data anywhere. But still, do not play with sensitive data. The playground provided "AS IS" without any warranties.

Try attacks:
* Bit Flipping
* Padding Oracle
* Compression Oracle
* ...

https://dscheg.github.io/aes
20 changes: 11 additions & 9 deletions aes.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ input {

#dir {
position: absolute;
bottom: 0;
right: 0;
bottom: 4px;
right: 4px;
font-size: 50%;
}

Expand Down Expand Up @@ -87,10 +87,7 @@ input {
background-image: url("modes/CFB_encryption.min.svg");
}

.xed.cipher button {
display: none;
}
.xed.decrypt button {
.xed.decrypt .xed-load {
display: none;
}

Expand All @@ -100,16 +97,21 @@ input {
.xor:has(textarea:focus) {
opacity: 1;
}
.grayed {
.grayed, .grayed textarea {
color: #777;
}

#result {
white-space: pre;
font: min(1.8vw, 1.8vh)/1em 'Julia';
width: min(80vw, 78vh);
resize: none;
border: 1px dotted #bbb;
}
#result:focus {
outline: transparent !important;
}
.night #result {
filter: invert(1) brightness(0.5);
filter: hue-rotate(180deg);
}
#result.error {
color: red;
Expand Down
45 changes: 36 additions & 9 deletions aes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ const $modeimg = $("#mode-img");
const $padding = $("#padding");
const $keysize = $("#keysize");
const $blocksize = $("#blocksize");
const $compress = $("#compress");

const $plain = $(".xed.plain");
const $deflate = $(".xed.deflate");
const $cipher = $(".xed.cipher");
const $decrypt = $(".xed.decrypt");
const $xor = $(".xed.xor");
Expand All @@ -23,7 +25,7 @@ const update = () => $plain.dispatchEvent(new Event("change"));
const setResult = (isOk, text) => {
$result.classList[isOk ? 'add' : 'remove']('success');
$result.classList[isOk ? 'remove' : 'add']('error');
$result.textContent = text;
$result.value = text;
};

$dir.value = localStorage.getItem("dir") || $dir[0].value;
Expand Down Expand Up @@ -71,6 +73,15 @@ $key.oninput = e => {
};
$key.oninput();

$compress.value = localStorage.getItem("compression") || "";
$compress.oninput = e => {
localStorage.setItem("compression", $compress.value);
const hide = $compress.value.length === 0;
$deflate.previousElementSibling.hidden = hide;
$deflate.hidden = hide;
update();
};

//const importKey = () => crypto.subtle.importKey("raw", fromHex($key.value), {name: "AES-CBC"}, true, ["encrypt", "decrypt"]);

const getCryptoParams = () => Object({
Expand All @@ -79,14 +90,26 @@ const getCryptoParams = () => Object({
padding: CryptoJS.pad[$padding.value]
});

const compress = (data, mode) => stream = mode != 0 && $compress.value != ""
? new Response(new Blob([data]).stream().pipeThrough(mode > 0 ? new CompressionStream($compress.value) : new DecompressionStream($compress.value)))
.arrayBuffer().then(buf => new Uint8Array(buf))
: new Promise((resolve, _) => resolve(data));

$plain.addEventListener("change", e => {
const plain = $plain.getDataHex();
const plain = $plain.getData();
compress(plain, 1).then(data => {
$deflate.setData(data);
localStorage.setItem("hex", toHex(plain));
}).catch(e => setResult(false, e));
});

$deflate.addEventListener("change", e => {
const compressed = $deflate.getDataHex();
const enc = CryptoJS.AES.encrypt(
CryptoJS.enc.Hex.parse(plain),
CryptoJS.enc.Hex.parse(compressed),
CryptoJS.enc.Hex.parse($key.value),
getCryptoParams());
$cipher.setDataHex(enc.ciphertext.toString(CryptoJS.enc.Hex));
localStorage.setItem("hex", plain);

/*importKey().then(key => crypto.subtle.encrypt({name: "AES-" + $mode.value, iv: fromHex($iv.value)}, key, $plain.getData()).then(cipher => {
$cipher.setData(new Uint8Array(cipher));
Expand All @@ -95,20 +118,24 @@ $plain.addEventListener("change", e => {

$cipher.addEventListener("change", e => {
try {
const cipher = $cipher.getDataHex();
const decrypt = CryptoJS.AES.decrypt(
CryptoJS.lib.CipherParams.create({ciphertext: CryptoJS.enc.Hex.parse($cipher.getDataHex())}),
CryptoJS.lib.CipherParams.create({ciphertext: CryptoJS.enc.Hex.parse(cipher)}),
CryptoJS.enc.Hex.parse($key.value),
getCryptoParams());

const hex = decrypt.toString(CryptoJS.enc.Hex);
if($plain.getDataHex().length > 0 && hex.length === 0) {
$decrypt.setDataHex('');
$decrypt.classList.add('grayed');
throw new Error("Decryption failed");
}

$decrypt.setDataHex(hex);
const text = new TextDecoder().decode(fromHex(hex));
setResult(true, JSON.stringify(JSON.parse(text.replace(/[\x00-\x1f]/ig, '\uFFFD')), null, 4));
compress(fromHex(hex), -1).then(data => {
$decrypt.setData(data);
$decrypt.classList.remove('grayed');
const text = new TextDecoder().decode(data);
setResult(true, JSON.stringify(JSON.parse(text.replace(/[\x00-\x1f]/ig, '\uFFFD')), null, 4));
}).catch(e => setResult(false, e));
} catch(e) {
setResult(false, e);
}
Expand Down
Binary file added favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions hex.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,11 @@
background-color: #fff5d9;
box-shadow: 0 0 10px #39e;
}

.xed-top, .xed-left, .xed-size {
color: #aaa;
}

.xed-size {
text-align: right;
}
7 changes: 6 additions & 1 deletion hex.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ $$(".xed").forEach($xed => {
$a.click();
};

const $size = $(".xed-size", $xed);
const $left = $(".xed-left", $xed);
const $right = $(".xed-right", $xed);
$right.value = '';

$right.oninput = function() {
const pos = $right.value
Expand Down Expand Up @@ -81,11 +83,14 @@ $$(".xed").forEach($xed => {
.map(i => (1E7 + (16 * i).toString(16)).slice(-8))
.join('\n');

$right.value = range(Math.floor(($hex.value.length + 1) / 3))
const len = Math.floor(($hex.value.length + 1) / 3);
$right.value = range(len)
.map(i => parseInt($hex.value.substr(i * 3, 2), 16))
.map(c => String.fromCodePoint(c + (0x20 <= c && c < 0x7F ? 0 : 0xF000)))
.join('').replace(/(.{16})(?=.)/g, '$1\n');

$size.textContent = 'size=' + len;

const newpos = pos > 0 && [' ', '\n'].includes($hex.value[pos - 1]) ? pos - 1 : pos;
$hex.setSelectionRange(newpos, newpos);

Expand Down
44 changes: 34 additions & 10 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<meta name="viewport" content="viewport-fit=cover,width=device-width,initial-scale=1.0,user-scalable=no"/>
<link href="hex.css" rel="stylesheet" type="text/css"/>
<link href="aes.css" rel="stylesheet" type="text/css"/>
<link rel="icon" type="image/png" href="favicon.png"/>
</head>
<body>

Expand All @@ -26,7 +27,7 @@ <h1>AES Crypto Playground</h1>
<option value="OFB">OFB</option>
<option value="CFB">CFB</option>
</select></td>
<td id="mode-img" rowspan=6><select id="dir">
<td id="mode-img" rowspan=7><select id="dir">
<option value="Decryption">Decryption</option>
<option value="Encryption">Encryption</option>
</td></tr>
Expand All @@ -42,6 +43,12 @@ <h1>AES Crypto Playground</h1>
<tr><td>Key</td><td><input type="text" id="key" maxlength=64 pattern="[0-9a-fA-F]*"/></td></tr>
<tr><td>Key&nbsp;Size</td><td><input type="text" id="keysize" disabled value="128 bit"/></td></tr>
<tr><td>Block&nbsp;Size</td><td><input type="text" id="blocksize" disabled value="128 bit"/></td></tr>
<tr><td>Compression</td><td><select id="compress">
<option value="">No Compression</option>
<option value="deflate-raw">Deflate Raw</option>
<option value="deflate">Deflate</option>
<option value="gzip">Gzip</option>
</select></td></tr>
</table>

<h3>Plain</h3>
Expand All @@ -52,7 +59,7 @@ <h3>Plain</h3>
<button class="xed-load" title="Load">📂&#xFE0E;</button>
<button class="xed-save" title="Save">💾&#xFE0E;</button>
</td>
<td class="xed-top"></td>
<td class="xed-top"></td><td class="xed-size"></td>
</tr>
<tr>
<td><textarea class="xed-left" cols=8 wrap="off" spellcheck="false" readonly>00000000</textarea></td>
Expand All @@ -61,6 +68,23 @@ <h3>Plain</h3>
</tr>
</table>

<h3 hidden>Compressed</h3>
<table class="xed deflate" hidden>
<tr>
<td>
<input type="file" class="xed-load-file" hidden/>
<button class="xed-load" title="Load">📂&#xFE0E;</button>
<button class="xed-save" title="Save">💾&#xFE0E;</button>
</td>
<td class="xed-top"></td><td class="xed-size"></td>
</tr>
<tr>
<td><textarea class="xed-left" cols=8 wrap="off" spellcheck="false" readonly>00000000</textarea></td>
<td><textarea class="xed-hex" cols=47 wrap="off" spellcheck="false"></textarea>
<td><textarea class="xed-right" cols=16 wrap="off" spellcheck="false"></textarea></td>
</tr>
</table>

<h3>Cipher</h3>
<table class="xed cipher">
<tr>
Expand All @@ -69,12 +93,12 @@ <h3>Cipher</h3>
<button class="xed-load" title="Load">📂&#xFE0E;</button>
<button class="xed-save" title="Save">💾&#xFE0E;</button>
</td>
<td class="xed-top"></td>
<td class="xed-top"></td><td class="xed-size"></td>
</tr>
<tr>
<td><textarea class="xed-left" cols=8 wrap="off" spellcheck="false" readonly>00000000</textarea></td>
<td><textarea class="xed-hex" cols=47 wrap="off" spellcheck="false"></textarea>
<td><textarea class="xed-right" cols=16 wrap="off" autofocus spellcheck="false"></textarea></td>
<td><textarea class="xed-right" cols=16 wrap="off" spellcheck="false"></textarea></td>
</tr>
</table>

Expand All @@ -86,12 +110,12 @@ <h3>Decrypted</h3>
<button class="xed-load" title="Load">📂&#xFE0E;</button>
<button class="xed-save" title="Save">💾&#xFE0E;</button>
</td>
<td class="xed-top"></td>
<td class="xed-top"></td><td class="xed-size"></td>
</tr>
<tr>
<td><textarea class="xed-left" cols=8 wrap="off" spellcheck="false" readonly>00000000</textarea></td>
<td><textarea class="xed-hex" cols=47 wrap="off" spellcheck="false" readonly disabled></textarea>
<td><textarea class="xed-right" cols=16 wrap="off" autofocus spellcheck="false" readonly disabled></textarea></td>
<td><textarea class="xed-hex" cols=47 wrap="off" spellcheck="false" readonly></textarea>
<td><textarea class="xed-right" cols=16 wrap="off" spellcheck="false" readonly></textarea></td>
</tr>
</table>

Expand All @@ -103,17 +127,17 @@ <h3 class="grayed">XOR Lines</h3>
<button class="xed-load" title="Load">📂&#xFE0E;</button>
<button class="xed-save" title="Save">💾&#xFE0E;</button>
</td>
<td class="xed-top"></td>
<td class="xed-top"></td><td class="xed-size"></td>
</tr>
<tr>
<td><textarea class="xed-left" cols=8 wrap="off" spellcheck="false" readonly>00000000</textarea></td>
<td><textarea class="xed-hex" cols=47 wrap="off" spellcheck="false"></textarea>
<td><textarea class="xed-right" cols=16 wrap="off" autofocus spellcheck="false"></textarea></td>
<td><textarea class="xed-right" cols=16 wrap="off" spellcheck="false"></textarea></td>
</tr>
</table>

<h3>Result</h3>
<div id="result">n/a</div>
<textarea id="result" rows=5 spellcheck="false" readonly>n/a</textarea>

<div class="copy"><a href="https://github.com/dscheg/aes">github.com/dscheg/aes</a></div>

Expand Down

0 comments on commit 736d22c

Please sign in to comment.