Вы находитесь на странице: 1из 6

//

JavaScrypt -- Main page support functions


//

For details, see http://www.fourmilab.ch/javascrypt/

var loadTime = (new Date()).getTime(); // Save time page was loaded


var key;
// Key (byte array)
var prng;
// Pseudorandom number generator
// setKey -- Set key from string or hexadecimal specification
function setKey() {
if (document.key.keytype[0].checked) {
var s = encode_utf8(document.key.text.value);
var i, kmd5e, kmd5o;
if (s.length == 1) {
s += s;
}
md5_init();
for (i = 0; i < s.length; i += 2) {
md5_update(s.charCodeAt(i));
}
md5_finish();
kmd5e = byteArrayToHex(digestBits);
md5_init();
for (i = 1; i < s.length; i += 2) {
md5_update(s.charCodeAt(i));
}
md5_finish();
kmd5o = byteArrayToHex(digestBits);
var hs = kmd5e + kmd5o;
key = hexToByteArray(hs);
hs = byteArrayToHex(key);
} else {
// Hexadecimal key
var s = document.key.text.value;
var hexDigits = "0123456789abcdefABCDEF";
var hs = "", i, bogus = false;
for (i = 0; i < s.length; i++) {
var c = s.charAt(i);
if (hexDigits.indexOf(c) >= 0) {
hs += c;
} else {
bogus = true;
}
}
if (bogus) {
alert("Error: Improper character(s) in hexadecimal key.");
}
if (hs.length > (keySizeInBits / 4)) {
alert("Warning: hexadecimal key exceeds " +
(keySizeInBits / 4) + " digit maximum; truncated.");
document.key.text.value = hs = hs.slice(0, 64);
} else {
// If key is fewer than 64 hex digits, fill it with zeroes
while (hs.length < (keySizeInBits / 4)) {
hs += "0";

}
}
key = hexToByteArray(hs);
}
}
/* Generate a key from the pseudorandom number generator
and stuff it in the key field. The kind of key generated
(text or hexadecimal) is determined by which box is checked
below the key field. */
function Generate_key() {
var i, j, k = "";
var i, j, k = "";
addEntropyTime();
var seed = keyFromEntropy();
var prng = new AESprng(seed);
if (document.key.keytype[0].checked) {
// Text key
var charA = ("A").charCodeAt(0);
for (i = 0; i < 12; i++) {
if (i > 0) {
k += "-";
}
for (j = 0; j < 5; j++) {
k += String.fromCharCode(charA + prng.nextInt(25));
}
}
} else {
// Hexadecimal key
var hexDigits = "0123456789ABCDEF";
for (i = 0; i < 64; i++) {
k += hexDigits.charAt(prng.nextInt(15));
}
}
document.key.text.value = k;
delete prng;
}
function Encrypt_text() {
var v, i;
var prefix = "##### Encrypted: decrypt with http://www.fourmilab.ch/jav
ascrypt/\n",
suffix = "##### End encrypted message\n";
if (document.key.text.value.length == 0) {
alert("Please specify a key with which to encrypt the message.");
return;
}
if (document.plain.text.value.length == 0) {
alert("No plain text to encrypt! Please enter or paste plain text i
n the field above.");
return;
}
document.cipher.text.value = "";

setKey();
addEntropyTime();
prng = new AESprng(keyFromEntropy());
var plaintext = encode_utf8(document.plain.text.value);
// Compute MD5 sum of message text and add to header
md5_init();
for (i = 0; i < plaintext.length; i++) {
md5_update(plaintext.charCodeAt(i));
}
md5_finish();
var header = "";
for (i = 0; i < digestBits.length; i++) {
header += String.fromCharCode(digestBits[i]);
}
// Add message length in bytes to header
i = plaintext.length;
header += String.fromCharCode(i
header += String.fromCharCode(i
header += String.fromCharCode(i
header += String.fromCharCode(i

>>> 24);
>>> 16);
>>> 8);
& 0xFF);

/* The format of the actual message passed to rijndaelEncrypt


is:
Bytes
0-15
16-19
20-end

Content
MD5 signature of plaintext
Length of plaintext, big-endian order
Plaintext

Note that this message will be padded with zero bytes


to an integral number of AES blocks (blockSizeInBits / 8).
This does not include the initial vector for CBC
encryption, which is added internally by rijndaelEncrypt.
*/
var ct = rijndaelEncrypt(header + plaintext, key, "CBC");
if (document.plain.encoding[0].checked) {
v = armour_codegroup(ct);
} else if (document.plain.encoding[1].checked) {
v = armour_hex(ct);
} else if (document.plain.encoding[2].checked) {
v = armour_base64(ct);
}
document.cipher.text.value = prefix + v + suffix;
delete prng;
}
/* Examine the message and determine which kind of ASCII
armour it uses from the sentinel preceding the message.
We test for each of the sentinels and, if any are
found, decide based on the one found first in the
message (since, for example, the sentinel for
codegroup armour might appear in a Base64 message,
but only after the Base64 sentinel). If none of

the sentinels are found, we decode using the armour


type specified by the checkboxes for encryption.
The return value is an integer which identifies the
armour type as follows:
0
1
2

Codegroup
Hexadecimal
Base 64

*/
function determineArmourType(s) {
var kt, pcg, phex, pb64, pmin;
pcg = s.indexOf(codegroupSentinel);
phex = s.indexOf(hexSentinel);
pb64 = s.indexOf(base64sent);
if (pcg == -1) {
pcg = s.length;
}
if (phex == -1) {
phex = s.length;
}
if (pb64 == -1) {
pb64 = s.length;
}
pmin = Math.min(pcg, Math.min(phex, pb64));
if (pmin < s.length) {
if (pmin == pcg) {
kt = 0;
} else if (pmin == phex) {
kt = 1;
} else {
kt = 2;
}
} else {
if (document.plain.encoding[0].checked) {
kt = 0;
} else if (document.plain.encoding[1].checked) {
kt = 1;
} else if (document.plain.encoding[2].checked) {
kt = 2;
}
}
return kt;
}
// Decrypt ciphertext with key, place result in plaintext field
function Decrypt_text() {
if (document.key.text.value.length == 0) {
alert("Please specify a key with which to decrypt the message.");
return;
}
if (document.cipher.text.value.length == 0) {
alert("No cipher text to decrypt! Please enter or paste cipher text
in the field above.");
return;
}
document.plain.text.value = "";

setKey();
var ct = new Array(), kt;
kt = determineArmourType(document.cipher.text.value);
if (kt == 0) {
ct = disarm_codegroup(document.cipher.text.value);
} else if (kt == 1) {
ct = disarm_hex(document.cipher.text.value);
} else if (kt == 2) {
ct = disarm_base64(document.cipher.text.value);
}
var result = rijndaelDecrypt(ct, key, "CBC");
var header = result.slice(0, 20);
result = result.slice(20);
/* Extract the length of the plaintext transmitted and
verify its consistency with the length decoded. Note
that in many cases the decrypted messages will include
pad bytes added to expand the plaintext to an integral
number of AES blocks (blockSizeInBits / 8). */
var dl = (header[16] << 24) | (header[17] << 16) | (header[18] << 8) | h
eader[19];
if ((dl < 0) || (dl > result.length)) {
alert("Message (length " + result.length + ") truncated. " +
dl + " characters expected.");
// Try to sauve qui peut by setting length to entire message
dl = result.length;
}
/* Compute MD5 signature of message body and verify
against signature in message. While we're at it,
we assemble the plaintext result string. Note that
the length is that just extracted above from the
message, *not* the full decrypted message text.
AES requires all messages to be an integral number
of blocks, and the message may have been padded with
zero bytes to fill out the last block; using the
length from the message header elides them from
both the MD5 computation and plaintext result. */
var i, plaintext = "";
md5_init();
for (i = 0; i < dl; i++) {
plaintext += String.fromCharCode(result[i]);
md5_update(result[i]);
}
md5_finish();
for (i = 0; i < digestBits.length; i++) {
if (digestBits[i] != header[i]) {
alert("Message corrupted. Checksum of decrypted message does no
t match.");
break;
}
}
// That's it; plug plaintext into the result field

document.plain.text.value = decode_utf8(plaintext);
}

Вам также может понравиться