And here is the script that it's for... I had to remove all whitespace, comments and two precomputed variables for it to fit though.
If the >>> ever gets added I'll release a working version in the Code Gallery.
Example:
AESEncryptCtr("bob", "kadoweu239a0djwei23oqe9w", 128)
I imagine this could be added to shared.encrypt as well.
PHP Code:
function Cipher(temp.input, temp.w) {
temp.Nb = 4;
temp.Nr = temp.w.size()/temp.Nb - 1;
temp.state = {};
temp.state[0] = {};
temp.state[1] = {};
temp.state[2] = {};
temp.state[3] = {};
for (temp.i = 0; temp.i < 4*temp.Nb; temp.i++) {
}
temp.state = AddRoundKey(temp.state, temp.w, 0, temp.Nb);
for (temp.round = 1; temp.round < temp.Nr; temp.round++) {
temp.state = SubBytes(temp.state, temp.Nb);
temp.state = ShiftRows(temp.state, temp.Nb);
temp.state = MixColumns(temp.state, temp.Nb);
temp.state = AddRoundKey(temp.state, temp.w, temp.round, temp.Nb);
}
temp.state = SubBytes(temp.state, temp.Nb);
temp.state = ShiftRows(temp.state, temp.Nb);
temp.state = AddRoundKey(temp.state, temp.w, temp.Nr, temp.Nb);
temp.output = new [4*temp.Nb];
for (temp.i = 0; temp.i < 4*temp.Nb; temp.i++) {
}
return temp.output;
}
function SubBytes(temp.s, temp.Nb) {
for (temp.r = 0; temp.r < 4; temp.r++) {
for (temp.c = 0; temp.c < temp.Nb; temp.c++) {
temp.s[temp.r][temp.c] = this.Sbox[temp.s[temp.r][temp.c]];
}
}
return s;
}
function ShiftRows(temp.s, temp.Nb) {
temp.t = new [4];
for (temp.r = 1; temp.r < 4; temp.r++) {
for (temp.c = 0; temp.c < 4; temp.c++) {
}
for (temp.c=0; temp.c < 4; temp.c++) {
temp.s[temp.r][temp.c] = temp.t[temp.c];
}
}
return s;
}
function MixColumns(temp.s, temp.Nb) {
for (temp.c = 0; temp.c < 4; temp.c++) {
temp.a = new [4];
temp.b = new [4];
for (temp.i = 0; temp.i < 4; temp.i++) {
temp.a[temp.i] = temp.s[temp.i][temp.c];
temp.b[temp.i] = temp.s[temp.i][temp.c]&0x80 ? temp.s[temp.i][temp.c]<<1 xor 0x011b : temp.s[temp.i][temp.c]<<1;
}
temp.s[0][temp.c] = temp.b[0] xor temp.a[1] xor temp.b[1] xor temp.a[2] xor temp.a[3];
temp.s[1][temp.c] = temp.a[0] xor temp.b[1] xor temp.a[2] xor temp.b[2] xor temp.a[3];
temp.s[2][temp.c] = temp.a[0] xor temp.a[1] xor temp.b[2] xor temp.a[3] xor temp.b[3];
temp.s[3][temp.c] = temp.a[0] xor temp.b[0] xor temp.a[1] xor temp.a[2] xor temp.b[3];
}
return temp.s;
}
function AddRoundKey(temp.state, temp.w, temp.rnd, temp.Nb) {
for (temp.r = 0; temp.r < 4; temp.r++) {
for (temp.c = 0; temp.c < temp.Nb; temp.c++) {
temp.state[temp.r][temp.c] = temp.state[temp.r][temp.c] xor temp.w[temp.rnd*4 + temp.c][temp.r];
}
}
return temp.state;
}
function KeyExpansion(temp.key) {
temp.Nb = 4;
temp.Nk = temp.key.size()/4;
temp.Nr = temp.Nk + 6;
temp.w = new [temp.Nb * (temp.Nr+1)];
temp.temp = new [4];
for (temp.i = 0; temp.i < temp.Nk; temp.i++) {
temp.r = {temp.key[4*temp.i], temp.key[4*temp.i + 1], temp.key[4*temp.i + 2], temp.key[4*temp.i + 3]};
temp.w[temp.i] = temp.r;
}
for (temp.i = temp.Nk; temp.i < (temp.Nb*(temp.Nr+1)); temp.i++) {
temp.w[temp.i] = new [4];
for (temp.t = 0; temp.t < 4; temp.t++) {
temp.temp[temp.t] = temp.w[temp.i-1][temp.t];
}
temp.temp = SubWord(RotWord(temp.temp));
for (temp.t = 0; temp.t < 4; temp.t++) {
temp.temp[temp.t] = temp.temp[temp.t] xor this.Rcon[temp.i/temp.Nk][temp.t];
}
temp.temp = SubWord(temp.temp);
}
for (temp.t = 0; temp.t < 4; temp.t++) {
temp.w[temp.i][temp.t] = temp.w[temp.i-temp.Nk][temp.t] xor temp.temp[temp.t];
}
}
return temp.w;
}
function SubWord(temp.w) {
for (temp.i = 0; temp.i < 4; temp.i++) {
temp.w[temp.i] = this.Sbox[temp.w[temp.i]];
}
return w;
}
function RotWord(temp.w) {
temp.tmp = temp.w[0];
for (temp.i = 0; temp.i < 3; temp.i++) {
temp.w[temp.i] = temp.w[temp.i+1];
}
temp.w[3] = temp.tmp;
return temp.w;
}
function AESEncryptCtr(temp.plaintext, temp.password, temp.nBits) {
temp.blockSize = 16;
if (!(temp.nBits == 128 || temp.nBits == 192 || temp.nBits == 256)) return "";
temp.nBytes = temp.nBits/8;
temp.pwBytes = new [temp.nBytes];
for (temp.i = 0; temp.i < temp.nBytes; temp.i++) {
temp.pwBytes[temp.i] = getascii(temp.password.charat(i));
}
temp.key = Cipher(temp.pwBytes, KeyExpansion(temp.pwBytes));
temp.key.addarray(temp.key.subarray(0, temp.nBytes-16));
temp.counterBlock = new [temp.blockSize];
temp.nonce = timevar2;
temp.nonceSec = int(temp.nonce/1000);
for (temp.i = 0; temp.i < 4; temp.i++) {
temp.counterBlock[temp.i] = (temp.nonceSec >>> temp.i*8) & 0xff;
}
for (temp.i = 0; temp.i < 4; temp.i++) {
temp.counterBlock[temp.i+4] = temp.nonceMs & 0xff;
}
temp.ctrTxt = "";
for (temp.i = 0; temp.i < 8; temp.i++) {
temp.ctrTxt @= char(temp.counterBlock[temp.i]);
}
temp.keySchedule = KeyExpansion(temp.key);
temp.blockCount = ceil(temp.plaintext.length()/temp.blockSize)+1;
temp.ciphertxt = new [temp.blockCount];
for (temp.b = 0; temp.b < temp.blockCount; temp.b++) {
for (temp.c = 0; temp.c < 4; temp.c++) {
temp.counterBlock[15-temp.c] = (temp.b >>> temp.c*8) & 0xff;
}
for (temp.c = 0; temp.c < 4; temp.c++) {
temp.counterBlock[15-temp.c-4] = (temp.b/0x100000000 >>> temp.c*8);
}
temp.cipherCntr = Cipher(temp.counterBlock, temp.keySchedule);
temp.cipherChar = new [temp.blockLength];
for (temp.i = 0; temp.i < temp.blockLength; temp.i++) {
temp.cipherChar[temp.i] = temp.cipherCntr[temp.i] xor getascii(temp.plaintext.charat(temp.b*temp.blockSize+temp.i));
temp.cipherChar[temp.i] = char(temp.cipherChar[temp.i]);
}
for (temp.i = 0; temp.i < cipherChar.size(); temp.i++) {
temp.ciphertxt[temp.b] @= cipherChar[temp.i];
}
}
temp.ciphertext = temp.ctrTxt;
for (temp.i = 0; temp.i < cipherChar.size(); temp.i++) {
temp.ciphertext @= cipherChar[temp.i];
}
temp.ciphertext = base64encode(ciphertext);
return temp.ciphertext;
}
function ceil(temp.i) {
return (temp.i == int(temp.i) ? temp.i : int(temp.i)+1);
}
function AESDecryptCtr(temp.ciphertext, temp.password, temp.nBits) {
temp.blockSize = 16;
if (!(temp.nBits==128 || temp.nBits==192 || temp.nBits==256)) return "";
temp.ciphertext = base64decode(temp.ciphertext);
temp.nBytes = temp.nBits/8;
temp.pwBytes = new [temp.nBytes];
for (temp.i = 0; temp.i < temp.nBytes; temp.i++) {
temp.pwBytes[temp.i] = getascii(temp.password.charat(i));
}
temp.key = Cipher(temp.pwBytes, KeyExpansion(temp.pwBytes));
temp.key.addarray(temp.key.subarray(0, temp.nBytes-16));
temp.counterBlock = new [8];
temp.ctrTxt = temp.ciphertext.subarray(0, 8);
for (temp.i = 0; temp.i < 8; temp.i++)
temp.counterBlock[temp.i] = getascii(temp.ctrTxt.charat(i));
temp.keySchedule = KeyExpansion(temp.key);
temp.nBlocks = ceil((temp.ciphertext.length()-8) / temp.blockSize);
temp.ct = new [temp.nBlocks];
for (temp.b = 0; temp.b < temp.nBlocks; temp.b++)
temp.ct[temp.b] = temp.ciphertext.subarray(8+temp.b*temp.blockSize, 8+temp.b*temp.blockSize+temp.blockSize);
temp.ciphertext = temp.ct;
temp.plaintxt = new [temp.ciphertext.length];
for (temp.b = 0; temp.b < temp.nBlocks; temp.b++) {
for (temp.c = 0; temp.c < 4; temp.c++) {
temp.counterBlock[15-temp.c] = ((temp.b) >>> temp.c*8) & 0xff;
}
for (temp.c = 0; temp.c < 4; temp.c++) {
temp.counterBlock[15-temp.c-4] = (((temp.b+1)/0x100000000-1) >>> temp.c*8) & 0xff;
}
temp.cipherCntr = Cipher(temp.counterBlock, temp.keySchedule);
temp.plaintxtByte = new [temp.ciphertext[temp.b].length()];
for (temp.i = 0; temp.i < temp.ciphertext[temp.b].length(); temp.i++) {
temp.plaintxtByte[temp.i] = temp.cipherCntr[temp.i] xor getascii(temp.ciphertext[temp.b].charat(i));
temp.plaintxtByte[temp.i] = char(temp.plaintxtByte[i]);
}
temp.plaintxt = "";
for (temp.i = 0; temp.i < temp.plaintxtByte.size(); temp.i++) {
temp.plaintxt[temp.b] @= temp.plaintxtByte[temp.i];
}
}
temp.plaintext = "";
for (temp.i = 0; temp.i < temp.plaintxt.size(); temp.i++) {
temp.plaintext @= temp.plaintxt[temp.i];
}
return temp.plaintext;
}