Last active
December 16, 2022 19:02
-
-
Save msf/5b5f8ea49a18ecfc4917a1aa4081bed3 to your computer and use it in GitHub Desktop.
add back fromHex()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<body> | |
<h2>My Heading</h2> | |
<p>Play around with the code and click on the "Run" button to view the result.</p> | |
<p id="demo"></p> | |
<script> | |
/* chacha20 - 256 bits */ | |
// Written in 2014 by Devi Mandiri. Public domain. | |
// | |
// Implementation derived from chacha-ref.c version 20080118 | |
// See for details: http://cr.yp.to/chacha/chacha-20080128.pdf | |
function U8TO32_LE(x, i) { | |
return x[i] | (x[i+1]<<8) | (x[i+2]<<16) | (x[i+3]<<24); | |
} | |
function U32TO8_LE(x, i, u) { | |
x[i] = u; u >>>= 8; | |
x[i+1] = u; u >>>= 8; | |
x[i+2] = u; u >>>= 8; | |
x[i+3] = u; | |
} | |
function ROTATE(v, c) { | |
return (v << c) | (v >>> (32 - c)); | |
} | |
var Chacha20 = function(key, nonce, counter) { | |
this.input = new Uint32Array(16); | |
// https://tools.ietf.org/html/draft-irtf-cfrg-chacha20-poly1305-01#section-2.3 | |
this.input[0] = 1634760805; | |
this.input[1] = 857760878; | |
this.input[2] = 2036477234; | |
this.input[3] = 1797285236; | |
this.input[4] = U8TO32_LE(key, 0); | |
this.input[5] = U8TO32_LE(key, 4); | |
this.input[6] = U8TO32_LE(key, 8); | |
this.input[7] = U8TO32_LE(key, 12); | |
this.input[8] = U8TO32_LE(key, 16); | |
this.input[9] = U8TO32_LE(key, 20); | |
this.input[10] = U8TO32_LE(key, 24); | |
this.input[11] = U8TO32_LE(key, 28); | |
this.input[12] = counter; | |
this.input[13] = U8TO32_LE(nonce, 0); | |
this.input[14] = U8TO32_LE(nonce, 4); | |
this.input[15] = U8TO32_LE(nonce, 8); | |
}; | |
Chacha20.prototype.quarterRound = function(x, a, b, c, d) { | |
x[a] += x[b]; x[d] = ROTATE(x[d] ^ x[a], 16); | |
x[c] += x[d]; x[b] = ROTATE(x[b] ^ x[c], 12); | |
x[a] += x[b]; x[d] = ROTATE(x[d] ^ x[a], 8); | |
x[c] += x[d]; x[b] = ROTATE(x[b] ^ x[c], 7); | |
}; | |
Chacha20.prototype.encrypt = function(dst, src, len) { | |
var x = new Uint32Array(16); | |
var output = new Uint8Array(64); | |
var i, dpos = 0, spos = 0; | |
while (len > 0 ) { | |
for (i = 16; i--;) x[i] = this.input[i]; | |
for (i = 20; i > 0; i -= 2) { | |
this.quarterRound(x, 0, 4, 8,12); | |
this.quarterRound(x, 1, 5, 9,13); | |
this.quarterRound(x, 2, 6,10,14); | |
this.quarterRound(x, 3, 7,11,15); | |
this.quarterRound(x, 0, 5,10,15); | |
this.quarterRound(x, 1, 6,11,12); | |
this.quarterRound(x, 2, 7, 8,13); | |
this.quarterRound(x, 3, 4, 9,14); | |
} | |
for (i = 16; i--;) x[i] += this.input[i]; | |
for (i = 16; i--;) U32TO8_LE(output, 4*i, x[i]); | |
this.input[12] += 1; | |
if (!this.input[12]) { | |
this.input[13] += 1; | |
} | |
if (len <= 64) { | |
for (i = len; i--;) { | |
dst[i+dpos] = src[i+spos] ^ output[i]; | |
} | |
return; | |
} | |
for (i = 64; i--;) { | |
dst[i+dpos] = src[i+spos] ^ output[i]; | |
} | |
len -= 64; | |
spos += 64; | |
dpos += 64; | |
} | |
}; | |
Chacha20.prototype.keystream = function(dst, len) { | |
for (var i = 0; i < len; ++i) dst[i] = 0; | |
this.encrypt(dst, dst, len); | |
}; | |
function fromHex(h) { | |
h = h.replace(/([^0-9a-f])/g, ''); | |
var out = [], len = h.length, w = ''; | |
for (var i = 0; i < len; i += 2) { | |
w = h[i]; | |
if (((i+1) >= len) || typeof h[i+1] === 'undefined') { | |
w += '0'; | |
} else { | |
w += h[i+1]; | |
} | |
out.push(parseInt(w, 16)); | |
} | |
return out; | |
} | |
const textEncoder = new TextEncode | |
const textEncoder = new TextEncoder(); | |
const textDecoder = new TextDecoder(); | |
let text = "testing encryption!!"; | |
const key =fromHex('1c 92 40 a5 eb 55 d3 f3 33 88 86 04 f6 b5 f0 47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0'); | |
const nonce = fromHex('00 00 00 00 01 02 03 04 05 06 07 08'); | |
function msf_encrypt(key, nonce, text) { | |
var plaintext = textEncoder.encode(text); | |
var plen = plaintext.length, | |
buf = new Uint8Array(plen), | |
ciphertext = new Uint8Array(plen), | |
ctx = new Chacha20(key, nonce, 0); | |
ctx.keystream(buf, plen); | |
for (var i = 0; i < plen; i++) { | |
ciphertext[i] = buf[i] ^ plaintext[i]; | |
} | |
return ciphertext; | |
} | |
function msf_decrypt(key, nonce, ciphertext) { | |
var plen = ciphertext.length, | |
buf = new Uint8Array(plen), | |
plaintext = new Uint8Array(plen), | |
ctx = new Chacha20(key, nonce, 0); | |
ctx.keystream(buf, plen); | |
for (var i = 0; i < plen; i++) { | |
plaintext[i] = buf[i] ^ ciphertext[i]; | |
} | |
return textDecoder.decode(plaintext); | |
} | |
function roundtrip(text) { | |
var out = msf_encrypt(key, nonce, text); | |
var cleartext = msf_decrypt(key, nonce, out); | |
return cleartext; | |
} | |
let x = 5; | |
let y = 6; | |
let z = roundtrip(text); | |
let a = roundtrip("o"); | |
document.getElementById("demo").innerHTML = text + " roundtrip: "+ roundtrip(text) + " The value of z is: " +a; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment