k98kurz icon

Sha1StreamCipher-alt.js

k98kurz | PRO | 07/14/21 11:04:19 PM UTC (Edited) | 0 ⭐ | 476 👁️ | Never ⏰ | []
JavaScript |

3.25 KB

|

None

|

0 👍

/

0 👎

// for use in future crypto/ctf challenge; probably hilariously insecure, but that's kinda the point
// callable like jQuery, e.g. Sha1StreamCipher('key_text').encrypt('super secret message').then((ct) => console.log(ct));
 
function Sha1StreamCipher (key) {
    function init (key) {
        async function getKeyStream (l) {
            var keyBytes = [], hash;
 
            // get first 20 bytes
            hash = await crypto.subtle.digest('SHA-1', key);
            keyBytes = keyBytes.slice.call(new Uint8Array(hash));
 
            // get more until we have enough
            while (keyBytes.length < l) {
                hash = await crypto.subtle.digest('SHA-1', hash);
                keyBytes = keyBytes.concat(keyBytes.slice.call(new Uint8Array(hash)));
            }
 
            return keyBytes;
        }
 
        this.encrypt = async function (plaintext) {
            var keyBytes, ciphertext;
            plaintext = typeof plaintext == 'string' ? toUint8(plaintext) : plaintext;
            keyBytes = await getKeyStream(plaintext.length);
            ciphertext = new Uint8Array(plaintext.length);
 
            for (var i=0, il=plaintext.length; i<il; ++i) {
                ciphertext[i] = plaintext[i] ^ keyBytes[i];
            }
 
            return toHex(ciphertext);
        };
 
        this.decrypt = async function (ciphertext) {
            var keyBytes, plaintext;
            ciphertext = isHex(ciphertext) ? fromHex(ciphertext) : typeof ciphertext == 'string' ? toUint8(ciphertext) : ciphertext;
            keyBytes = await getKeyStream(ciphertext.length);
            plaintext = new Uint8Array(ciphertext.length);
 
            for (var i=0, il=ciphertext.length; i<il; ++i) {
                plaintext[i] = ciphertext[i] ^ keyBytes[i];
            }
 
            return toText(plaintext);
        };
 
        this.getKeyBytes = async function (length) {
            return await getKeyStream(length | 0);
        };
 
        function toUint8 (text) {
            var arr = new Uint8Array(text.length);
            for (var i=0, il=text.length; i<il; ++i) {
                arr[i] = text.charCodeAt(i);
            }
            return arr;
        }
 
        function toText (arr) {
            var text = '';
            for (var i=0, il=arr.length; i<il; ++i) {
                text += String.fromCharCode(arr[i]);
            }
            return text;
        }
 
        function fromHex (input) {
            input = input.length % 2 ? '0' + input : input;
            var output = new Uint8Array(input.length / 2);
            for (var i=0, l=input.length; i<l; i+=2) {
                output[i / 2] = parseInt(input[i] + input[i+1], 16);
            }
            return output;
        }
 
        function toHex (arr) {
            arr = arr instanceof Uint8Array ? arr : toUint8(arr);
 
            var text = '', char = '';
            for (var i=0, il=arr.length; i<il; ++i) {
                char = arr[i].toString(16);
                text += char.length == 2 ? char : '0' + char;
            }
            return text;
        }
 
        function isHex (str) {
            return (/^[a-fA-F0-9]+$/).test(str);
        }
 
        key = toUint8(key);
    };
 
    return new init(key);
}

Comments