aboutsummaryrefslogtreecommitdiffhomepage
path: root/File-decryption/webapp/main.js
blob: 8169fb05a52818617d0ff83abef1e988d52491c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// as seen in /usr/lib/libzc.so / SetupKeys
const MASTER_KEY = new Uint8Array([
    0x13, 0x27, 0x3f, 0x42,
    0xa5, 0xb6, 0x79, 0xe8,
    0x20, 0x31, 0xc4, 0xf5,
    0x16, 0x17, 0x88, 0x2f,
    0x43, 0xa4, 0x55, 0x69,
    0x77, 0xb8, 0xe2, 0x83,
    0x04, 0x05, 0x60, 0x70,
    0x80, 0x02, 0x03, 0x04,
    0x50, 0x6a, 0x7c, 0x8a,
    0x02, 0x30, 0x40, 0x51,
    0x6a, 0x7d, 0x8d, 0x22,
    0x33, 0x44, 0x59, 0x66,
    0x71, 0x08, 0x02, 0x03,
    0x43, 0x05, 0x67, 0x7a,
    0x8f]);

function hex(byteArray) {
    return Array.prototype.map.call(byteArray, function (byte) {
        return ('0' + (byte & 0xFF).toString(16)).slice(-2);
    }).join('');
}

// ported from EVP_BytesToKey 
// https://github.com/openssl/openssl/blob/c04e78f0c69201226430fed14c291c281da47f2d/crypto/evp/evp_key.c#L78
function deriveKeyAndIV(password, iterations = 10) {
    var keyLen = 16;
    var ivLen = 16;
    var addmd = 0;

    var key = new Uint8Array(keyLen);
    var iv = new Uint8Array(ivLen);
    var tmp = new Uint8Array();
    var i, key_i = 0, iv_i = 0;

    for (; keyLen > 0 || ivLen > 0;) {
        if (addmd++) {
            block = new Uint8Array([...tmp, ...password]);
        } else {
            block = password;
        }

        tmp = new Uint8Array(sha1.array(block));
        for (i = 1; i < iterations; i++) {
            tmp = sha1.array(tmp);
        }

        i = 0;
        while (keyLen && i != tmp.length) {
            key[key_i++] = tmp[i];
            keyLen--;
            i++;
        }

        while (ivLen != 0 && i != tmp.length) {
            iv[iv_i++] = tmp[i];
            ivLen--;
            i++;
        }
    }

    return { key: key, iv: iv };
}

function processFileInput(e) {
    const fileName = e.target.fileName;
    const serial = document.getElementById('serial-input').value;
    let main_key = null;
    if (serial.length > 0) {
        // local decryption, use master key + serial
        main_key = new Uint8Array([...MASTER_KEY, ...new TextEncoder("utf-8").encode(serial)]);
    } else {
        // global decryption, use master key only
        main_key = MASTER_KEY;
    }

    // derive key and iv with our EVP_BytesToKey port
    const derived = deriveKeyAndIV(main_key);
    // encrypted file contents
    const ciphertext = e.target.result;
    // import the raw key
    window.crypto.subtle.importKey("raw", derived.key, "AES-CTR", true, ["encrypt", "decrypt"]).then(function (key) {
        // decrypt using aes-128-ctr
        window.crypto.subtle.decrypt({ name: "AES-CTR", counter: derived.iv, length: 128 }, key, ciphertext).then(function (cleartext) {
            var blob = new Blob([cleartext], { type: "application/octet-stream" });
            const link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download = fileName + '.dec';
            link.click();
        });
    });
}

document.addEventListener("DOMContentLoaded", function () {
    let acknowledgement = document.querySelector('.ethics-message-ack');
    let fileInput = document.getElementById('file-input');
    let fileInputLabel = document.querySelector('.file-input-label');
    
    // Etics message
    acknowledgement.addEventListener('click', function () {
        document.querySelector('.ethics-message').style.display = 'none';
        // Enable the file input
        fileInput.disabled = false;
        fileInputLabel.classList.remove('upload-disabled');
    });

    // handle file uploads
    fileInput.onchange = () => {
        const reader = new FileReader()
        reader.onload = processFileInput;
        for (let file of fileInput.files) {
            // https://stackoverflow.com/questions/24245105/how-to-get-the-filename-from-the-javascript-filereader
            reader.fileName = file.name;
            reader.readAsArrayBuffer(file);
        }
    };
});