From 124ef39cb84dec12d21a36e98039e6a5042e7317 Mon Sep 17 00:00:00 2001 From: ausiv4 Date: Wed, 12 Aug 2009 17:01:23 +0000 Subject: When upgrading the user from a non-srp account to an SRP account, the client must send the server the password. I wasn't happy about doing this in plaintext, so I've incorporated slowAES on both the client and the server to encrypt the password before it is sent, using the key generated in the first SRP transaction. --- django/srpproject/srp/aes.py | 655 ++++++++++++++++++++++++++++ django/srpproject/srp/views.py | 36 +- django/srpproject/templates/aes.html | 69 +++ django/srpproject/urls.py | 2 + javascript/aes.js | 771 +++++++++++++++++++++++++++++++++ javascript/cryptoHelpers.js | 185 ++++++++ javascript/jsPacker/build-pack-hash.sh | 2 +- javascript/jsPacker/hash.min.js | 2 +- javascript/jsPacker/srp.min.js | 2 +- javascript/srp.js | 25 +- 10 files changed, 1742 insertions(+), 7 deletions(-) create mode 100644 django/srpproject/srp/aes.py create mode 100644 django/srpproject/templates/aes.html create mode 100644 javascript/aes.js create mode 100644 javascript/cryptoHelpers.js diff --git a/django/srpproject/srp/aes.py b/django/srpproject/srp/aes.py new file mode 100644 index 0000000..4c27d41 --- /dev/null +++ b/django/srpproject/srp/aes.py @@ -0,0 +1,655 @@ +#!/usr/bin/python +# +# aes.py: implements AES - Advanced Encryption Standard +# from the SlowAES project, http://code.google.com/p/slowaes/ +# +# Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ), +# Alex Martelli ( http://www.aleax.it ) +# +# Ported from C code written by Laurent Haan ( http://www.progressive-coding.com ) +# +# Licensed under the Apache License, Version 2.0 +# http://www.apache.org/licenses/ +# +import os +import sys +import math + +def append_PKCS7_padding(s): + """return s padded to a multiple of 16-bytes by PKCS7 padding""" + numpads = 16 - (len(s)%16) + return s + numpads*chr(numpads) + +def strip_PKCS7_padding(s): + """return s stripped of PKCS7 padding""" + if len(s)%16 or not s: + raise ValueError("String of len %d can't be PCKS7-padded" % len(s)) + numpads = ord(s[-1]) + if numpads > 16: + raise ValueError("String ending with %r can't be PCKS7-padded" % s[-1]) + return s[:-numpads] + +class AES(object): + # valid key sizes + keySize = dict(SIZE_128=16, SIZE_192=24, SIZE_256=32) + + # Rijndael S-box + sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, + 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, + 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, + 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, + 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, + 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, + 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, + 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, + 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, + 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, + 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, + 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, + 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, + 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, + 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, + 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, + 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, + 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, + 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, + 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, + 0x54, 0xbb, 0x16] + + # Rijndael Inverted S-box + rsbox = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, + 0x9e, 0x81, 0xf3, 0xd7, 0xfb , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, + 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb , 0x54, + 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, + 0x42, 0xfa, 0xc3, 0x4e , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, + 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 , 0x72, 0xf8, + 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, + 0x65, 0xb6, 0x92 , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, + 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 , 0x90, 0xd8, 0xab, + 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, + 0x45, 0x06 , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, + 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b , 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, + 0x73 , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, + 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e , 0x47, 0xf1, 0x1a, 0x71, 0x1d, + 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b , + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, + 0xfe, 0x78, 0xcd, 0x5a, 0xf4 , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, + 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f , 0x60, + 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, + 0x93, 0xc9, 0x9c, 0xef , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, + 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 , 0x17, 0x2b, + 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, + 0x21, 0x0c, 0x7d] + + def getSBoxValue(self,num): + """Retrieves a given S-Box Value""" + return self.sbox[num] + + def getSBoxInvert(self,num): + """Retrieves a given Inverted S-Box Value""" + return self.rsbox[num] + + def rotate(self, word): + """ Rijndael's key schedule rotate operation. + + Rotate a word eight bits to the left: eg, rotate(1d2c3a4f) == 2c3a4f1d + Word is an char list of size 4 (32 bits overall). + """ + return word[1:] + word[:1] + + # Rijndael Rcon + Rcon = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, + 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, + 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, + 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, + 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, + 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, + 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, + 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, + 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, + 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, + 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, + 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, + 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, + 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, + 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, + 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, + 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, + 0xe8, 0xcb ] + + def getRconValue(self, num): + """Retrieves a given Rcon Value""" + return self.Rcon[num] + + def core(self, word, iteration): + """Key schedule core.""" + # rotate the 32-bit word 8 bits to the left + word = self.rotate(word) + # apply S-Box substitution on all 4 parts of the 32-bit word + for i in range(4): + word[i] = self.getSBoxValue(word[i]) + # XOR the output of the rcon operation with i to the first part + # (leftmost) only + word[0] = word[0] ^ self.getRconValue(iteration) + return word + + def expandKey(self, key, size, expandedKeySize): + """Rijndael's key expansion. + + Expands an 128,192,256 key into an 176,208,240 bytes key + + expandedKey is a char list of large enough size, + key is the non-expanded key. + """ + # current expanded keySize, in bytes + currentSize = 0 + rconIteration = 1 + expandedKey = [0] * expandedKeySize + + # set the 16, 24, 32 bytes of the expanded key to the input key + for j in range(size): + expandedKey[j] = key[j] + currentSize += size + + while currentSize < expandedKeySize: + # assign the previous 4 bytes to the temporary value t + t = expandedKey[currentSize-4:currentSize] + + # every 16,24,32 bytes we apply the core schedule to t + # and increment rconIteration afterwards + if currentSize % size == 0: + t = self.core(t, rconIteration) + rconIteration += 1 + # For 256-bit keys, we add an extra sbox to the calculation + if size == self.keySize["SIZE_256"] and ((currentSize % size) == 16): + for l in range(4): t[l] = self.getSBoxValue(t[l]) + + # We XOR t with the four-byte block 16,24,32 bytes before the new + # expanded key. This becomes the next four bytes in the expanded + # key. + for m in range(4): + expandedKey[currentSize] = expandedKey[currentSize - size] ^ \ + t[m] + currentSize += 1 + + return expandedKey + + def addRoundKey(self, state, roundKey): + """Adds (XORs) the round key to the state.""" + for i in range(16): + state[i] ^= roundKey[i] + return state + + def createRoundKey(self, expandedKey, roundKeyPointer): + """Create a round key. + Creates a round key from the given expanded key and the + position within the expanded key. + """ + roundKey = [0] * 16 + for i in range(4): + for j in range(4): + roundKey[j*4+i] = expandedKey[roundKeyPointer + i*4 + j] + return roundKey + + def galois_multiplication(self, a, b): + """Galois multiplication of 8 bit characters a and b.""" + p = 0 + for counter in range(8): + if b & 1: p ^= a + hi_bit_set = a & 0x80 + a <<= 1 + # keep a 8 bit + a &= 0xFF + if hi_bit_set: + a ^= 0x1b + b >>= 1 + return p + + # + # substitute all the values from the state with the value in the SBox + # using the state value as index for the SBox + # + def subBytes(self, state, isInv): + if isInv: getter = self.getSBoxInvert + else: getter = self.getSBoxValue + for i in range(16): state[i] = getter(state[i]) + return state + + # iterate over the 4 rows and call shiftRow() with that row + def shiftRows(self, state, isInv): + for i in range(4): + state = self.shiftRow(state, i*4, i, isInv) + return state + + # each iteration shifts the row to the left by 1 + def shiftRow(self, state, statePointer, nbr, isInv): + for i in range(nbr): + if isInv: + state[statePointer:statePointer+4] = \ + state[statePointer+3:statePointer+4] + \ + state[statePointer:statePointer+3] + else: + state[statePointer:statePointer+4] = \ + state[statePointer+1:statePointer+4] + \ + state[statePointer:statePointer+1] + return state + + # galois multiplication of the 4x4 matrix + def mixColumns(self, state, isInv): + # iterate over the 4 columns + for i in range(4): + # construct one column by slicing over the 4 rows + column = state[i:i+16:4] + # apply the mixColumn on one column + column = self.mixColumn(column, isInv) + # put the values back into the state + state[i:i+16:4] = column + + return state + + # galois multiplication of 1 column of the 4x4 matrix + def mixColumn(self, column, isInv): + if isInv: mult = [14, 9, 13, 11] + else: mult = [2, 1, 1, 3] + cpy = list(column) + g = self.galois_multiplication + + column[0] = g(cpy[0], mult[0]) ^ g(cpy[3], mult[1]) ^ \ + g(cpy[2], mult[2]) ^ g(cpy[1], mult[3]) + column[1] = g(cpy[1], mult[0]) ^ g(cpy[0], mult[1]) ^ \ + g(cpy[3], mult[2]) ^ g(cpy[2], mult[3]) + column[2] = g(cpy[2], mult[0]) ^ g(cpy[1], mult[1]) ^ \ + g(cpy[0], mult[2]) ^ g(cpy[3], mult[3]) + column[3] = g(cpy[3], mult[0]) ^ g(cpy[2], mult[1]) ^ \ + g(cpy[1], mult[2]) ^ g(cpy[0], mult[3]) + return column + + # applies the 4 operations of the forward round in sequence + def aes_round(self, state, roundKey): + state = self.subBytes(state, False) + state = self.shiftRows(state, False) + state = self.mixColumns(state, False) + state = self.addRoundKey(state, roundKey) + return state + + # applies the 4 operations of the inverse round in sequence + def aes_invRound(self, state, roundKey): + state = self.shiftRows(state, True) + state = self.subBytes(state, True) + state = self.addRoundKey(state, roundKey) + state = self.mixColumns(state, True) + return state + + # Perform the initial operations, the standard round, and the final + # operations of the forward aes, creating a round key for each round + def aes_main(self, state, expandedKey, nbrRounds): + state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0)) + i = 1 + while i < nbrRounds: + state = self.aes_round(state, + self.createRoundKey(expandedKey, 16*i)) + i += 1 + state = self.subBytes(state, False) + state = self.shiftRows(state, False) + state = self.addRoundKey(state, + self.createRoundKey(expandedKey, 16*nbrRounds)) + return state + + # Perform the initial operations, the standard round, and the final + # operations of the inverse aes, creating a round key for each round + def aes_invMain(self, state, expandedKey, nbrRounds): + state = self.addRoundKey(state, + self.createRoundKey(expandedKey, 16*nbrRounds)) + i = nbrRounds - 1 + while i > 0: + state = self.aes_invRound(state, + self.createRoundKey(expandedKey, 16*i)) + i -= 1 + state = self.shiftRows(state, True) + state = self.subBytes(state, True) + state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0)) + return state + + # encrypts a 128 bit input block against the given key of size specified + def encrypt(self, iput, key, size): + output = [0] * 16 + # the number of rounds + nbrRounds = 0 + # the 128 bit block to encode + block = [0] * 16 + # set the number of rounds + if size == self.keySize["SIZE_128"]: nbrRounds = 10 + elif size == self.keySize["SIZE_192"]: nbrRounds = 12 + elif size == self.keySize["SIZE_256"]: nbrRounds = 14 + else: return None + + # the expanded keySize + expandedKeySize = 16*(nbrRounds+1) + + # Set the block values, for the block: + # a0,0 a0,1 a0,2 a0,3 + # a1,0 a1,1 a1,2 a1,3 + # a2,0 a2,1 a2,2 a2,3 + # a3,0 a3,1 a3,2 a3,3 + # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 + # + # iterate over the columns + for i in range(4): + # iterate over the rows + for j in range(4): + block[(i+(j*4))] = iput[(i*4)+j] + + # expand the key into an 176, 208, 240 bytes key + # the expanded key + expandedKey = self.expandKey(key, size, expandedKeySize) + + # encrypt the block using the expandedKey + block = self.aes_main(block, expandedKey, nbrRounds) + + # unmap the block again into the output + for k in range(4): + # iterate over the rows + for l in range(4): + output[(k*4)+l] = block[(k+(l*4))] + return output + + # decrypts a 128 bit input block against the given key of size specified + def decrypt(self, iput, key, size): + output = [0] * 16 + # the number of rounds + nbrRounds = 0 + # the 128 bit block to decode + block = [0] * 16 + # set the number of rounds + if size == self.keySize["SIZE_128"]: nbrRounds = 10 + elif size == self.keySize["SIZE_192"]: nbrRounds = 12 + elif size == self.keySize["SIZE_256"]: nbrRounds = 14 + else: return None + + # the expanded keySize + expandedKeySize = 16*(nbrRounds+1) + + # Set the block values, for the block: + # a0,0 a0,1 a0,2 a0,3 + # a1,0 a1,1 a1,2 a1,3 + # a2,0 a2,1 a2,2 a2,3 + # a3,0 a3,1 a3,2 a3,3 + # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 + + # iterate over the columns + for i in range(4): + # iterate over the rows + for j in range(4): + block[(i+(j*4))] = iput[(i*4)+j] + # expand the key into an 176, 208, 240 bytes key + expandedKey = self.expandKey(key, size, expandedKeySize) + # decrypt the block using the expandedKey + block = self.aes_invMain(block, expandedKey, nbrRounds) + # unmap the block again into the output + for k in range(4): + # iterate over the rows + for l in range(4): + output[(k*4)+l] = block[(k+(l*4))] + return output + + +class AESModeOfOperation(object): + + aes = AES() + + # structure of supported modes of operation + modeOfOperation = dict(OFB=0, CFB=1, CBC=2) + + # converts a 16 character string into a number array + def convertString(self, string, start, end, mode): + if end - start > 16: end = start + 16 + if mode == self.modeOfOperation["CBC"]: ar = [0] * 16 + else: ar = [] + + i = start + j = 0 + while len(ar) < end - start: + ar.append(0) + while i < end: + ar[j] = ord(string[i]) + j += 1 + i += 1 + return ar + + # Mode of Operation Encryption + # stringIn - Input String + # mode - mode of type modeOfOperation + # hexKey - a hex key of the bit length size + # size - the bit length of the key + # hexIV - the 128 bit hex Initilization Vector + def encrypt(self, stringIn, mode, key, size, IV): + if len(key) % size: + return None + if len(IV) % 16: + return None + # the AES input/output + plaintext = [] + iput = [0] * 16 + output = [] + ciphertext = [0] * 16 + # the output cipher string + cipherOut = [] + # char firstRound + firstRound = True + if stringIn != None: + for j in range(int(math.ceil(float(len(stringIn))/16))): + start = j*16 + end = j*16+16 + if end > len(stringIn): + end = len(stringIn) + plaintext = self.convertString(stringIn, start, end, mode) + # print 'PT@%s:%s' % (j, plaintext) + if mode == self.modeOfOperation["CFB"]: + if firstRound: + output = self.aes.encrypt(IV, key, size) + firstRound = False + else: + output = self.aes.encrypt(iput, key, size) + for i in range(16): + if len(plaintext)-1 < i: + ciphertext[i] = 0 ^ output[i] + elif len(output)-1 < i: + ciphertext[i] = plaintext[i] ^ 0 + elif len(plaintext)-1 < i and len(output) < i: + ciphertext[i] = 0 ^ 0 + else: + ciphertext[i] = plaintext[i] ^ output[i] + for k in range(end-start): + cipherOut.append(ciphertext[k]) + iput = ciphertext + elif mode == self.modeOfOperation["OFB"]: + if firstRound: + output = self.aes.encrypt(IV, key, size) + firstRound = False + else: + output = self.aes.encrypt(iput, key, size) + for i in range(16): + if len(plaintext)-1 < i: + ciphertext[i] = 0 ^ output[i] + elif len(output)-1 < i: + ciphertext[i] = plaintext[i] ^ 0 + elif len(plaintext)-1 < i and len(output) < i: + ciphertext[i] = 0 ^ 0 + else: + ciphertext[i] = plaintext[i] ^ output[i] + for k in range(end-start): + cipherOut.append(ciphertext[k]) + iput = output + elif mode == self.modeOfOperation["CBC"]: + for i in range(16): + if firstRound: + iput[i] = plaintext[i] ^ IV[i] + else: + iput[i] = plaintext[i] ^ ciphertext[i] + # print 'IP@%s:%s' % (j, iput) + firstRound = False + ciphertext = self.aes.encrypt(iput, key, size) + # always 16 bytes because of the padding for CBC + for k in range(16): + cipherOut.append(ciphertext[k]) + return mode, len(stringIn), cipherOut + + # Mode of Operation Decryption + # cipherIn - Encrypted String + # originalsize - The unencrypted string length - required for CBC + # mode - mode of type modeOfOperation + # key - a number array of the bit length size + # size - the bit length of the key + # IV - the 128 bit number array Initilization Vector + def decrypt(self, cipherIn, originalsize, mode, key, size, IV): + # cipherIn = unescCtrlChars(cipherIn) + if len(key) % size: + return None + if len(IV) % 16: + return None + # the AES input/output + ciphertext = [] + iput = [] + output = [] + plaintext = [0] * 16 + # the output plain text string + stringOut = '' + # char firstRound + firstRound = True + if cipherIn != None: + for j in range(int(math.ceil(float(len(cipherIn))/16))): + start = j*16 + end = j*16+16 + if j*16+16 > len(cipherIn): + end = len(cipherIn) + ciphertext = cipherIn[start:end] + if mode == self.modeOfOperation["CFB"]: + if firstRound: + output = self.aes.encrypt(IV, key, size) + firstRound = False + else: + output = self.aes.encrypt(iput, key, size) + for i in range(16): + if len(output)-1 < i: + plaintext[i] = 0 ^ ciphertext[i] + elif len(ciphertext)-1 < i: + plaintext[i] = output[i] ^ 0 + elif len(output)-1 < i and len(ciphertext) < i: + plaintext[i] = 0 ^ 0 + else: + plaintext[i] = output[i] ^ ciphertext[i] + for k in range(end-start): + stringOut += chr(plaintext[k]) + iput = ciphertext + elif mode == self.modeOfOperation["OFB"]: + if firstRound: + output = self.aes.encrypt(IV, key, size) + firstRound = False + else: + output = self.aes.encrypt(iput, key, size) + for i in range(16): + if len(output)-1 < i: + plaintext[i] = 0 ^ ciphertext[i] + elif len(ciphertext)-1 < i: + plaintext[i] = output[i] ^ 0 + elif len(output)-1 < i and len(ciphertext) < i: + plaintext[i] = 0 ^ 0 + else: + plaintext[i] = output[i] ^ ciphertext[i] + for k in range(end-start): + stringOut += chr(plaintext[k]) + iput = output + elif mode == self.modeOfOperation["CBC"]: + output = self.aes.decrypt(ciphertext, key, size) + for i in range(16): + if firstRound: + plaintext[i] = IV[i] ^ output[i] + else: + plaintext[i] = iput[i] ^ output[i] + firstRound = False + if originalsize is not None and originalsize < end: + for k in range(originalsize-start): + stringOut += chr(plaintext[k]) + else: + for k in range(end-start): + stringOut += chr(plaintext[k]) + iput = ciphertext + return stringOut + + +def encryptData(key, data, mode=AESModeOfOperation.modeOfOperation["CBC"]): + """encrypt `data` using `key` + + `key` should be a string of bytes. + + returned cipher is a string of bytes prepended with the initialization + vector. + + """ + key = map(ord, key) + data = append_PKCS7_padding(data) + keysize = len(key) + assert keysize in AES.keySize.values(), 'invalid key size: %s' % keysize + # create a new iv using random data + iv = [ord(i) for i in os.urandom(16)] + moo = AESModeOfOperation() + (mode, length, ciph) = moo.encrypt(data, mode, key, keysize, iv) + # With padding, the original length does not need to be known. It's a bad + # idea to store the original message length. + # prepend the iv. + return ''.join(map(chr, iv)) + ''.join(map(chr, ciph)) + +def decryptData(key, data, mode=AESModeOfOperation.modeOfOperation["CBC"]): + """decrypt `data` using `key` + + `key` should be a string of bytes. + + `data` should have the initialization vector prepended as a string or + ordinal values. + + """ + + key = map(ord, key) + keysize = len(key) + assert keysize in AES.keySize.values(), 'invalid key size: %s' % keysize + # iv is first 16 bytes + iv = map(ord, data[:16]) + data = map(ord, data[16:]) + moo = AESModeOfOperation() + decr = moo.decrypt(data, None, mode, key, keysize, iv) + decr = strip_PKCS7_padding(decr) + return decr + +def generateRandomKey(keysize): + """Generates a key from random data of length `keysize`. + + The returned key is a string of bytes. + + """ + if keysize not in (16, 24, 32): + emsg = 'Invalid keysize, %s. Should be one of (16, 24, 32).' + raise ValueError, emsg % keysize + return os.urandom(keysize) + +if __name__ == "__main__": + moo = AESModeOfOperation() + cleartext = "This is a test!" + cypherkey = [143,194,34,208,145,203,230,143,177,246,97,206,145,92,255,84] + iv = [103,35,148,239,76,213,47,118,255,222,123,176,106,134,98,92] + mode, orig_len, ciph = moo.encrypt(cleartext, moo.modeOfOperation["CBC"], + cypherkey, moo.aes.keySize["SIZE_128"], iv) + print 'm=%s, ol=%s (%s), ciph=%s' % (mode, orig_len, len(cleartext), ciph) + decr = moo.decrypt(ciph, orig_len, mode, cypherkey, + moo.aes.keySize["SIZE_128"], iv) + print decr + diff --git a/django/srpproject/srp/views.py b/django/srpproject/srp/views.py index 8529fa9..cbf1389 100644 --- a/django/srpproject/srp/views.py +++ b/django/srpproject/srp/views.py @@ -25,6 +25,10 @@ def generate_fake_salt(I): salt_chars = "./" + string.ascii_letters + string.digits salt = "".join([random.choice(salt_chars) for i in range(0,16)]) return salt, int(hashlib.sha256("%s:%s" % (salt, settings.SECRET_KEY)).hexdigest(), 16) + +def test_aes(request): + from django.shortcuts import render_to_response + return render_to_response('aes.html',{'static_files': "http://%s/srp-test/javascript" % request.get_host()}) def login_page(request): from django.shortcuts import render_to_response @@ -150,7 +154,8 @@ def upgrade_add_verifier(request): from django.contrib.auth.models import User import hashlib salt = generate_salt() - x = int(hashlib.sha256(salt + hashlib.sha256("%s:%s" % (request.session["srp_I"], request.POST["p"])).hexdigest()).hexdigest(), 16) + key = hashlib.sha256(request.session["srp_S"]).hexdigest() + x = int(hashlib.sha256(salt + hashlib.sha256("%s:%s" % (request.session["srp_I"], decrypt(request.POST["p"], key, int(request.POST["l"])))).hexdigest()).hexdigest(), 16) user = User.objects.get(username=request.session["srp_I"]) srpuser = SRPUser() srpuser.__dict__.update(user.__dict__) @@ -159,3 +164,32 @@ def upgrade_add_verifier(request): srpuser.password = "" srpuser.save() return HttpResponse("", mimetype="text/xml") + +def decrypt(c, key, plen): + from srp import aes + import base64 + moo = aes.AESModeOfOperation() + cypherkey = map(ord, key.decode("hex")) + try: + ciphertext = base64.b64decode(c.replace("_", "+")) + except TypeError: + return HttpResponse("%s" % request.POST["c"], mimetype="text/xml" ) + iv = map(ord, ciphertext[:16]) + ciphertext= map(ord, ciphertext[16:]) + return moo.decrypt(ciphertext, 0, moo.modeOfOperation["CFB"], cypherkey, len(cypherkey), iv)[:plen] + + +def doaes(request): + from srp import aes + import base64 + moo = aes.AESModeOfOperation() + cypherkey = map(ord, "6754c921b8dcbd1f8b58748cd87ac60ce857314687a65df05c470a46f438842c".decode("hex")) + try: + ciphertext = base64.b64decode(request.POST["c"].replace("_", "+")) + except TypeError: + return HttpResponse("%s" % request.POST["c"], mimetype="text/xml" ) + iv = map(ord, ciphertext[:16]) + ciphertext= map(ord, ciphertext[16:]) + # (self, cipherIn, originalsize, mode, key, size, IV): + plaintext = moo.decrypt(ciphertext, int(request.POST["l"]), moo.modeOfOperation["OFB"], cypherkey, len(cypherkey), iv)[:int(request.POST["l"])] + return HttpResponse("

%s

" % plaintext, mimetype="text/xml" ) diff --git a/django/srpproject/templates/aes.html b/django/srpproject/templates/aes.html new file mode 100644 index 0000000..dbdd4ac --- /dev/null +++ b/django/srpproject/templates/aes.html @@ -0,0 +1,69 @@ + + + + + + + + + + + + + diff --git a/django/srpproject/urls.py b/django/srpproject/urls.py index 550676e..07f446f 100644 --- a/django/srpproject/urls.py +++ b/django/srpproject/urls.py @@ -23,4 +23,6 @@ urlpatterns = patterns('', (r'^srp/register/$', views.register_page), (r'^srp/upgrade/authenticate/$', views.upgrade_auth), (r'^srp/upgrade/verifier/$', views.upgrade_add_verifier), + (r'^srp/aes/$', views.test_aes), + (r'^srp/aes/post/$', views.doaes), ) diff --git a/javascript/aes.js b/javascript/aes.js new file mode 100644 index 0000000..5682618 --- /dev/null +++ b/javascript/aes.js @@ -0,0 +1,771 @@ +/* + * aes.js: implements AES - Advanced Encryption Standard + * from the SlowAES project, http://code.google.com/p/slowaes/ + * + * Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ), + * Mark Percival ( http://mpercival.com ), + * + * Ported from C code written by Laurent Haan ( http://www.progressive-coding.com ) + * + * Licensed under the Apache License, Version 2.0 + * http://www.apache.org/licenses/ + */ + +var slowAES = { + /* + * START AES SECTION + */ + aes:{ + // structure of valid key sizes + keySize:{ + SIZE_128:16, + SIZE_192:24, + SIZE_256:32 + }, + + // Rijndael S-box + sbox:[ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ], + + // Rijndael Inverted S-box + rsbox: + [ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb + , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb + , 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e + , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 + , 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 + , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 + , 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 + , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b + , 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 + , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e + , 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b + , 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 + , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f + , 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef + , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 + , 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d ], + + /* rotate the word eight bits to the left */ + rotate:function(word) + { + var c = word[0]; + for (var i = 0; i < 3; i++) + word[i] = word[i+1]; + word[3] = c; + + return word; + }, + + // Rijndael Rcon + Rcon:[ + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, + 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, + 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, + 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, + 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, + 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, + 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, + 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, + 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, + 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, + 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, + 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, + 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, + 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb ], + + G2X: [ + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, + 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, + 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46, + 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, + 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, + 0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, + 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xa6, + 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, + 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, + 0xd8, 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, + 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, 0x1b, 0x19, 0x1f, 0x1d, + 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, + 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, + 0x23, 0x21, 0x27, 0x25, 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, + 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, 0x7b, 0x79, 0x7f, 0x7d, + 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, + 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, + 0x83, 0x81, 0x87, 0x85, 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, + 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, 0xdb, 0xd9, 0xdf, 0xdd, + 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, + 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, + 0xe3, 0xe1, 0xe7, 0xe5 + ], + + G3X: [ + 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, + 0x14, 0x17, 0x12, 0x11, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, + 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, 0x60, 0x63, 0x66, 0x65, + 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, + 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, + 0x44, 0x47, 0x42, 0x41, 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, + 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, 0xf0, 0xf3, 0xf6, 0xf5, + 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, + 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, + 0xb4, 0xb7, 0xb2, 0xb1, 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, + 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, 0x9b, 0x98, 0x9d, 0x9e, + 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, + 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, + 0xbf, 0xbc, 0xb9, 0xba, 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, + 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, 0xcb, 0xc8, 0xcd, 0xce, + 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, + 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, + 0x4f, 0x4c, 0x49, 0x4a, 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, + 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, 0x3b, 0x38, 0x3d, 0x3e, + 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, + 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, + 0x1f, 0x1c, 0x19, 0x1a + ], + + G9X: [ + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, + 0x6c, 0x65, 0x7e, 0x77, 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, + 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x3b, 0x32, 0x29, 0x20, + 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, + 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, + 0xc7, 0xce, 0xd5, 0xdc, 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, + 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, 0xe6, 0xef, 0xf4, 0xfd, + 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, + 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, + 0x21, 0x28, 0x33, 0x3a, 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, + 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, 0xec, 0xe5, 0xfe, 0xf7, + 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, + 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, + 0x10, 0x19, 0x02, 0x0b, 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, + 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, 0x47, 0x4e, 0x55, 0x5c, + 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, + 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, + 0xf6, 0xff, 0xe4, 0xed, 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, + 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, 0xa1, 0xa8, 0xb3, 0xba, + 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, + 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, + 0x5d, 0x54, 0x4f, 0x46 + ], + + GBX: [ + 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, + 0x74, 0x7f, 0x62, 0x69, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, + 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0x7b, 0x70, 0x6d, 0x66, + 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, + 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, + 0xbf, 0xb4, 0xa9, 0xa2, 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, + 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, 0x46, 0x4d, 0x50, 0x5b, + 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, + 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, + 0xf9, 0xf2, 0xef, 0xe4, 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, + 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, 0xf7, 0xfc, 0xe1, 0xea, + 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, + 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, + 0x33, 0x38, 0x25, 0x2e, 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, + 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, 0x3c, 0x37, 0x2a, 0x21, + 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, + 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, + 0x75, 0x7e, 0x63, 0x68, 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, + 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, 0x7a, 0x71, 0x6c, 0x67, + 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, + 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, + 0xbe, 0xb5, 0xa8, 0xa3 + ], + + GDX: [ + 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, + 0x5c, 0x51, 0x46, 0x4b, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, + 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 0xbb, 0xb6, 0xa1, 0xac, + 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, + 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, + 0x37, 0x3a, 0x2d, 0x20, 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, + 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, 0xbd, 0xb0, 0xa7, 0xaa, + 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, + 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, + 0x8a, 0x87, 0x90, 0x9d, 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, + 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, 0xda, 0xd7, 0xc0, 0xcd, + 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, + 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, + 0x56, 0x5b, 0x4c, 0x41, 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, + 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, 0xb1, 0xbc, 0xab, 0xa6, + 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, + 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, + 0xeb, 0xe6, 0xf1, 0xfc, 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, + 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 0x0c, 0x01, 0x16, 0x1b, + 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, + 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, + 0x80, 0x8d, 0x9a, 0x97 + ], + + GEX: [ + 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, + 0x48, 0x46, 0x54, 0x5a, 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, + 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xdb, 0xd5, 0xc7, 0xc9, + 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, + 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, + 0x73, 0x7d, 0x6f, 0x61, 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, + 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, 0x4d, 0x43, 0x51, 0x5f, + 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, + 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, + 0x3e, 0x30, 0x22, 0x2c, 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, + 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, 0x41, 0x4f, 0x5d, 0x53, + 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, + 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, + 0xe9, 0xe7, 0xf5, 0xfb, 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, + 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, 0x7a, 0x74, 0x66, 0x68, + 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, + 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, + 0xa4, 0xaa, 0xb8, 0xb6, 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, + 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, 0x37, 0x39, 0x2b, 0x25, + 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, + 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, + 0x9f, 0x91, 0x83, 0x8d + ], + + // Key Schedule Core + core:function(word,iteration) + { + /* rotate the 32-bit word 8 bits to the left */ + word = this.rotate(word); + /* apply S-Box substitution on all 4 parts of the 32-bit word */ + for (var i = 0; i < 4; ++i) + word[i] = this.sbox[word[i]]; + /* XOR the output of the rcon operation with i to the first part (leftmost) only */ + word[0] = word[0]^this.Rcon[iteration]; + return word; + }, + + /* Rijndael's key expansion + * expands an 128,192,256 key into an 176,208,240 bytes key + * + * expandedKey is a pointer to an char array of large enough size + * key is a pointer to a non-expanded key + */ + expandKey:function(key,size) + { + var expandedKeySize = (16*(this.numberOfRounds(size)+1)); + + /* current expanded keySize, in bytes */ + var currentSize = 0; + var rconIteration = 1; + var t = []; // temporary 4-byte variable + + var expandedKey = []; + for(var i = 0;i < expandedKeySize;i++) + expandedKey[i] = 0; + + /* set the 16,24,32 bytes of the expanded key to the input key */ + for (var j = 0; j < size; j++) + expandedKey[j] = key[j]; + currentSize += size; + + while (currentSize < expandedKeySize) + { + /* assign the previous 4 bytes to the temporary value t */ + for (var k = 0; k < 4; k++) + t[k] = expandedKey[(currentSize - 4) + k]; + + /* every 16,24,32 bytes we apply the core schedule to t + * and increment rconIteration afterwards + */ + if(currentSize % size == 0) + t = this.core(t, rconIteration++); + + /* For 256-bit keys, we add an extra sbox to the calculation */ + if(size == this.keySize.SIZE_256 && ((currentSize % size) == 16)) + for(var l = 0; l < 4; l++) + t[l] = this.sbox[t[l]]; + + /* We XOR t with the four-byte block 16,24,32 bytes before the new expanded key. + * This becomes the next four bytes in the expanded key. + */ + for(var m = 0; m < 4; m++) { + expandedKey[currentSize] = expandedKey[currentSize - size] ^ t[m]; + currentSize++; + } + } + return expandedKey; + }, + + // Adds (XORs) the round key to the state + addRoundKey:function(state,roundKey) + { + for (var i = 0; i < 16; i++) + state[i] ^= roundKey[i]; + return state; + }, + + // Creates a round key from the given expanded key and the + // position within the expanded key. + createRoundKey:function(expandedKey,roundKeyPointer) + { + var roundKey = []; + for (var i = 0; i < 4; i++) + for (var j = 0; j < 4; j++) + roundKey[j*4+i] = expandedKey[roundKeyPointer + i*4 + j]; + return roundKey; + }, + + /* substitute all the values from the state with the value in the SBox + * using the state value as index for the SBox + */ + subBytes:function(state,isInv) + { + for (var i = 0; i < 16; i++) + state[i] = isInv?this.rsbox[state[i]]:this.sbox[state[i]]; + return state; + }, + + /* iterate over the 4 rows and call shiftRow() with that row */ + shiftRows:function(state,isInv) + { + for (var i = 0; i < 4; i++) + state = this.shiftRow(state,i*4, i,isInv); + return state; + }, + + /* each iteration shifts the row to the left by 1 */ + shiftRow:function(state,statePointer,nbr,isInv) + { + for (var i = 0; i < nbr; i++) + { + if(isInv) + { + var tmp = state[statePointer + 3]; + for (var j = 3; j > 0; j--) + state[statePointer + j] = state[statePointer + j-1]; + state[statePointer] = tmp; + } + else + { + var tmp = state[statePointer]; + for (var j = 0; j < 3; j++) + state[statePointer + j] = state[statePointer + j+1]; + state[statePointer + 3] = tmp; + } + } + return state; + }, + + // galois multiplication of 8 bit characters a and b + galois_multiplication:function(a,b) + { + var p = 0; + for(var counter = 0; counter < 8; counter++) + { + if((b & 1) == 1) + p ^= a; + if(p > 0x100) p ^= 0x100; + var hi_bit_set = (a & 0x80); //keep p 8 bit + a <<= 1; + if(a > 0x100) a ^= 0x100; //keep a 8 bit + if(hi_bit_set == 0x80) + a ^= 0x1b; + if(a > 0x100) a ^= 0x100; //keep a 8 bit + b >>= 1; + if(b > 0x100) b ^= 0x100; //keep b 8 bit + } + return p; + }, + + // galois multipication of the 4x4 matrix + mixColumns:function(state,isInv) + { + var column = []; + /* iterate over the 4 columns */ + for (var i = 0; i < 4; i++) + { + /* construct one column by iterating over the 4 rows */ + for (var j = 0; j < 4; j++) + column[j] = state[(j*4)+i]; + /* apply the mixColumn on one column */ + column = this.mixColumn(column,isInv); + /* put the values back into the state */ + for (var k = 0; k < 4; k++) + state[(k*4)+i] = column[k]; + } + return state; + }, + + // galois multipication of 1 column of the 4x4 matrix + mixColumn:function(column,isInv) + { + var mult = []; + if(isInv) + mult = [14,9,13,11]; + else + mult = [2,1,1,3]; + var cpy = []; + for(var i = 0; i < 4; i++) + cpy[i] = column[i]; + + column[0] = this.galois_multiplication(cpy[0],mult[0]) ^ + this.galois_multiplication(cpy[3],mult[1]) ^ + this.galois_multiplication(cpy[2],mult[2]) ^ + this.galois_multiplication(cpy[1],mult[3]); + column[1] = this.galois_multiplication(cpy[1],mult[0]) ^ + this.galois_multiplication(cpy[0],mult[1]) ^ + this.galois_multiplication(cpy[3],mult[2]) ^ + this.galois_multiplication(cpy[2],mult[3]); + column[2] = this.galois_multiplication(cpy[2],mult[0]) ^ + this.galois_multiplication(cpy[1],mult[1]) ^ + this.galois_multiplication(cpy[0],mult[2]) ^ + this.galois_multiplication(cpy[3],mult[3]); + column[3] = this.galois_multiplication(cpy[3],mult[0]) ^ + this.galois_multiplication(cpy[2],mult[1]) ^ + this.galois_multiplication(cpy[1],mult[2]) ^ + this.galois_multiplication(cpy[0],mult[3]); + return column; + }, + + // applies the 4 operations of the forward round in sequence + round:function(state, roundKey) + { + state = this.subBytes(state,false); + state = this.shiftRows(state,false); + state = this.mixColumns(state,false); + state = this.addRoundKey(state, roundKey); + return state; + }, + + // applies the 4 operations of the inverse round in sequence + invRound:function(state,roundKey) + { + state = this.shiftRows(state,true); + state = this.subBytes(state,true); + state = this.addRoundKey(state, roundKey); + state = this.mixColumns(state,true); + return state; + }, + + /* + * Perform the initial operations, the standard round, and the final operations + * of the forward aes, creating a round key for each round + */ + main:function(state,expandedKey,nbrRounds) + { + state = this.addRoundKey(state, this.createRoundKey(expandedKey,0)); + for (var i = 1; i < nbrRounds; i++) + state = this.round(state, this.createRoundKey(expandedKey,16*i)); + state = this.subBytes(state,false); + state = this.shiftRows(state,false); + state = this.addRoundKey(state, this.createRoundKey(expandedKey,16*nbrRounds)); + return state; + }, + + /* + * Perform the initial operations, the standard round, and the final operations + * of the inverse aes, creating a round key for each round + */ + invMain:function(state, expandedKey, nbrRounds) + { + state = this.addRoundKey(state, this.createRoundKey(expandedKey,16*nbrRounds)); + for (var i = nbrRounds-1; i > 0; i--) + state = this.invRound(state, this.createRoundKey(expandedKey,16*i)); + state = this.shiftRows(state,true); + state = this.subBytes(state,true); + state = this.addRoundKey(state, this.createRoundKey(expandedKey,0)); + return state; + }, + + numberOfRounds:function(size) + { + var nbrRounds; + switch (size) /* set the number of rounds */ + { + case this.keySize.SIZE_128: + nbrRounds = 10; + break; + case this.keySize.SIZE_192: + nbrRounds = 12; + break; + case this.keySize.SIZE_256: + nbrRounds = 14; + break; + default: + return null; + break; + } + return nbrRounds; + }, + + // encrypts a 128 bit input block against the given key of size specified + encrypt:function(input,key,size) + { + var output = []; + var block = []; /* the 128 bit block to encode */ + var nbrRounds = this.numberOfRounds(size); + /* Set the block values, for the block: + * a0,0 a0,1 a0,2 a0,3 + * a1,0 a1,1 a1,2 a1,3 + * a2,0 a2,1 a2,2 a2,3 + * a3,0 a3,1 a3,2 a3,3 + * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 + */ + for (var i = 0; i < 4; i++) /* iterate over the columns */ + for (var j = 0; j < 4; j++) /* iterate over the rows */ + block[(i+(j*4))] = input[(i*4)+j]; + + /* expand the key into an 176, 208, 240 bytes key */ + var expandedKey = this.expandKey(key, size); /* the expanded key */ + /* encrypt the block using the expandedKey */ + block = this.main(block, expandedKey, nbrRounds); + for (var k = 0; k < 4; k++) /* unmap the block again into the output */ + for (var l = 0; l < 4; l++) /* iterate over the rows */ + output[(k*4)+l] = block[(k+(l*4))]; + return output; + }, + + // decrypts a 128 bit input block against the given key of size specified + decrypt:function(input, key, size) + { + var output = []; + var block = []; /* the 128 bit block to decode */ + var nbrRounds = this.numberOfRounds(size); + /* Set the block values, for the block: + * a0,0 a0,1 a0,2 a0,3 + * a1,0 a1,1 a1,2 a1,3 + * a2,0 a2,1 a2,2 a2,3 + * a3,0 a3,1 a3,2 a3,3 + * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 + */ + for (var i = 0; i < 4; i++) /* iterate over the columns */ + for (var j = 0; j < 4; j++) /* iterate over the rows */ + block[(i+(j*4))] = input[(i*4)+j]; + /* expand the key into an 176, 208, 240 bytes key */ + var expandedKey = this.expandKey(key, size); + /* decrypt the block using the expandedKey */ + block = this.invMain(block, expandedKey, nbrRounds); + for (var k = 0; k < 4; k++)/* unmap the block again into the output */ + for (var l = 0; l < 4; l++)/* iterate over the rows */ + output[(k*4)+l] = block[(k+(l*4))]; + return output; + } + }, + /* + * END AES SECTION + */ + + /* + * START MODE OF OPERATION SECTION + */ + //structure of supported modes of operation + modeOfOperation:{ + OFB:0, + CFB:1, + CBC:2 + }, + + // gets a properly padded block + getPaddedBlock: function(bytesIn,start,end,mode) + { + if(end - start > 16) + end = start + 16; + + var array = bytesIn.slice(start, end); + + if (mode == this.modeOfOperation.CBC) + { + var cpad = 16 - array.length; + while(array.length < 16) + { + array.push(cpad); + } + } + + return array; + }, + + /* + * Mode of Operation Encryption + * bytesIn - Input String as array of bytes + * mode - mode of type modeOfOperation + * key - a number array of length 'size' + * size - the bit length of the key + * iv - the 128 bit number array Initialization Vector + */ + encrypt: function (bytesIn, mode, key, size, iv) + { + if(key.length%size) + { + throw 'Key length does not match specified size.'; + } + if(iv.length%16) + { + throw 'iv length must be 128 bits.'; + } + // the AES input/output + var byteArray = []; + var input = []; + var output = []; + var ciphertext = []; + var cipherOut = []; + // char firstRound + var firstRound = true; + if (bytesIn !== null) + { + for (var j = 0;j < Math.ceil(bytesIn.length/16); j++) + { + var start = j*16; + var end = j*16+16; + if(j*16+16 > bytesIn.length) + end = bytesIn.length; + byteArray = this.getPaddedBlock(bytesIn,start,end,mode); + if (mode == this.modeOfOperation.CFB) + { + if (firstRound) + { + output = this.aes.encrypt(iv, key, size); + firstRound = false; + } + else + output = this.aes.encrypt(input, key, size); + for (var i = 0; i < 16; i++) + ciphertext[i] = byteArray[i] ^ output[i]; + for(var k = 0;k < end-start;k++) + cipherOut.push(ciphertext[k]); + input = ciphertext; + } + else if (mode == this.modeOfOperation.OFB) + { + if (firstRound) + { + output = this.aes.encrypt(iv, key, size); + firstRound = false; + } + else + output = this.aes.encrypt(input, key, size); + for (var i = 0; i < 16; i++) + ciphertext[i] = byteArray[i] ^ output[i]; + for(var k = 0;k < end-start;k++) + cipherOut.push(ciphertext[k]); + input = output; + } + else if (mode == this.modeOfOperation.CBC) + { + for (var i = 0; i < 16; i++) + input[i] = byteArray[i] ^ ((firstRound) ? iv[i] : ciphertext[i]); + firstRound = false; + ciphertext = this.aes.encrypt(input, key, size); + // always 16 bytes because of the padding for CBC + for(var k = 0;k < 16;k++) + cipherOut.push(ciphertext[k]); + } + } + } + return {mode:mode,originalsize:bytesIn.length,cipher:cipherOut}; + }, + + /* + * Mode of Operation Decryption + * cipherIn - Encrypted String as array of bytes + * originalsize - The unencrypted string length - required for CBC + * mode - mode of type modeOfOperation + * key - a number array of length 'size' + * size - the bit length of the key + * iv - the 128 bit number array Initialization Vector + */ + decrypt:function(cipherIn,originalsize,mode,key,size,iv) + { + if(key.length%size) + { + throw 'Key length does not match specified size.'; + return null; + } + if(iv.length%16) + { + throw 'iv length must be 128 bits.'; + } + // the AES input/output + var ciphertext = []; + var input = []; + var output = []; + var byteArray = []; + var bytesOut = []; + // char firstRound + var firstRound = true; + if (cipherIn !== null) + { + for (var j = 0;j < Math.ceil(cipherIn.length/16); j++) + { + var start = j*16; + var end = j*16+16; + if(j*16+16 > cipherIn.length) + end = cipherIn.length; + ciphertext = this.getPaddedBlock(cipherIn,start,end,mode); + if (mode == this.modeOfOperation.CFB) + { + if (firstRound) + { + output = this.aes.encrypt(iv, key, size); + firstRound = false; + } + else + output = this.aes.encrypt(input, key, size); + for (i = 0; i < 16; i++) + byteArray[i] = output[i] ^ ciphertext[i]; + for(var k = 0;k < end-start;k++) + bytesOut.push(byteArray[k]); + input = ciphertext; + } + else if (mode == this.modeOfOperation.OFB) + { + if (firstRound) + { + output = this.aes.encrypt(iv, key, size); + firstRound = false; + } + else + output = this.aes.encrypt(input, key, size); + for (i = 0; i < 16; i++) + byteArray[i] = output[i] ^ ciphertext[i]; + for(var k = 0;k < end-start;k++) + bytesOut.push(byteArray[k]); + input = output; + } + else if(mode == this.modeOfOperation.CBC) + { + output = this.aes.decrypt(ciphertext, key, size); + for (i = 0; i < 16; i++) + byteArray[i] = ((firstRound) ? iv[i] : input[i]) ^ output[i]; + firstRound = false; + if (originalsize < end) + for(var k = 0;k < originalsize-start;k++) + bytesOut.push(byteArray[k]); + else + for(var k = 0;k < end-start;k++) + bytesOut.push(byteArray[k]); + input = ciphertext; + } + } + } + return bytesOut; + } + /* + * END MODE OF OPERATION SECTION + */ +}; + diff --git a/javascript/cryptoHelpers.js b/javascript/cryptoHelpers.js new file mode 100644 index 0000000..a77ee42 --- /dev/null +++ b/javascript/cryptoHelpers.js @@ -0,0 +1,185 @@ +/* + * cryptoHelpers.js: implements AES - Advanced Encryption Standard + * from the SlowAES project, http://code.google.com/p/slowaes/ + * + * Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ), + * Mark Percival ( http://mpercival.com ), + * Johan Sundstrom ( http://ecmanaut.blogspot.com ), + * John Resig ( http://ejohn.org ) + * + * Licensed under the Apache License, Version 2.0 + * http://www.apache.org/licenses/ + */ + + + +var cryptoHelpers = { + + // encodes a unicode string to UTF8 (8 bit characters are critical to AES functioning properly) + encode_utf8:function(s) + { + try{return unescape(encodeURIComponent(s));} + catch(e){throw 'error during utf8 encoding: cryptoHelpers.encode_utf8.';} + }, + + + // decodes a UTF8 string back to unicode + decode_utf8:function(s) + { + try{return decodeURIComponent(escape(s));} + catch(e){throw('error during utf8 decoding: cryptoHelpers.decode_utf8.');} + }, + + //convert a number array to a hex string + toHex:function() + { + var array = []; + if(arguments.length == 1 && arguments[0].constructor == Array) + array = arguments[0]; + else + array = arguments; + var ret = ''; + for(var i = 0;i < array.length;i++) + ret += (array[i] < 16 ? '0' : '') + array[i].toString(16); + return ret.toLowerCase(); + }, + + //convert a hex string to a number array + toNumbers:function(s) + { + var ret = []; + s.replace(/(..)/g,function(s){ + ret.push(parseInt(s,16)); + }); + return ret; + }, + + // get a random number in the range [min,max] + getRandom:function(min,max) + { + if(min === null) + min = 0; + if(max === null) + max = 1; + return Math.floor(Math.random()*(max+1)) + min; + }, + + generateSharedKey:function(len) + { + if(len === null) + len = 16; + var key = []; + for(var i = 0; i < len*2; i++) + key.push(this.getRandom(0,255)); + return key; + }, + + generatePrivateKey:function(s,size) + { + var sha = jsHash.sha2.arr_sha256(s); + return sha.slice(0,size); + }, + + convertStringToByteArray: function(s) + { + var byteArray = []; + for(var i = 0;i < s.length;i++) + { + byteArray.push(s.charCodeAt(i)); + } + return byteArray; + }, + + convertByteArrayToString: function(byteArray) + { + var s = ''; + for(var i = 0;i < byteArray.length;i++) + { + s += String.fromCharCode(byteArray[i]); + } + return s; + }, + + base64: { + // Takes a Nx16x1 byte array and converts it to Base64 + + chars: [ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/', + '=' // for decoding purposes + ], + + encode_line: function(flatArr){ + var b64 = ''; + + for (var i = 0; i < flatArr.length; i += 3){ + b64 += this.chars[flatArr[i] >> 2]; + b64 += this.chars[((flatArr[i] & 3) << 4) | (flatArr[i + 1] >> 4)]; + if (!(flatArr[i + 1] === null)){ + b64 += this.chars[((flatArr[i + 1] & 15) << 2) | (flatArr[i + 2] >> 6)]; + }else{ + b64 += '='; + } + if (!(flatArr[i + 2] === null)){ + b64 += this.chars[flatArr[i + 2] & 63]; + }else{ + b64 += '='; + } + } + return b64; + }, + + encode: function(flatArr) + { + var b64 = this.encode_line(flatArr); + // OpenSSL is super particular about line breaks + var broken_b64 = b64.slice(0, 64) + '\n'; + for (var i = 1; i < (Math.ceil(b64.length / 64)); i++) + { + broken_b64 += b64.slice(i * 64, i * 64 + 64) + (Math.ceil(b64.length / 64) == i + 1 ? '': '\n'); + } + return broken_b64; + }, + + decode: function(string) + { + string = string.replace(/[\r\n\t ]+/g, '') + '===='; // drop all whitespaces and pad with '=' (end of b64 marker) + var flatArr = []; + var c = []; + //var b = []; + for (var i = 0; true ; i = i + 4){ + c[0] = this.chars.indexOf(string.charAt(i)); + if(c[0] == 64){ + return flatArr; + } + c[1] = this.chars.indexOf(string.charAt(i + 1)); + c[2] = this.chars.indexOf(string.charAt(i + 2)); + c[3] = this.chars.indexOf(string.charAt(i + 3)); + + if( + (c[0] < 0) || // char1 is wrong + (c[1] < 0) || (c[1] == 64) || // char2 is wrong + (c[2] < 0) || // char3 is neither an valid char nor '=' + (c[3] < 0) // char4 is neither an valid char nor '=' + ){ + throw 'error during base64 decoding at pos '+i+': cryptoHelpers.base64.decode.'; + } + + flatArr.push((c[0] << 2) | (c[1] >> 4)); + if(c[2] >= 0 && c[2] < 64){ + flatArr.push(((c[1] & 15) << 4) | (c[2] >> 2)); + if(c[3] >= 0 && c[2] < 64){ + flatArr.push(((c[2] & 3) << 6) | c[3]); + } + } + } + } + } +}; + diff --git a/javascript/jsPacker/build-pack-hash.sh b/javascript/jsPacker/build-pack-hash.sh index 45e841a..adeaefe 100644 --- a/javascript/jsPacker/build-pack-hash.sh +++ b/javascript/jsPacker/build-pack-hash.sh @@ -1,4 +1,4 @@ #!/bin/bash -cat ../SHA1.js ../MD5.js > hash.js +cat ../aes.js ../cryptoHelpers.js ../SHA1.js ../MD5.js > hash.js perl jsPacker.pl -fsq -e62 -i hash.js -o hash.min.js rm hash.js diff --git a/javascript/jsPacker/hash.min.js b/javascript/jsPacker/hash.min.js index a34be63..d8dbba6 100644 --- a/javascript/jsPacker/hash.min.js +++ b/javascript/jsPacker/hash.min.js @@ -1 +1 @@ -eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('l 41(K){l S(n,s){e 2x=(n<>>(32-s));f 2x};l 3Z(1K){e 1g="";e i;e 2e;e 2d;J(i=0;i<=6;i+=2){2e=(1K>>>(i*4+4))&2c;2d=(1K>>>(i*4))&2c;1g+=2e.1P(16)+2d.1P(16)}f 1g};l 1f(1K){e 1g="";e i;e v;J(i=7;i>=0;i--){v=(1K>>>(i*4))&2c;1g+=v.1P(16)}f 1g};l 1L(u){u=u.2p(/\\r\\n/g,"\\n");e w="";J(e n=0;n2o)&&(c<2n)){w+=O.N((c>>6)|2m);w+=O.N((c&1b)|V)}1c{w+=O.N((c>>12)|2l);w+=O.N(((c>>6)&1b)|V);w+=O.N((c&1b)|V)}}f w};e 1I;e i,j;e W=2w 1M(3Y);e 1H=2j;e 1G=2i;e 1F=2h;e 1E=2g;e 1D=3X;e A,B,C,D,E;e L;K=1L(K);e P=K.U;e T=2w 1M();J(i=0;i>>29);T.1J((P<<3)&R);J(1I=0;1I>>(32-2b))}l h(1V,1U){e 1T,1S,1e,1d,1a;1e=(1V&2a);1d=(1U&2a);1T=(1V&1R);1S=(1U&1R);1a=(1V&2u)+(1U&2u);Z(1T&1S){f(1a^2a^1e^1d)}Z(1T|1S){Z(1a&1R){f(1a^3L^1e^1d)}1c{f(1a^1R^1e^1d)}}1c{f(1a^1e^1d)}}l F(x,y,z){f(x&y)|((~x)&z)}l G(x,y,z){f(x&z)|(y&(~z))}l H(x,y,z){f(x^y^z)}l I(x,y,z){f(y^(x|(~z)))}l t(a,b,c,d,x,s,Y){a=h(a,h(h(F(b,c,d),x),Y));f h(1C(a,s),b)};l q(a,b,c,d,x,s,Y){a=h(a,h(h(G(b,c,d),x),Y));f h(1C(a,s),b)};l o(a,b,c,d,x,s,Y){a=h(a,h(h(H(b,c,d),x),Y));f h(1C(a,s),b)};l m(a,b,c,d,x,s,Y){a=h(a,h(h(I(b,c,d),x),Y));f h(1C(a,s),b)};l 2k(u){e 18;e 1A=u.U;e 28=1A+8;e 2s=(28-(28%2t))/2t;e 1Q=(2s+1)*16;e X=1M(1Q-1);e 1B=0;e Q=0;2r(Q<1A){18=(Q-(Q%4))/4;1B=(Q%4)*8;X[18]=(X[18]|(u.M(Q)<<1B));Q++}18=(Q-(Q%4))/4;1B=(Q%4)*8;X[18]=X[18]|(2q<<1B);X[1Q-2]=1A<<3;X[1Q-1]=1A>>>29;f X};l 1h(1z){e 1N="",1O="",27,1y;J(1y=0;1y<=3;1y++){27=(1z>>>(1y*8))&3K;1O="0"+27.1P(16);1N=1N+1O.3J(1O.U-2,2)}f 1N};l 1L(u){u=u.2p(/\\r\\n/g,"\\n");e w="";J(e n=0;n2o)&&(c<2n)){w+=O.N((c>>6)|2m);w+=O.N((c&1b)|V)}1c{w+=O.N((c>>12)|2l);w+=O.N(((c>>6)&1b)|V);w+=O.N((c&1b)|V)}}f w};e x=1M();e k,26,25,1Z,1Y,a,b,c,d;e 1x=7,1w=12,1v=17,1u=22;e 1t=5,1s=9,1r=14,1q=20;e 1p=4,1o=11,1n=16,1m=23;e 1l=6,1k=10,1j=15,1i=21;u=1L(u);x=2k(u);a=2j;b=2i;c=2h;d=2g;J(k=0;k35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('18 aI={2O:{7j:{8L:16,8K:24,86:32},7K:[1W,3z,4D,5g,6g,4B,5A,1U,4W,1Y,5e,3s,3O,3j,2E,56,6d,69,5Y,2C,2r,5C,3q,3P,5z,2d,4e,4s,3L,3I,27,44,5S,3f,5Q,3A,2H,4z,5l,2p,3C,5T,5o,5U,3l,2F,4A,4u,2f,5Z,4x,4l,3V,4T,5b,2l,4v,6u,1x,3Q,5n,5L,4N,5h,4w,1Q,4U,4Z,1J,3x,6k,4O,52,5M,6f,2n,5K,5X,2x,4Q,4F,4o,6x,5W,2e,6h,5x,3o,2w,1V,4c,25,26,3Z,3v,5p,4J,1T,3H,4h,5k,2z,2y,4q,5E,5m,2b,3m,3Y,3T,1S,68,5j,5y,2v,5O,3K,5P,6t,4i,2t,3F,3N,5c,2a,5V,3g,47,4m,3E,3r,3R,5i,2m,3w,57,6e,3e,6p,5d,54,4G,58,5B,3y,5N,4H,46,4V,6r,6c,4f,6m,6i,3G,4Y,4K,2g,5a,62,6j,3U,28,3X,3p,50,6s,51,2q,2A,4d,6o,1R,5v,2j,4E,4j,3M,3t,3k,1P,61,53,3d,2G,3u,4L,4a,4C,43,4P,2u,65,55,1Z,3S,6v,67,66,2c,2s,5r,2i,5H,5F,2o,4p,4R,6q,4X,3b,2h,6n,5J,49,6w,2B,2D,5D,5R,4g,5q,1X,6b,3h,48,4S,5G,5f,3i,3J,2k,5u,3D,5s,4k,45,3n,3B,4n,6a,4t,5t,5I,5w,4M,41,42,4I,4r,4y,2L,4b,6l,3c,3W],8S:[52,4w,2w,61,4W,2H,5T,6t,5w,2v,5y,6b,5N,3g,3j,4h,3z,5X,25,69,5u,2x,5V,5s,3C,3J,5k,3w,6e,4K,4k,1V,6l,5g,2k,3U,67,2q,4x,5d,6i,3Z,5v,5a,41,2r,4l,53,2u,3S,4t,2h,3B,3i,6s,4N,56,3o,4e,3p,3k,4p,4o,1Z,27,48,49,54,4g,42,4S,3W,2d,3I,51,2p,4G,4C,3F,3K,2G,6q,6n,3Y,3f,5W,5R,3N,2g,4u,6m,5D,3e,1P,5P,4Q,6c,2F,2E,6x,6a,2t,2A,3X,5l,2j,3v,5b,3G,2n,5E,50,4J,4U,3D,5O,6d,4z,2L,2b,5q,4s,2o,5J,1Y,3r,4R,4B,28,1R,5G,4I,4H,5e,46,4a,2m,6g,5p,45,3P,66,4M,5B,4T,4d,2i,4V,4j,5z,2D,4q,3Q,5m,3t,2s,6v,5h,4n,3x,3q,5U,4Z,3l,1X,5K,1U,5t,5A,5S,6o,6w,3H,3V,4c,1J,6h,3u,4X,5F,2c,47,4E,2e,2l,62,44,3O,55,4m,6k,4L,5H,5r,68,2y,4f,4v,5Z,4A,5x,6u,2a,5C,5L,1x,3R,5i,3y,5j,3m,3d,58,3b,26,5I,4y,5o,43,1S,5Q,5Y,3L,1T,4O,6j,5M,2z,4P,6r,4i,4b,3M,5n,3c,3T,1Q,4F,4r,2B,57,3s,2f,6p,65,4D,6f,3A,3h,5f,4Y,1W,3n,5c,3E,2C],8Y:1e(1K){18 c=1K[0];1c(18 i=0;i<3;i++)1K[i]=1K[i+1];1K[3]=c;1d 1K},8X:[1P,1Y,2b,2f,2u,2a,2e,2v,1x,1J,2H,2G,2F,2E,2z,2l,2x,2g,2t,1W,2c,2m,2D,2w,2d,2n,2C,2r,1T,1U,1R,25,27,2j,2A,2o,2B,2q,1S,1Z,26,2k,2y,2h,2p,1Q,1X,28,2i,2s,1V,1P,1Y,2b,2f,2u,2a,2e,2v,1x,1J,2H,2G,2F,2E,2z,2l,2x,2g,2t,1W,2c,2m,2D,2w,2d,2n,2C,2r,1T,1U,1R,25,27,2j,2A,2o,2B,2q,1S,1Z,26,2k,2y,2h,2p,1Q,1X,28,2i,2s,1V,1P,1Y,2b,2f,2u,2a,2e,2v,1x,1J,2H,2G,2F,2E,2z,2l,2x,2g,2t,1W,2c,2m,2D,2w,2d,2n,2C,2r,1T,1U,1R,25,27,2j,2A,2o,2B,2q,1S,1Z,26,2k,2y,2h,2p,1Q,1X,28,2i,2s,1V,1P,1Y,2b,2f,2u,2a,2e,2v,1x,1J,2H,2G,2F,2E,2z,2l,2x,2g,2t,1W,2c,2m,2D,2w,2d,2n,2C,2r,1T,1U,1R,25,27,2j,2A,2o,2B,2q,1S,1Z,26,2k,2y,2h,2p,1Q,1X,28,2i,2s,1V,1P,1Y,2b,2f,2u,2a,2e,2v,1x,1J,2H,2G,2F,2E,2z,2l,2x,2g,2t,1W,2c,2m,2D,2w,2d,2n,2C,2r,1T,1U,1R,25,27,2j,2A,2o,2B,2q,1S,1Z,26,2k,2y,2h,2p,1Q,1X,28,2i,2s,1V],aH:[6x,2b,2f,50,2u,3X,3E,6w,2a,6u,4Y,3W,3V,4Z,6v,3D,2e,4V,6s,3A,3B,6r,4U,3S,4W,3U,3C,2H,6t,28,3T,4X,2v,41,3w,6m,6n,26,3Z,53,3Y,52,6l,3u,3v,6k,51,2g,3y,6o,54,2h,42,2w,2G,3x,6q,27,2i,56,55,43,3z,6p,1x,69,4Q,4g,4f,4R,6a,3J,6c,3K,2k,4T,4S,2l,3L,6b,4O,4e,3I,67,68,3H,4d,4P,4b,4N,66,3F,3G,65,2t,4c,44,2q,6e,2c,3M,6d,2p,45,4J,47,2d,6f,2F,3N,46,4K,6j,3Q,2j,4M,2s,4a,3R,6i,3P,6g,4L,49,48,2r,6h,3O,1J,58,5H,1X,3r,5G,57,4u,5a,4w,2L,5I,5J,1Y,4v,5b,5M,25,4z,5d,2y,4A,3t,2D,3s,5K,2x,4y,4x,5c,5L,1Z,3o,5C,5i,4G,4F,5j,5D,3n,5F,3p,4H,2z,5k,4I,3q,5E,5g,4E,3m,2C,5B,3l,4D,5h,4B,5f,5A,3k,1W,2B,5e,4C,5u,4r,1S,5P,5Q,1R,2m,5v,4p,5t,5O,1P,1Q,5N,5s,4q,3c,5R,5w,2o,2n,5x,5S,3b,2E,3d,4s,5z,5y,4t,3e,5T,62,3i,4n,5r,2A,4o,3j,61,1V,5Y,5p,4m,4l,5q,5Z,1U,4h,5m,5V,3f,3g,5U,5l,4i,5n,4k,1T,5W,5X,3h,4j,5o],aG:[6x,5J,50,5b,3E,2L,3X,4w,3V,1J,3D,1X,4Y,57,6u,5G,4W,2y,2H,2D,3T,4z,28,25,3B,3s,3S,4y,6s,5L,4V,5c,3y,1W,2h,4C,2G,5A,2w,5f,55,5g,6p,2C,2i,4D,27,3l,3Y,4F,3u,3n,51,5i,6k,5C,6n,5F,53,2z,3w,3q,41,4I,44,4l,2c,1U,2p,5p,6d,5Y,2F,62,4K,5r,2d,3j,47,4o,3P,3g,49,4i,6h,5V,2r,5m,2s,5n,6i,5W,2j,4j,3Q,3h,4O,5y,67,5T,4d,4s,3H,3d,3G,3c,4c,2o,66,5S,4N,5x,6c,5Q,4T,5v,3L,1S,2l,4r,4f,4p,3J,1P,4Q,5s,69,5N,5u,4S,5P,6b,2m,2k,1R,3K,1Q,1x,4q,4g,5O,6a,5t,4R,2E,68,5z,4P,3e,3I,4t,4e,2n,4b,3b,3F,5w,2t,5R,65,4h,48,3f,3O,5l,4L,5U,6g,5X,6j,5o,4M,1T,3R,4k,4a,1V,3M,4m,45,5Z,6e,5q,2q,2A,4J,61,6f,4n,46,3i,3N,3o,3v,4G,2g,5D,6l,5j,52,5k,2v,5E,6m,4H,3Z,3p,26,4B,42,3k,3x,5e,54,2B,6o,5B,6q,5h,56,3m,3z,4E,43,5M,6t,5d,4X,3t,3C,4A,3U,4x,2e,1Z,3A,2x,4U,5K,6r,5a,2u,5I,6w,4v,2f,1Y,2b,3r,2a,4u,3W,5H,6v,58,4Z],aF:[6x,4w,6u,1J,6s,4y,2H,4z,6n,4I,6k,4F,2G,4C,6p,4D,6c,4r,69,4p,66,2o,67,4s,2F,4o,6d,4l,6h,4i,6i,4j,5M,3U,5K,2e,5H,3W,5I,2f,5B,43,2B,42,5D,2g,5E,3Z,2E,4e,5R,4b,5O,4g,5P,2k,5X,4a,5U,48,5Z,45,61,46,56,3m,54,3k,52,3o,2v,3p,4X,3t,4U,1Z,4Z,3r,2u,1Y,4M,1T,4L,3f,2q,1V,4J,3i,4P,3e,2t,3b,4R,1Q,4S,1R,2z,3w,5i,3u,5f,3y,5g,27,5b,3E,57,3D,5c,3B,2y,28,5r,2d,5p,2c,5m,3P,5n,3Q,5v,3L,5s,3J,5x,3G,5y,3H,3R,5o,3O,5l,3M,5q,3N,2A,3I,5z,3F,5w,1x,5t,3K,5u,3z,5h,3x,5e,3v,5j,26,5k,3C,5d,3A,2x,2a,58,2b,5a,3j,4K,1U,2p,3g,2r,3h,2s,1S,4T,1P,4Q,3c,4N,3d,4O,3q,53,3n,51,1W,2w,3l,55,2L,50,1X,4Y,3s,4V,25,4W,2l,5Q,4f,5N,4c,5S,4d,5T,47,62,44,5Y,49,5V,2j,5W,3X,5J,3V,5G,3S,5L,3T,2D,41,5F,3Y,5C,2h,5A,2i,2C,4t,68,2n,65,4q,6a,2m,6b,4k,6j,4h,6g,4m,6e,4n,6f,4A,6t,4x,6r,4u,6v,4v,6w,4E,6q,4B,6o,4G,6l,4H,6m],aE:[6x,5a,3W,1X,4U,5L,28,4A,3v,4F,53,5E,2i,3m,6o,5f,4b,3c,67,5z,3L,2m,4R,5N,2s,5X,3O,4i,6e,5p,47,3i,5g,6q,3k,2h,5D,51,4I,26,4x,3B,2D,4X,2L,2f,58,6u,1V,44,5r,6f,4j,3R,5U,2r,5Q,4S,4q,3J,5w,66,3d,4e,49,3f,6j,5n,3N,4o,2p,5Z,4P,5T,3G,2n,69,5t,2k,1S,6m,2z,3Y,3o,2w,2B,3z,4D,3D,4u,2u,5J,3U,25,6s,2x,1P,4g,5u,6c,4t,3H,5S,2t,61,4K,4l,3M,5m,6g,1T,2j,5d,2H,3s,2e,5G,4Z,4v,3E,4C,3x,5B,55,3p,41,5i,6l,5l,6h,3h,4a,62,4J,4m,2c,4s,3I,5R,4N,1Q,4f,5v,6b,3q,3Z,5j,6k,4B,3y,2C,56,5H,4Y,4w,2b,2y,6t,1Z,3S,6a,5s,2l,1R,4O,2E,3F,2o,2d,4n,2q,5Y,48,3g,6i,5o,3T,3t,6r,5c,2a,1J,50,5I,54,5A,27,4E,6n,5k,2g,3n,1Y,3X,57,6v,4y,3A,5M,4W,5C,52,4H,3w,5h,6p,1W,42,5x,65,3e,4d,5P,4T,4p,1x,4k,3Q,5V,4L,1U,45,2A,2F,43,3l,2G,5e,3u,4G,2v,5F,4V,5K,3C,4z,6w,5b,3V,3r,6d,5q,46,3j,4M,5W,3P,4h,3K,4r,4Q,5O,4c,3b,68,5y],aD:[6x,5I,4Z,57,3C,25,3S,4x,42,4C,27,3m,51,5j,6m,5F,4J,5r,6d,5Z,2j,4k,3O,3g,3G,3b,4e,4s,6a,5N,4T,5u,3c,3F,4t,4d,5O,69,5v,4S,2A,4K,5Y,6e,4j,4a,3f,3P,4B,2h,3l,3z,5i,52,5E,6n,5J,6w,58,4Y,3t,28,4y,2e,3k,3y,4D,43,5C,6l,5k,53,5b,2u,5H,6u,4A,3T,3s,3A,2o,4b,3e,3H,5t,4Q,5Q,6b,61,2F,5p,2q,3h,3R,4h,49,6f,62,2p,5q,3Q,1T,48,4i,4c,2n,3I,3d,4R,5s,6c,5P,50,5a,6v,5G,3U,4z,3B,1Z,3x,1W,2i,4E,6k,5D,2v,2z,3N,3j,44,4m,6i,5X,4L,5m,4N,5w,68,5T,4g,4p,3L,1R,3X,4v,2a,1X,4X,2y,6s,5K,6o,5A,55,5h,3u,3o,3Z,4I,2B,2G,5g,56,3n,3v,4H,41,4w,2f,3r,3D,5d,4W,5L,6r,5x,2t,2E,67,4q,4f,1S,3K,3i,2d,4l,45,5W,6j,5l,2r,5S,65,5z,4O,1Q,3J,4r,2k,4n,47,1U,3M,5n,4M,5U,6h,5e,2w,2C,6q,4F,2g,3p,3w,2L,2b,4u,3V,5M,2H,5c,4U,3E,1Y,3W,1J,6t,2D,4V,2x,54,5f,6p,5B,3Y,4G,26,3q,46,4o,2c,1V,2s,5o,6g,5V,66,5R,4P,5y,1x,1P,2l,2m],aC:[6x,6w,6v,6u,6t,2H,6s,6r,6q,6p,2G,6o,6n,6m,6l,6k,6j,6i,6h,6g,2F,6f,6e,6d,6c,6b,6a,69,68,67,66,65,62,61,5Z,5Y,5X,5W,5V,5U,2E,5T,5S,5R,5Q,5P,5O,5N,5M,2D,5L,5K,5J,5I,5H,5G,5F,5E,5D,5C,5B,2C,5A,2B,5z,5y,5x,5w,5v,5u,5t,5s,5r,2A,5q,5p,5o,5n,5m,5l,2z,5k,5j,5i,5h,5g,5f,5e,5d,2y,5c,2x,5b,5a,58,57,56,55,2w,54,53,2v,52,51,50,2u,4Z,4Y,4X,4W,4V,4U,4T,4S,4R,4Q,4P,4O,4N,2t,4M,2s,2r,4L,4K,4J,2q,2p,4I,4H,4G,4F,4E,4D,4C,4B,4A,4z,4y,4x,4w,4v,4u,1J,4t,4s,2o,2n,4r,2m,4q,4p,4o,4n,4m,4l,4k,4j,4i,4h,2l,2k,4g,4f,4e,4d,4c,4b,4a,2j,49,48,47,46,45,44,43,2i,2h,42,41,3Z,2g,3Y,3X,2f,3W,3V,3U,3T,3S,2e,3R,3Q,3P,3O,2d,3N,3M,2c,3L,3K,1x,3J,3I,3H,3G,3F,3E,2b,2a,3D,3C,28,3B,3A,3z,27,3y,3x,3w,26,3v,3u,3t,25,3s,1Z,2L,1Y,3r,1X,3q,3p,3o,3n,3m,3l,1W,3k,3j,3i,1V,1U,1T,3h,3g,3f,3e,3d,3c,3b,1S,1R,1Q,1P],8V:1e(1K,8W){1K=1a.8Y(1K);1c(18 i=0;i<4;++i)1K[i]=1a.7K[1K[i]];1K[0]=1K[0]^1a.8X[8W];1d 1K},85:1e(1k,1g){18 89=(16*(1a.7I(1g)+1));18 34=0;18 8U=1;18 t=[];18 1m=[];1c(18 i=0;i<89;i++)1m[i]=0;1c(18 j=0;j<1g;j++)1m[j]=1k[j];34+=1g;7r(34<89){1c(18 k=0;k<4;k++)t[k]=1m[(34-4)+k];1f(34%1g==0)t=1a.8V(t,8U++);1f(1g==1a.7j.86&&((34%1g)==16))1c(18 l=0;l<4;l++)t[l]=1a.7K[t[l]];1c(18 m=0;m<4;m++){1m[34]=1m[34-1g]^t[m];34++}}1d 1m},6D:1e(1b,31){1c(18 i=0;i<16;i++)1b[i]^=31[i];1d 1b},6C:1e(1m,8T){18 31=[];1c(18 i=0;i<4;i++)1c(18 j=0;j<4;j++)31[j*4+i]=1m[8T+i*4+j];1d 31},7k:1e(1b,2V){1c(18 i=0;i<16;i++)1b[i]=2V?1a.8S[1b[i]]:1a.7K[1b[i]];1d 1b},7l:1e(1b,2V){1c(18 i=0;i<4;i++)1b=1a.8R(1b,i*4,i,2V);1d 1b},8R:1e(1b,33,8Q,2V){1c(18 i=0;i<8Q;i++){1f(2V){18 7J=1b[33+3];1c(18 j=3;j>0;j--)1b[33+j]=1b[33+j-1];1b[33]=7J}1n{18 7J=1b[33];1c(18 j=0;j<3;j++)1b[33+j]=1b[33+j+1];1b[33+3]=7J}}1d 1b},1z:1e(a,b){18 p=0;1c(18 88=0;88<8;88++){1f((b&1)==1)p^=a;1f(p>3a)p^=3a;18 8P=(a&1x);a<<=1;1f(a>3a)a^=3a;1f(8P==1x)a^=1J;1f(a>3a)a^=3a;b>>=1;1f(b>3a)b^=3a;}1d p},87:1e(1b,2V){18 2J=[];1c(18 i=0;i<4;i++){1c(18 j=0;j<4;j++)2J[j]=1b[(j*4)+i];2J=1a.8O(2J,2V);1c(18 k=0;k<4;k++)1b[(k*4)+i]=2J[k]}1d 1b},8O:1e(2J,2V){18 1q=[];1f(2V)1q=[14,9,13,11];1n 1q=[2,1,1,3];18 1s=[];1c(18 i=0;i<4;i++)1s[i]=2J[i];2J[0]=1a.1z(1s[0],1q[0])^1a.1z(1s[3],1q[1])^1a.1z(1s[2],1q[2])^1a.1z(1s[1],1q[3]);2J[1]=1a.1z(1s[1],1q[0])^1a.1z(1s[0],1q[1])^1a.1z(1s[3],1q[2])^1a.1z(1s[2],1q[3]);2J[2]=1a.1z(1s[2],1q[0])^1a.1z(1s[1],1q[1])^1a.1z(1s[0],1q[2])^1a.1z(1s[3],1q[3]);2J[3]=1a.1z(1s[3],1q[0])^1a.1z(1s[2],1q[1])^1a.1z(1s[1],1q[2])^1a.1z(1s[0],1q[3]);1d 2J},8N:1e(1b,31){1b=1a.7k(1b,2N);1b=1a.7l(1b,2N);1b=1a.87(1b,2N);1b=1a.6D(1b,31);1d 1b},8M:1e(1b,31){1b=1a.7l(1b,37);1b=1a.7k(1b,37);1b=1a.6D(1b,31);1b=1a.87(1b,37);1d 1b},8J:1e(1b,1m,1D){1b=1a.6D(1b,1a.6C(1m,0));1c(18 i=1;i<1D;i++)1b=1a.8N(1b,1a.6C(1m,16*i));1b=1a.7k(1b,2N);1b=1a.7l(1b,2N);1b=1a.6D(1b,1a.6C(1m,16*1D));1d 1b},8I:1e(1b,1m,1D){1b=1a.6D(1b,1a.6C(1m,16*1D));1c(18 i=1D-1;i>0;i--)1b=1a.8M(1b,1a.6C(1m,16*i));1b=1a.7l(1b,37);1b=1a.7k(1b,37);1b=1a.6D(1b,1a.6C(1m,0));1d 1b},7I:1e(1g){18 1D;8m(1g){6A 1a.7j.8L:1D=10;36;6A 1a.7j.8K:1D=12;36;6A 1a.7j.86:1D=14;36;aB:1d 2Y;36}1d 1D},2P:1e(1r,1k,1g){18 1j=[];18 2U=[];18 1D=1a.7I(1g);1c(18 i=0;i<4;i++)1c(18 j=0;j<4;j++)2U[(i+(j*4))]=1r[(i*4)+j];18 1m=1a.85(1k,1g);2U=1a.8J(2U,1m,1D);1c(18 k=0;k<4;k++)1c(18 l=0;l<4;l++)1j[(k*4)+l]=2U[(k+(l*4))];1d 1j},81:1e(1r,1k,1g){18 1j=[];18 2U=[];18 1D=1a.7I(1g);1c(18 i=0;i<4;i++)1c(18 j=0;j<4;j++)2U[(i+(j*4))]=1r[(i*4)+j];18 1m=1a.85(1k,1g);2U=1a.8I(2U,1m,1D);1c(18 k=0;k<4;k++)1c(18 l=0;l<4;l++)1j[(k*4)+l]=2U[(k+(l*4))];1d 1j}},38:{82:0,83:1,7H:2},84:1e(2Z,1G,1C,1I){1f(1C-1G>16)1C=1G+16;18 2M=2Z.7B(1G,1C);1f(1I==1a.38.7H){18 8H=16-2M.1h;7r(2M.1h<16){2M.1o(8H)}}1d 2M},2P:1e(2Z,1I,1k,1g,2I){1f(1k.1h%1g){6B\'8G 1h 8F 8E 8D 8C 1g.\'}1f(2I.1h%16){6B\'2I 1h 8B 8A 2Q 8z.\'}18 1p=[];18 1r=[];18 1j=[];18 1B=[];18 7i=[];18 1H=37;1f(2Z!==2Y){1c(18 j=0;j<6I.7A(2Z.1h/16);j++){18 1G=j*16;18 1C=j*16+16;1f(j*16+16>2Z.1h)1C=2Z.1h;1p=1a.84(2Z,1G,1C,1I);1f(1I==1a.38.83){1f(1H){1j=1a.2O.2P(2I,1k,1g);1H=2N}1n 1j=1a.2O.2P(1r,1k,1g);1c(18 i=0;i<16;i++)1B[i]=1p[i]^1j[i];1c(18 k=0;k<1C-1G;k++)7i.1o(1B[k]);1r=1B}1n 1f(1I==1a.38.82){1f(1H){1j=1a.2O.2P(2I,1k,1g);1H=2N}1n 1j=1a.2O.2P(1r,1k,1g);1c(18 i=0;i<16;i++)1B[i]=1p[i]^1j[i];1c(18 k=0;k<1C-1G;k++)7i.1o(1B[k]);1r=1j}1n 1f(1I==1a.38.7H){1c(18 i=0;i<16;i++)1r[i]=1p[i]^((1H)?2I[i]:1B[i]);1H=2N;1B=1a.2O.2P(1r,1k,1g);1c(18 k=0;k<16;k++)7i.1o(1B[k])}}}1d{1I:1I,7G:2Z.1h,aA:7i}},81:1e(6L,7G,1I,1k,1g,2I){1f(1k.1h%1g){6B\'8G 1h 8F 8E 8D 8C 1g.\';1d 2Y}1f(2I.1h%16){6B\'2I 1h 8B 8A 2Q 8z.\'}18 1B=[];18 1r=[];18 1j=[];18 1p=[];18 6K=[];18 1H=37;1f(6L!==2Y){1c(18 j=0;j<6I.7A(6L.1h/16);j++){18 1G=j*16;18 1C=j*16+16;1f(j*16+16>6L.1h)1C=6L.1h;1B=1a.84(6L,1G,1C,1I);1f(1I==1a.38.83){1f(1H){1j=1a.2O.2P(2I,1k,1g);1H=2N}1n 1j=1a.2O.2P(1r,1k,1g);1c(i=0;i<16;i++)1p[i]=1j[i]^1B[i];1c(18 k=0;k<1C-1G;k++)6K.1o(1p[k]);1r=1B}1n 1f(1I==1a.38.82){1f(1H){1j=1a.2O.2P(2I,1k,1g);1H=2N}1n 1j=1a.2O.2P(1r,1k,1g);1c(i=0;i<16;i++)1p[i]=1j[i]^1B[i];1c(18 k=0;k<1C-1G;k++)6K.1o(1p[k]);1r=1j}1n 1f(1I==1a.38.7H){1j=1a.2O.81(1B,1k,1g);1c(i=0;i<16;i++)1p[i]=((1H)?2I[i]:1r[i])^1j[i];1H=2N;1f(7G<1C)1c(18 k=0;k<7G-1G;k++)6K.1o(1p[k]);1n 1c(18 k=0;k<1C-1G;k++)6K.1o(1p[k]);1r=1B}}}1d 6K}};18 7x={8y:1e(s){8x{1d az(ay(s))}8w(e){6B\'7Y 7X 8v ax: 7x.8y.\'}},8u:1e(s){8x{1d aw(av(s))}8w(e){6B(\'7Y 7X 8v 8q: 7x.8u.\')}},au:1e(){18 2M=[];1f(7F.1h==1&&7F[0].as==73)2M=7F[0];1n 2M=7F;18 6J=\'\';1c(18 i=0;i<2M.1h;i++)6J+=(2M[i]<16?\'0\':\'\')+2M[i].74(16);1d 6J.7L()},ar:1e(s){18 6J=[];s.7n(/(..)/g,1e(s){6J.1o(aq(s,16))});1d 6J},8t:1e(7D,7E){1f(7D===2Y)7D=0;1f(7E===2Y)7E=1;1d 6I.ap(6I.ao()*(7E+1))+7D},an:1e(7C){1f(7C===2Y)7C=16;18 1k=[];1c(18 i=0;i<7C*2;i++)1k.1o(1a.8t(0,8j));1d 1k},am:1e(s,1g){18 8s=al.ak.aj(s);1d 8s.7B(0,1g)},ai:1e(s){18 1p=[];1c(18 i=0;i>2];1O+=1a.2X[((1y[i]&3)<<4)|(1y[i+1]>>4)];1f(!(1y[i+1]===2Y)){1O+=1a.2X[((1y[i+1]&15)<<2)|(1y[i+2]>>6)]}1n{1O+=\'=\'}1f(!(1y[i+2]===2Y)){1O+=1a.2X[1y[i+2]&63]}1n{1O+=\'=\'}}1d 1O},ag:1e(1y){18 1O=1a.8r(1y);18 7Z=1O.7B(0,64)+\'\\n\';1c(18 i=1;i<(6I.7A(1O.1h/64));i++){7Z+=1O.7B(i*64,i*64+64)+(6I.7A(1O.1h/64)==i+1?\'\':\'\\n\')}1d 7Z},8p:1e(1i){1i=1i.7n(/[\\r\\n\\t ]+/g,\'\')+\'====\';18 1y=[];18 c=[];1c(18 i=0;37;i=i+4){c[0]=1a.2X.7z(1i.7y(i));1f(c[0]==64){1d 1y}c[1]=1a.2X.7z(1i.7y(i+1));c[2]=1a.2X.7z(1i.7y(i+2));c[3]=1a.2X.7z(1i.7y(i+3));1f((c[0]<0)||(c[1]<0)||(c[1]==64)||(c[2]<0)||(c[3]<0)){6B\'7Y 7X 7W 8q at af \'+i+\': 7x.7W.8p.\'}1y.1o((c[0]<<2)|(c[1]>>4));1f(c[2]>=0&&c[2]<64){1y.1o(((c[1]&15)<<4)|(c[2]>>2));1f(c[3]>=0&&c[2]<64){1y.1o(((c[2]&3)<<6)|c[3])}}}}}};1e ae(1F){1e 2T(n,s){18 8o=(n<>>(32-s));1d 8o};1e ad(7h){18 6H="";18 i;18 7V;18 7U;1c(i=0;i<=6;i+=2){7V=(7h>>>(i*4+4))&2L;7U=(7h>>>(i*4))&2L;6H+=7V.74(16)+7U.74(16)}1d 6H};1e 6G(7h){18 6H="";18 i;18 v;1c(i=7;i>=0;i--){v=(7h>>>(i*4))&2L;6H+=v.74(16)}1d 6H};1e 7m(1i){1i=1i.7n(/\\r\\n/g,"\\n");18 1A="";1c(18 n=0;n<1i.1h;n++){18 c=1i.1E(n);1f(c<2Q){1A+=1N.1M(c)}1n 1f((c>8i)&&(c<8h)){1A+=1N.1M((c>>6)|8g);1A+=1N.1M((c&63)|2Q)}1n{1A+=1N.1M((c>>12)|8f);1A+=1N.1M(((c>>6)&63)|2Q);1A+=1N.1M((c&63)|2Q)}}1d 1A};18 7g;18 i,j;18 W=8n 73(80);18 7f=8d;18 7e=8c;18 7d=8b;18 7c=8a;18 7b=ab;18 A,B,C,D,E;18 1L;1F=7m(1F);18 2K=1F.1h;18 2W=8n 73();1c(i=0;i<2K-3;i+=4){j=1F.1E(i)<<24|1F.1E(i+1)<<16|1F.1E(i+2)<<8|1F.1E(i+3);2W.1o(j)}8m(2K%4){6A 0:i=aa;36;6A 1:i=1F.1E(2K-1)<<24|a9;36;6A 2:i=1F.1E(2K-2)<<24|1F.1E(2K-1)<<16|a8;36;6A 3:i=1F.1E(2K-3)<<24|1F.1E(2K-2)<<16|1F.1E(2K-1)<<8|1x;36}2W.1o(i);7r((2W.1h%16)!=14)2W.1o(0);2W.1o(2K>>>29);2W.1o((2K<<3)&2S);1c(7g=0;7g<2W.1h;7g+=16){1c(i=0;i<16;i++)W[i]=2W[7g+i];1c(i=16;i<=79;i++)W[i]=2T(W[i-3]^W[i-8]^W[i-14]^W[i-16],1);A=7f;B=7e;C=7d;D=7c;E=7b;1c(i=0;i<=19;i++){1L=(2T(A,5)+((B&C)|(~B&D))+E+W[i]+a7)&2S;E=D;D=C;C=2T(B,30);B=A;A=1L}1c(i=20;i<=39;i++){1L=(2T(A,5)+(B^C^D)+E+W[i]+a6)&2S;E=D;D=C;C=2T(B,30);B=A;A=1L}1c(i=40;i<=59;i++){1L=(2T(A,5)+((B&C)|(B&D)|(C&D))+E+W[i]+a5)&2S;E=D;D=C;C=2T(B,30);B=A;A=1L}1c(i=60;i<=79;i++){1L=(2T(A,5)+(B^C^D)+E+W[i]+a4)&2S;E=D;D=C;C=2T(B,30);B=A;A=1L}7f=(7f+A)&2S;7e=(7e+B)&2S;7d=(7d+C)&2S;7c=(7c+D)&2S;7b=(7b+E)&2S}18 1L=6G(7f)+6G(7e)+6G(7d)+6G(7c)+6G(7b);1d 1L.7L()}18 a3=1e(1i){1e 7a(76,7T){1d(76<<7T)|(76>>>(32-7T))}1e 1l(7w,7v){18 7u,7t,6F,6E,6z;6F=(7w&7S);6E=(7v&7S);7u=(7w&7s);7t=(7v&7s);6z=(7w&8l)+(7v&8l);1f(7u&7t){1d(6z^7S^6F^6E)}1f(7u|7t){1f(6z&7s){1d(6z^a2^6F^6E)}1n{1d(6z^7s^6F^6E)}}1n{1d(6z^6F^6E)}}1e F(x,y,z){1d(x&y)|((~x)&z)}1e G(x,y,z){1d(x&z)|(y&(~z))}1e H(x,y,z){1d(x^y^z)}1e I(x,y,z){1d(y^(x|(~z)))}1e 1w(a,b,c,d,x,s,ac){a=1l(a,1l(1l(F(b,c,d),x),ac));1d 1l(7a(a,s),b)};1e 1v(a,b,c,d,x,s,ac){a=1l(a,1l(1l(G(b,c,d),x),ac));1d 1l(7a(a,s),b)};1e 1u(a,b,c,d,x,s,ac){a=1l(a,1l(1l(H(b,c,d),x),ac));1d 1l(7a(a,s),b)};1e 1t(a,b,c,d,x,s,ac){a=1l(a,1l(1l(I(b,c,d),x),ac));1d 1l(7a(a,s),b)};1e 8e(1i){18 6y;18 77=1i.1h;18 7R=77+8;18 8k=(7R-(7R%64))/64;18 7q=(8k+1)*16;18 35=73(7q-1);18 78=0;18 2R=0;7r(2R<77){6y=(2R-(2R%4))/4;78=(2R%4)*8;35[6y]=(35[6y]|(1i.1E(2R)<<78));2R++}6y=(2R-(2R%4))/4;78=(2R%4)*8;35[6y]=35[6y]|(1x<<78);35[7q-2]=77<<3;35[7q-1]=77>>>29;1d 35};1e 6M(76){18 7o="",7p="",7Q,75;1c(75=0;75<=3;75++){7Q=(76>>>(75*8))&8j;7p="0"+7Q.74(16);7o=7o+7p.a1(7p.1h-2,2)}1d 7o};1e 7m(1i){1i=1i.7n(/\\r\\n/g,"\\n");18 1A="";1c(18 n=0;n<1i.1h;n++){18 c=1i.1E(n);1f(c<2Q){1A+=1N.1M(c)}1n 1f((c>8i)&&(c<8h)){1A+=1N.1M((c>>6)|8g);1A+=1N.1M((c&63)|2Q)}1n{1A+=1N.1M((c>>12)|8f);1A+=1N.1M(((c>>6)&63)|2Q);1A+=1N.1M((c&63)|2Q)}}1d 1A};18 x=73();18 k,7P,7O,7N,7M,a,b,c,d;18 72=7,71=12,70=17,6Z=22;18 6Y=5,6X=9,6W=14,6V=20;18 6U=4,6T=11,6S=16,6R=23;18 6Q=6,6P=10,6O=15,6N=21;1i=7m(1i);x=8e(1i);a=8d;b=8c;c=8b;d=8a;1c(k=0;k35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('E 1E(s){D 2v=8;D 7h=0;E 1f(x,y){D 4h=(x&4g)+(y&4g);D 7p=(x>>16)+(y>>16)+(4h>>16);F(7p<<16)|(4h&4g)}E S(X,n){F(X>>>n)|(X<<(32-n))}E R(X,n){F(X>>>n)}E 7l(x,y,z){F((x&y)^((~x)&z))}E 7j(x,y,z){F((x&y)^(x&z)^(y&z))}E 7k(x){F(S(x,2)^S(x,13)^S(x,22))}E 7m(x){F(S(x,6)^S(x,11)^S(x,25))}E 7n(x){F(S(x,7)^S(x,18)^R(x,3))}E 7o(x){F(S(x,17)^S(x,19)^R(x,10))}E 7d(m,l){D K=V 1w(bi,bh,bg,bf,bd,bc,bb,b9,b8,b7,b6,b5,b4,b3,b2,b1,b0,aZ,aY,aX,aW,aV,aU,aT,aS,aR,aQ,aP,aO,aN,aM,aL,aK,aJ,aI,aH,aG,aF,aE,aD,aC,aB,aA,az,ay,ax,aw,av,au,at,as,ar,aq,ap,ao,an,al,ak,aj,ai,ah,ag,af,ae);D Z=V 1w(ad,ab,aa,a9,a8,a7,a6,a5);D W=V 1w(64);D a,b,c,d,e,f,g,h,i,j;D 3w,4f;m[l>>5]|=2P<<(24-l%32);m[((l+64>>9)<<4)+15]=l;P(D i=0;i>5]|=(1P.27(i/2v)&7i)<<(24-i%32)}F 4e}E 7f(2u){2u=2u.a4(/\\r\\n/g,"\\n");D 1T="";P(D n=0;n<2u.U;n++){D c=2u.27(n);C(c<3v){1T+=2x.2w(c)}J C((c>5U)&&(c>6)|a2);1T+=2x.2w((c&63)|3v)}J{1T+=2x.2w((c>>12)|a1);1T+=2x.2w(((c>>6)&63)|3v);1T+=2x.2w((c&63)|3v)}}F 1T}E 7e(3u){D 4d=7h?"a0":"9Z";D 1P="";P(D i=0;i<3u.U*4;i++){1P+=4d.2R((3u[i>>2]>>((3-i%4)*8+4))&7g)+4d.2R((3u[i>>2]>>((3-i%4)*8))&7g)}F 1P}s=7f(s);F 7e(7d(7c(s),s.U*2v))}E 3t(){o.i=0;o.j=0;o.S=V 1w()}E 7b(2c){D i,j,t;P(i=0;i<1S;++i)o.S[i]=i;j=0;P(i=0;i<1S;++i){j=(j+o.S[i]+2c[i%2c.U])&1D;t=o.S[i];o.S[i]=o.S[j];o.S[j]=t}o.i=0;o.j=0}E 7a(){D t;o.i=(o.i+1)&1D;o.j=(o.j+o.S[o.i])&1D;t=o.S[o.i];o.S[o.i]=o.S[o.j];o.S[o.j]=t;F o.S[(t+o.S[o.i])&1D]}3t.H.74=7b;3t.H.72=7a;E 75(){F V 3t()}D 3s=1S;D 2V;D 1s;D 1g;E 78(x){1s[1g++]^=x&1D;1s[1g++]^=(x>>8)&1D;1s[1g++]^=(x>>16)&1D;1s[1g++]^=(x>>24)&1D;C(1g>=3s)1g-=3s}E 4c(){78(V 9Y().9X())}C(1s==1b){1s=V 1w();1g=0;D t;C(3r.49=="6V"&&3r.9W<"5"&&1U.77){D z=1U.77.76(32);P(t=0;t>>8;1s[1g++]=t&1D}1g=0;4c();}E 70(){C(2V==1b){4c();2V=75();2V.74(1s);P(1g=0;1g<1s.U;++1g)1s[1g]=0;1g=0;}F 2V.72()}E 6Z(ba){D i;P(i=0;i=0){D v=x*o[i++]+w[j]+c;c=1e.1Z(v/9R);w[j++]=v&9Q}F c}E 6W(i,x,w,j,c,n){D 2t=x&2S,2s=x>>15;L(--n>=0){D l=o[i]&2S;D h=o[i++]>>15;D m=2s*l+h*2t;l=2t*l+((m&2S)<<15)+w[j]+(c&6X);c=(l>>>30)+(m>>>15)+2s*h+(c>>>30);w[j++]=l&6X}F c}E 6T(i,x,w,j,c,n){D 2t=x&4b,2s=x>>14;L(--n>=0){D l=o[i]&4b;D h=o[i++]>>14;D m=2s*l+h*2t;l=2t*l+((m&4b)<<14)+w[j]+c;c=(l>>28)+(m>>14)+2s*h;w[j++]=l&9P}F c}C(4a&&(3r.49=="4K 9O 9N")){G.H.am=6W;1L=30}J C(4a&&(3r.49!="6V")){G.H.am=6U;1L=26}J{G.H.am=6T;1L=28}G.H.O=1L;G.H.1h=((1<<1L)-1);G.H.1m=(1<<1L);D 3q=52;G.H.6R=1e.2F(2,3q);G.H.45=3q-1L;G.H.42=2*1L-3q;D 6S="9M";D 2U=V 1w();D 2a,1r;2a="0".27(0);P(1r=0;1r<=9;++1r)2U[2a++]=1r;2a="a".27(0);P(1r=10;1r<36;++1r)2U[2a++]=1r;2a="A".27(0);P(1r=10;1r<36;++1r)2U[2a++]=1r;E 46(n){F 6S.2R(n)}E 3X(s,i){D c=2U[s.27(i)];F(c==1b)?-1:c}E 6z(r){P(D i=o.t-1;i>=0;--i)r[i]=o[i];r.t=o.t;r.s=o.s}E 6y(x){o.t=1;o.s=(x<0)?-1:0;C(x>0)o[0]=x;J C(x<-1)o[0]=x+1m;J o.t=0}E 1I(i){D r=Q();r.2j(i);F r}E 6x(s,b){D k;C(b==16)k=4;J C(b==8)k=3;J C(b==1S)k=8;J C(b==2)k=1;J C(b==32)k=5;J C(b==4)k=2;J{o.5O(s,b);F}o.t=0;o.s=0;D i=s.U,20=1t,1q=0;L(--i>=0){D x=(k==8)?s[i]&2O:3X(s,i);C(x<0){C(s.2R(i)=="-")20=1F;6c}20=1t;C(1q==0)o[o.t++]=x;J C(1q+k>o.O){o[o.t-1]|=(x&((1<<(o.O-1q))-1))<<1q;o[o.t++]=(x>>(o.O-1q))}J o[o.t-1]|=x<<1q;1q+=k;C(1q>=o.O)1q-=o.O}C(k==8&&(s[0]&2P)!=0){o.s=-1;C(1q>0)o[o.t-1]|=((1<<(o.O-1q))-1)<<1q}o.1n();C(20)G.1v.Y(o,o)}E 6w(){D c=o.s&o.1h;L(o.t>0&&o[o.t-1]==c)--o.t}E 6j(b){C(o.s<0)F"-"+o.2I().1z(b);D k;C(b==16)k=4;J C(b==8)k=3;J C(b==2)k=1;J C(b==32)k=5;J C(b==4)k=2;J F o.5Q(b);D 2K=(1<0){C(p>p)>0){m=1F;r=46(d)}L(i>=0){C(p>(p+=o.O-k)}J{d=(o[i]>>(p-=k))&2K;C(p<=0){p+=o.O;--i}}C(d>0)m=1F;C(m)r+=46(d)}}F m?r:"0"}E 6i(){D r=Q();G.1v.Y(o,r);F r}E 6h(){F(o.s<0)?o.2I():o}E 6g(a){D r=o.s-a.s;C(r!=0)F r;D i=o.t;r=i-a.t;C(r!=0)F r;L(--i>=0)C((r=o[i]-a[i])!=0)F r;F 0}E 2L(x){D r=1,t;C((t=x>>>16)!=0){x=t;r+=16}C((t=x>>8)!=0){x=t;r+=8}C((t=x>>4)!=0){x=t;r+=4}C((t=x>>2)!=0){x=t;r+=2}C((t=x>>1)!=0){x=t;r+=1}F r}E 6f(){C(o.t<=0)F 0;F o.O*(o.t-1)+2L(o[o.t-1]^(o.s&o.1h))}E 6v(n,r){D i;P(i=o.t-1;i>=0;--i)r[i+n]=o[i];P(i=n-1;i>=0;--i)r[i]=0;r.t=o.t+n;r.s=o.s}E 6u(n,r){P(D i=n;i=0;--i){r[i+1p+1]=(o[i]>>2r)|c;c=(o[i]&2T)<<1C}P(i=1p-1;i>=0;--i)r[i]=0;r[1p]=c;r.t=o.t+1p+1;r.s=o.s;r.1n()}E 6s(n,r){r.s=o.s;D 1p=1e.1Z(n/o.O);C(1p>=o.t){r.t=0;F}D 1C=n%o.O;D 2r=o.O-1C;D 2T=(1<<1C)-1;r[0]=o[1p]>>1C;P(D i=1p+1;i>1C}C(1C>0)r[o.t-1p-1]|=(o.s&2T)<<2r;r.t=o.t-1p;r.1n()}E 6r(a,r){D i=0,c=0,m=1e.1N(a.t,o.t);L(i>=o.O}C(a.t>=o.O}c+=o.s}J{c+=o.s;L(i>=o.O}c-=a.s}r.s=(c<0)?-1:0;C(c<-1)r[i++]=o.1m+c;J C(c>0)r[i++]=c;r.t=i;r.1n()}E 6q(a,r){D x=o.1H(),y=a.1H();D i=x.t;r.t=i+y.t;L(--i>=0)r[i]=0;P(i=0;i=0)r[i]=0;P(i=0;i=x.1m){r[i+x.t]-=x.1m;r[i+x.t+1]=1}}C(r.t>0)r[r.t-1]+=x.am(i,x[i],r,2*i,0,1);r.s=0;r.1n()}E 6o(m,q,r){D 21=m.1H();C(21.t<=0)F;D 3p=o.1H();C(3p.t<21.t){C(q!=1b)q.2j(0);C(r!=1b)o.1J(r);F}C(r==1b)r=Q();D y=Q(),40=o.s,6O=m.s;D 2q=o.O-2L(21[21.t-1]);C(2q>0){21.2k(2q,y);3p.2k(2q,r)}J{21.1J(y);3p.1J(r)}D 1B=y.t;D 3o=y[1B-1];C(3o==0)F;D 44=3o*(1<1)?y[1B-2]>>o.42:0);D 6Q=o.6R/44,6P=(1<=0){r[r.t++]=1;r.Y(t,r)}G.1u.2o(1B,t);t.Y(y,y);L(y.t<1B)y[y.t++]=0;L(--j>=0){D 3n=(r[--i]==3o)?o.1h:1e.1Z(r[i]*6Q+(r[i-1]+e)*6P);C((r[i]+=y.am(0,3n,r,j,0,1B))<3n){y.2o(j,t);r.Y(t,r);L(r[i]<--3n)r.Y(t,r)}}C(q!=1b){r.2N(1B,q);C(40!=6O)G.1v.Y(q,q)}r.t=1B;r.1n();C(2q>0)r.1j(2q,r);C(40<0)G.1v.Y(r,r)}E 6e(a){D r=Q();o.1H().1K(a,1b,r);C(o.s<0&&r.1d(G.1v)>0)a.Y(r,r);F r}E 1R(m){o.m=m}E 6N(x){C(x.s<0||x.1d(o.m)>=0)F x.3h(o.m);J F x}E 6M(x){F x}E 6L(x){x.1K(o.m,1b,x)}E 6K(x,y,r){x.2n(y,r);o.1x(r)}E 6J(x,r){x.2M(r);o.1x(r)}1R.H.2m=6N;1R.H.2l=6M;1R.H.1x=6L;1R.H.1W=6K;1R.H.1A=6J;E 6m(){C(o.t<1)F 0;D x=o[0];C((x&1)==0)F 0;D y=x&3;y=(y*(2-(x&3W)*y))&3W;y=(y*(2-(x&2O)*y))&2O;y=(y*(2-(((x&3l)*y)&3l)))&3l;y=(y*(2-x*y%o.1m))%o.1m;F(y>0)?o.1m-y:-y}E 1Q(m){o.m=m;o.3Z=m.6n();o.3Y=o.3Z&2S;o.6H=o.3Z>>15;o.6G=(1<<(m.O-15))-1;o.6I=2*m.t}E 6E(x){D r=Q();x.1H().2o(o.m.t,r);r.1K(o.m,1b,r);C(x.s<0&&r.1d(G.1v)>0)o.m.Y(r,r);F r}E 6D(x){D r=Q();x.1J(r);o.1x(r);F r}E 6C(x){L(x.t<=o.6I)x[x.t++]=0;P(D i=0;i>15)*o.3Y)&o.6G)<<15))&x.1h;j=i+o.m.t;x[j]+=o.m.am(0,6F,x,i,0,o.m.t);L(x[j]>=x.1m){x[j]-=x.1m;x[++j]++}}x.1n();x.2N(o.m.t,x);C(x.1d(o.m)>=0)x.Y(o.m,x)}E 6A(x,r){x.2M(r);o.1x(r)}E 6B(x,y,r){x.2n(y,r);o.1x(r)}1Q.H.2m=6E;1Q.H.2l=6D;1Q.H.1x=6C;1Q.H.1W=6B;1Q.H.1A=6A;E 6l(){F((o.t>0)?(o[0]&1):o.s)==0}E 6k(e,z){C(e>9L||e<1)F G.1u;D r=Q(),1c=Q(),g=z.2m(o),i=2L(e)-1;g.1J(r);L(--i>=0){z.1A(r,1c);C((e&(1<0)z.1W(1c,g,r);J{D t=r;r=1c;1c=t}}F z.2l(r)}E 6d(e,m){D z;C(e<1S||m.1l())z=V 1R(m);J z=V 1Q(m);F o.3S(e,z)}G.H.1J=6z;G.H.2j=6y;G.H.3m=6x;G.H.1n=6w;G.H.2o=6v;G.H.2N=6u;G.H.2k=6t;G.H.1j=6s;G.H.Y=6r;G.H.2n=6q;G.H.2M=6p;G.H.1K=6o;G.H.6n=6m;G.H.1l=6l;G.H.3S=6k;G.H.1z=6j;G.H.2I=6i;G.H.1H=6h;G.H.1d=6g;G.H.3Q=6f;G.H.3h=6e;G.H.5S=6d;G.1v=1I(0);G.1u=1I(1);E 5y(){D r=Q();o.1J(r);F r}E 5x(){C(o.s<0){C(o.t==1)F o[0]-o.1m;J C(o.t==0)F-1}J C(o.t==1)F o[0];J C(o.t==0)F 0;F((o[1]&((1<<(32-o.O))-1))<>24}E 5v(){F(o.t==0)?o.s:(o[0]<<16)>>16}E 5R(r){F 1e.1Z(1e.9K*o.O/1e.9J(r))}E 5u(){C(o.s<0)F-1;J C(o.t<=0||(o.t==1&&o[0]<=0))F 0;J F 1}E 5P(b){C(b==1b)b=10;C(o.1G()==0||b<2||b>36)F"0";D 2Q=o.3N(b);D a=1e.2F(b,2Q);D d=1I(a),y=Q(),z=Q(),r="";o.1K(d,y,z);L(y.1G()>0){r=(a+z.3K()).1z(b).9I(1)+r;y.1K(d,y,z)}F z.3K().1z(b)+r}E 5N(s,b){o.2j(0);C(b==1b)b=10;D 2Q=o.3N(b);D d=1e.2F(b,2Q),20=1t,j=0,w=0;P(D i=0;i=2Q){o.3L(d);o.2h(w,0);j=0;w=0}}C(j>0){o.3L(1e.2F(b,j));o.2h(w,0)}C(20)G.1v.Y(o,o)}E 5M(a,b,c){C("6b"==3g b){C(a<2)o.2j(1);J{o.3M(a,c);C(!o.5f(a-1))o.1V(G.1u.3i(a-1),3k,o);C(o.1l())o.2h(1,0);L(!o.4W(b)){o.2h(2,0);C(o.3Q()>a)o.Y(G.1u.3i(a-1),o)}}}J{D x=V 1w(),t=a&7;x.U=(a>>3)+1;b.6a(x);C(t>0)x[0]&=((1<0){C(p>p)!=(o.s&o.1h)>>p)r[k++]=d|(o.s<<(o.O-p));L(i>=0){C(p<8){d=(o[i]&((1<>(p+=o.O-8)}J{d=(o[i]>>(p-=8))&2O;C(p<=0){p+=o.O;--i}}C((d&2P)!=0)d|=-1S;C(k==0&&(o.s&2P)!=(d&2P))++k;C(k>0||d!=o.s)r[k++]=d}}F r}E 5s(a){F(o.1d(a)==0)}E 5r(a){F(o.1d(a)<0)?o:a}E 5q(a){F(o.1d(a)>0)?o:a}E 5L(a,1Y,r){D i,f,m=1e.1N(a.t,o.t);P(i=0;i>=16;r+=16}C((x&2O)==0){x>>=8;r+=8}C((x&3W)==0){x>>=4;r+=4}C((x&3)==0){x>>=2;r+=2}C((x&1)==0)++r;F r}E 5h(){P(D i=0;i=o.t)F(o.s!=0);F((o[j]&(1<<(n%o.O)))!=0)}E 5K(n,1Y){D r=G.1u.3i(n);o.1V(r,1Y,r);F r}E 5d(n){F o.3j(n,3k)}E 5c(n){F o.3j(n,3V)}E 5b(n){F o.3j(n,3U)}E 5J(a,r){D i=0,c=0,m=1e.1N(a.t,o.t);L(i>=o.O}C(a.t>=o.O}c+=o.s}J{c+=o.s;L(i>=o.O}c+=a.s}r.s=(c<0)?-1:0;C(c>0)r[i++]=c;J C(c<-1)r[i++]=o.1m+c;r.t=i;r.1n()}E 5a(a){D r=Q();o.2H(a,r);F r}E 58(a){D r=Q();o.Y(a,r);F r}E 57(a){D r=Q();o.2n(a,r);F r}E 55(a){D r=Q();o.1K(a,r,1b);F r}E 54(a){D r=Q();o.1K(a,1b,r);F r}E 51(a){D q=Q(),r=Q();o.1K(a,q,r);F V 1w(q,r)}E 5I(n){o[o.t]=o.am(0,n-1,o,0,0,o.t);++o.t;o.1n()}E 5H(n,w){L(o.t<=w)o[o.t++]=0;o[w]+=n;L(o[w]>=o.1m){o[w]-=o.1m;C(++w>=o.t)o[o.t++]=0;++o[w]}}E 2p(){}E 3T(x){F x}E 65(x,y,r){x.2n(y,r)}E 62(x,r){x.2M(r)}2p.H.2m=3T;2p.H.2l=3T;2p.H.1W=65;2p.H.1A=62;E 4Y(e){F o.3S(e,V 2p())}E 5F(a,n,r){D i=1e.1N(o.t+a.t,n);r.s=0;r.t=i;L(i>0)r[--i]=0;D j;P(j=r.t-o.t;i=0)r[i]=0;P(i=1e.3J(n-o.t,0);i2*o.m.t)F x.3h(o.m);J C(x.1d(o.m)<0)F x;J{D r=Q();x.1J(r);o.1x(r);F r}}E 5Y(x){F x}E 5X(x){x.2N(o.m.t-1,o.1c);C(x.t>o.m.t+1){x.t=o.m.t+1;x.1n()}o.60.5E(o.1c,o.m.t+1,o.3R);o.m.5G(o.3R,o.m.t+1,o.1c);L(x.1d(o.1c)<0)x.2h(1,o.m.t+1);x.Y(o.1c,x);L(x.1d(o.m)>=0)x.Y(o.m,x)}E 5V(x,r){x.2M(r);o.1x(r)}E 5W(x,y,r){x.2n(y,r);o.1x(r)}1X.H.2m=5Z;1X.H.2l=5Y;1X.H.1x=5X;1X.H.1W=5W;1X.H.1A=5V;E 50(e,m){D i=e.3Q(),k,r=1I(1),z;C(i<=0)F r;J C(i<18)k=1;J C(i<48)k=3;J C(i<9H)k=4;J C(i<9G)k=5;J k=6;C(i<8)z=V 1R(m);J C(m.1l())z=V 1X(m);J z=V 1Q(m);D g=V 1w(),n=3,2J=k-1,2K=(1<1){D 3P=Q();z.1A(g[1],3P);L(n<=2K){g[n]=Q();z.1W(3P,g[n-2],g[n]);n+=2}}D j=e.t-1,w,3O=1F,1c=Q(),t;i=2L(e[j])-1;L(j>=0){C(i>=2J)w=(e[j]>>(i-2J))&2K;J{w=(e[j]&((1<<(i+1))-1))<<(2J-i);C(j>0)w|=e[j-1]>>(o.O+i-2J)}n=k;L((w&1)==0){w>>=1;--n}C((i-=n)<0){i+=o.O;--j}C(3O){g[w].1J(r);3O=1t}J{L(n>1){z.1A(r,1c);z.1A(1c,r);n-=2}C(n>0)z.1A(r,1c);J{t=r;r=1c;1c=t}z.1W(1c,g[w],r)}L(j>=0&&(e[j]&(1<0){x.1j(g,x);y.1j(g,y)}L(x.1G()>0){C((i=x.2g())>0)x.1j(i,x);C((i=y.2g())>0)y.1j(i,y);C(x.1d(y)>=0){x.Y(y,x);x.1j(1,x)}J{y.Y(x,y);y.1j(1,y)}}C(g>0)y.2k(g,y);F y}E 5B(n){C(n<=0)F 0;D d=o.1m%n,r=(o.s<0)?n-1:0;C(o.t>0)C(d==0)r=o[0]%n;J P(D i=o.t-1;i>=0;--i)r=(d*r+o[i])%n;F r}E 4Z(m){D ac=m.1l();C((o.1l()&&ac)||m.1G()==0)F G.1v;D u=m.2G(),v=o.2G();D a=1I(1),b=1I(0),c=1I(0),d=1I(1);L(u.1G()!=0){L(u.1l()){u.1j(1,u);C(ac){C(!a.1l()||!b.1l()){a.2H(o,a);b.Y(m,b)}a.1j(1,a)}J C(!b.1l())b.Y(m,b);b.1j(1,b)}L(v.1l()){v.1j(1,v);C(ac){C(!c.1l()||!d.1l()){c.2H(o,c);d.Y(m,d)}c.1j(1,c)}J C(!d.1l())d.Y(m,d);d.1j(1,d)}C(u.1d(v)>=0){u.Y(v,u);C(ac)a.Y(c,a);b.Y(d,b)}J{v.Y(u,v);C(ac)c.Y(a,c);d.Y(b,d)}}C(v.1d(G.1u)!=0)F G.1v;C(d.1d(m)>=0)F d.3f(m);C(d.1G()<0)d.2H(m,d);J F d;C(d.1G()<0)F d.3E(m);J F d}D 1k=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,9F,9E,9D,9C,9B,5U,9A,9z,9y,9x,9w,9v,9u,9t,9s,9r,9q,9p,9o,9n,9m,9l,9k,9j,9i,9h,9g,9f,9e,9d,9c,9b,9a,99,98,96,95,94,93,92,91,90,8Z,8Y,8X,8W,8V,8U,8T,8S,8R,8Q,8P,8O,8N,8M,8L,8K,8J,8I,8H,8G,8F,8E,8D,8C,8B,8A,8z,8y,8x,8w];D 5T=(1<<26)/1k[1k.U-1];E 4V(t){D i,x=o.1H();C(x.t==1&&x[0]<=1k[1k.U-1]){P(i=0;i<1k.U;++i)C(x[0]==1k[i])F 1F;F 1t}C(x.1l())F 1t;i=1;L(i<1k.U){D m=1k[i],j=i+1;L(j<1k.U&&m<5T)m*=1k[j++];m=x.5C(m);L(i>1;C(t>1k.U)t=1k.U;D a=Q();P(D i=0;i0){D 1O=T.1o.1i("r")[0];C(!1O.1M("a")){3B(1O.1M("s"),1O.1M("B"),p);1a.2B(2e+1a.2C("4x/"),"M="+M,4y)}J 3c(1O.1M("s"),1O.1M("B"),1O.1M("a"),1O.1M("d"))}J C(T.1o.1i("2d").U>0)1a.1y(T.1o.1i("2d")[0])}};E 3B(s,2D,4C){D B=V G(2D,16);D 4D=2D;D u=V G(1E(3F+4D),16);D x=V G(1E(s+1E(I+":"+4C)),16);D 4B=k.3D(g.2f(x,N));D 4A=a.3E(u.3D(x));S=B.3f(4B).2f(4A,N);D 4z=A.1z(16)+B.1z(16)+S.1z(16);M=1E(4z);3d=1E(A.1z(16)+M+S.1z(16));};E 4y(){C(T.3b==4&&T.3a==39){C(T.1o.1i("M").U>0){C(1a.2A(T.1o.1i("M")[0])==3d){1a.4l();2X=1F}J 1a.1y("4t 2c 4s 2b 4r")}J C(T.1o.1i("2d").U>0)1a.1y(1a.2A(T.1o.1i("2d")[0]))}};E 3c(s,2D,3C,3A){4m();E 3z(){C(!2z("2Z")||!2z("35")){1U.4w(3z,10);F}C(3C=="7L")3e=2Z;J C(3C=="7K")3e=35;3y(3e(3A+p));3B(s,2D,3e(3A+p));1a.2B(2e+1a.2C("3c/4x/"),"M="+M,4v)};1U.4w(3z,10)};E 4v(){C(T.3b==4&&T.3a==39){C(T.1o.1i("M").U>0){C(1a.2A(T.1o.1i("M")[0])==3d){D 4u=2e+1a.2C("3c/7J/");1a.2B(4u,"p="+p,4q)}J 1a.1y("4t 2c 4s 2b 4r")}J C(T.1o.1i("2d").U>0){1a.1y(1a.2A(T.1o.1i("2d")[0]))}}};E 4q(){C(T.3b==4&&T.3a==39){C(T.1o.1i("7I").U>0)1a.4p();J 1a.1y("7H 7G 2b be 7F")}};E 34(4n){D 38=2W.7E(\'3x\');38.4o=\'7D/7C\';38.4i=4n;2W.1i(\'7B\')[0].7A(38)};E 4m(){C(2z("2Z")&&2z("35"))F;D 2y=1a.4j.7z("/");D 33=2y.7y(0,2y.U-1).7x("/");C(2y[2y.U-1]=="7w.1N.2Y")34(33+"/7v.1N.2Y");J{34(33+"/35.2Y");34(33+"/2Z.2Y")}}o.2c=E(){C(K==1b)C(2X){K=1E(S);F K}J 1a.1y("7u 7t 2b 7s 2X.");J F K};o.4l=E(){3y("7r 7q.")};o.1y=E(t){3y(t)}};4k.H.4j=2W.1i(\'3x\')[2W.1i(\'3x\').U-1].1M("4i");',62,701,'||||||||||||||||||||||||this||||||||||||||if|var|function|return|BigInteger|prototype||else||while|||DB|for|nbi|||xhr|length|new|||subTo|HASH|||||||||||that|null|r2|compareTo|Math|safe_add|rng_pptr|DM|getElementsByTagName|rShiftTo|lowprimes|isEven|DV|clamp|responseXML|ds|sh|vv|rng_pool|false|ONE|ZERO|Array|reduce|error_message|toString|sqrTo|ys|bs|255|SHA256|true|signum|abs|nbv|copyTo|divRemTo|dbits|getAttribute|min|response|str|Montgomery|Classic|256|utftext|window|bitwiseTo|mulTo|Barrett|op|floor|mi|pm||||||charCodeAt|||rr|not|key|error|url|modPow|getLowestSetBit|dAddOffset|n1|fromInt|lShiftTo|revert|convert|multiplyTo|dlShiftTo|NullExp|nsh|cbs|xh|xl|string|chrsz|fromCharCode|String|arr|isdefined|innerxml|ajaxRequest|paths|ephemeral|params|pow|clone|addTo|negate|k1|km|nbits|squareTo|drShiftTo|0xff|0x80|cs|charAt|0x7fff|bm|BI_RC|rng_state|document|authenticated|js|SHA1||||path|import_file|MD5|||scriptElt|200|status|readyState|upgrade|M2|hashfun|subtract|typeof|mod|shiftLeft|changeBit|op_or|0xffff|fromString|qd|y0|pt|BI_FP|navigator|rng_psize|Arcfour|binarray|128|T1|script|alert|do_upgrade|dsalt|calculations|algo|multiply|add|Astr|setRequestHeader|rng|SecureRandom|max|intValue|dMultiply|fromNumber|chunkSize|is1|g2|bitLength|q3|exp|nNop|op_xor|op_andnot|0xf|intAt|mpl|mp|ts||F2||yt|F1|int2char|||appName|j_lm|0x3fff|rng_seed_time|hex_tab|bin|T2|0xFFFF|lsw|src|srpPath|SRP|success|import_hashes|fname|type|identify|confirm_verifier|match|does|Server|auth_url|confirm_upgrade|setTimeout|authenticate|confirm_authentication|Mstr|aux|kgx|pass|Bstr|receive_salts|handshake_url|Ajax|Content|full_url|callback|Microsoft|ActiveXObject|XMLHttpRequest|variable|node|server|password|username|ser|base_url|Nstr|bnIsProbablePrime|isProbablePrime|bnGCD|bnPow|bnModInverse|bnModPow|bnDivideAndRemainder|||bnRemainder|bnDivide|divide|bnMultiply|bnSubtract||bnAdd|bnFlipBit|bnClearBit|bnSetBit|bnTestBit|testBit|bnBitCount|bnGetLowestSetBit|bnShiftRight|shiftRight|bnShiftLeft|bnNot|bnAndNot|bnXor|bnOr|bnAnd|bnMax|bnMin|bnEquals|bnToByteArray|bnSigNum|bnShortValue|bnByteValue|bnIntValue|bnClone|bnpMillerRabin|millerRabin|bnpModInt|modInt|bnpMultiplyUpperTo|multiplyUpperTo|bnpMultiplyLowerTo|multiplyLowerTo|bnpDAddOffset|bnpDMultiply|bnpAddTo|bnpChangeBit|bnpBitwiseTo|bnpFromNumber|bnpFromRadix|fromRadix|bnpToRadix|toRadix|bnpChunkSize|modPowInt|lplim|127|barrettSqrTo|barrettMulTo|barrettReduce|barrettRevert|barrettConvert|mu||nSqrTo|||nMulTo|cbit||lbit|op_and|nextBytes|number|continue|bnModPowInt|bnMod|bnBitLength|bnCompareTo|bnAbs|bnNegate|bnToString|bnpExp|bnpIsEven|bnpInvDigit|invDigit|bnpDivRemTo|bnpSquareTo|bnpMultiplyTo|bnpSubTo|bnpRShiftTo|bnpLShiftTo|bnpDRShiftTo|bnpDLShiftTo|bnpClamp|bnpFromString|bnpFromInt|bnpCopyTo|montSqrTo|montMulTo|montReduce|montRevert|montConvert|u0|um|mph|mt2|cSqrTo|cMulTo|cReduce|cRevert|cConvert|ms|d2|d1|FV|BI_RM|am3|am1|Netscape|am2|0x3fffffff|canary|rng_get_bytes|rng_get_byte||next||init|prng_newstate|random|crypto|rng_seed_int||ARC4next|ARC4init|str2binb|core_sha256|binb2hex|Utf8Encode|0xF|hexcase|mask|Maj|Sigma0256|Ch|Sigma1256|Gamma0256|Gamma1256|msw|successful|Authentication|been|has|User|hash|srp|join|slice|split|appendChild|head|javascript|text|createElement|confirmed|could|Verifier|ok|verifier|md5|sha1|handshake|failed|send|close|Connection|urlencoded|form|www|application|POST|open|onreadystatechange|supported|catch|XMLHTTP|try|undefined||nodeValue|firstChild|django|calcX|getN||getg|geturl|getxhr|getI|c46d46600d87fef149bd79b81119842f3c20241fda67d06ef412d8f6d9479c58|115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3|gcd|modInverse|divideAndRemainder|remainder|flipBit|clearBit|setBit|bitCount|andNot|xor|or|and|equals|toByteArray|shortValue|byteValue|509|503|499|491|487|479|467|463|461|457|449|443|439|433|431|421|419|409|401|397|389|383|379|373|367|359|353|349|347|337|331|317|313|311|307|293|283||281|277|271|269|263|257|251|241|239|233|229|227|223|211|199|197|193|191|181|179|173|167|163|157|151|149|139|137|131|113|109|107|103|101|768|144|substr|log|LN2|0xffffffff|0123456789abcdefghijklmnopqrstuvwxyz|Explorer|Internet|0xfffffff|0x3ffffff|0x4000000|0xefcafe|0xffffff|0xdeadbeefcafe|65536|appVersion|getTime|Date|0123456789abcdef|0123456789ABCDEF|224|192|2048|replace|0x5BE0CD19|0x1F83D9AB|0x9B05688C|0x510E527F|0xA54FF53A|0x3C6EF372|0xBB67AE85||0x6A09E667|0xC67178F2|0xBEF9A3F7|0xA4506CEB|0x90BEFFFA|0x8CC70208|0x84C87814|0x78A5636F|0x748F82EE||0x682E6FF3|0x5B9CCA4F|0x4ED8AA4A|0x391C0CB3|0x34B0BCB5|0x2748774C|0x1E376C08|0x19A4C116|0x106AA070|0xF40E3585|0xD6990624|0xD192E819|0xC76C51A3|0xC24B8B70|0xA81A664B|0xA2BFE8A1|0x92722C85|0x81C2C92E|0x766A0ABB|0x650A7354|0x53380D13|0x4D2C6DFC|0x2E1B2138|0x27B70A85|0x14292967|0x6CA6351|0xD5A79147|0xC6E00BF3|0xBF597FC7|0xB00327C8|0xA831C66D|0x983E5152|0x76F988DA|0x5CB0A9DC|0x4A7484AA|0x2DE92C6F|0x240CA1CC|0xFC19DC6|0xEFBE4786|0xE49B69C1|0xC19BF174|0x9BDC06A7|0x80DEB1FE|0x72BE5D74|0x550C7DC3|0x243185BE|0x12835B01|0xD807AA98|0xAB1C5ED5||0x923F82A4|0x59F111F1|0x3956C25B||0xE9B5DBA5|0xB5C0FBCF|0x71374491|0x428A2F98'.split('|'),0,{})) +eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('E 1A(s){D 2x=8;D 7r=0;E 1f(x,y){D 4k=(x&4j)+(y&4j);D 7z=(x>>16)+(y>>16)+(4k>>16);F(7z<<16)|(4k&4j)}E S(X,n){F(X>>>n)|(X<<(32-n))}E R(X,n){F(X>>>n)}E 7v(x,y,z){F((x&y)^((~x)&z))}E 7t(x,y,z){F((x&y)^(x&z)^(y&z))}E 7u(x){F(S(x,2)^S(x,13)^S(x,22))}E 7w(x){F(S(x,6)^S(x,11)^S(x,25))}E 7x(x){F(S(x,7)^S(x,18)^R(x,3))}E 7y(x){F(S(x,17)^S(x,19)^R(x,10))}E 7n(m,l){D K=V 1u(bD,bC,bB,bA,bz,by,bx,bw,bv,bu,bt,br,bq,bp,bo,bn,bl,bk,bj,bi,bh,bg,bf,bd,bc,bb,b9,b8,b7,b6,b5,b4,b3,b2,b1,b0,aZ,aY,aX,aW,aV,aU,aT,aS,aR,aQ,aP,aO,aN,aM,aL,aK,aJ,aI,aH,aG,aF,aE,aD,aC,aB,aA,az,ay);D 1a=V 1u(ax,aw,av,au,at,as,ar,aq);D W=V 1u(64);D a,b,c,d,e,f,g,h,i,j;D 3y,4i;m[l>>5]|=2S<<(24-l%32);m[((l+64>>9)<<4)+15]=l;P(D i=0;i>5]|=(1P.27(i/2x)&7s)<<(24-i%32)}F 4h}E 7p(2w){2w=2w.4A(/\\r\\n/g,"\\n");D 1T="";P(D n=0;n<2w.T;n++){D c=2w.27(n);C(c<3x){1T+=2z.2y(c)}J C((c>69)&&(c>6)|ao);1T+=2z.2y((c&63)|3x)}J{1T+=2z.2y((c>>12)|an);1T+=2z.2y(((c>>6)&63)|3x);1T+=2z.2y((c&63)|3x)}}F 1T}E 7o(3w){D 4g=7r?"al":"ak";D 1P="";P(D i=0;i<3w.T*4;i++){1P+=4g.2U((3w[i>>2]>>((3-i%4)*8+4))&7q)+4g.2U((3w[i>>2]>>((3-i%4)*8))&7q)}F 1P}s=7p(s);F 7o(7n(7m(s),s.T*2x))}E 3v(){o.i=0;o.j=0;o.S=V 1u()}E 7l(1B){D i,j,t;P(i=0;i<1S;++i)o.S[i]=i;j=0;P(i=0;i<1S;++i){j=(j+o.S[i]+1B[i%1B.T])&1E;t=o.S[i];o.S[i]=o.S[j];o.S[j]=t}o.i=0;o.j=0}E 7k(){D t;o.i=(o.i+1)&1E;o.j=(o.j+o.S[o.i])&1E;t=o.S[o.i];o.S[o.i]=o.S[o.j];o.S[o.j]=t;F o.S[(t+o.S[o.i])&1E]}3v.H.7f=7l;3v.H.7e=7k;E 7g(){F V 3v()}D 3u=1S;D 2X;D 1s;D 1g;E 7j(x){1s[1g++]^=x&1E;1s[1g++]^=(x>>8)&1E;1s[1g++]^=(x>>16)&1E;1s[1g++]^=(x>>24)&1E;C(1g>=3u)1g-=3u}E 4f(){7j(V aj().ai())}C(1s==1b){1s=V 1u();1g=0;D t;C(3t.4c=="77"&&3t.ah<"5"&&1U.7i){D z=1U.7i.7h(32);P(t=0;t>>8;1s[1g++]=t&1E}1g=0;4f();}E 7d(){C(2X==1b){4f();2X=7g();2X.7f(1s);P(1g=0;1g<1s.T;++1g)1s[1g]=0;1g=0;}F 2X.7e()}E 7c(ba){D i;P(i=0;i=0){D v=x*o[i++]+w[j]+c;c=1e.1Z(v/ab);w[j++]=v&aa}F c}E 78(i,x,w,j,c,n){D 2v=x&2V,2u=x>>15;L(--n>=0){D l=o[i]&2V;D h=o[i++]>>15;D m=2u*l+h*2v;l=2v*l+((m&2V)<<15)+w[j]+(c&7a);c=(l>>>30)+(m>>>15)+2u*h+(c>>>30);w[j++]=l&7a}F c}E 75(i,x,w,j,c,n){D 2v=x&4e,2u=x>>14;L(--n>=0){D l=o[i]&4e;D h=o[i++]>>14;D m=2u*l+h*2v;l=2v*l+((m&4e)<<14)+w[j]+c;c=(l>>28)+(m>>14)+2u*h;w[j++]=l&a9}F c}C(4d&&(3t.4c=="4V a8 a7")){G.H.am=78;1L=30}J C(4d&&(3t.4c!="77")){G.H.am=76;1L=26}J{G.H.am=75;1L=28}G.H.O=1L;G.H.1h=((1<<1L)-1);G.H.1m=(1<<1L);D 3s=52;G.H.72=1e.2I(2,3s);G.H.4a=3s-1L;G.H.46=2*1L-3s;D 74="a6";D 2W=V 1u();D 2a,1r;2a="0".27(0);P(1r=0;1r<=9;++1r)2W[2a++]=1r;2a="a".27(0);P(1r=10;1r<36;++1r)2W[2a++]=1r;2a="A".27(0);P(1r=10;1r<36;++1r)2W[2a++]=1r;E 4b(n){F 74.2U(n)}E 40(s,i){D c=2W[s.27(i)];F(c==1b)?-1:c}E 6J(r){P(D i=o.t-1;i>=0;--i)r[i]=o[i];r.t=o.t;r.s=o.s}E 6I(x){o.t=1;o.s=(x<0)?-1:0;C(x>0)o[0]=x;J C(x<-1)o[0]=x+1m;J o.t=0}E 1I(i){D r=Q();r.2l(i);F r}E 6H(s,b){D k;C(b==16)k=4;J C(b==8)k=3;J C(b==1S)k=8;J C(b==2)k=1;J C(b==32)k=5;J C(b==4)k=2;J{o.5Z(s,b);F}o.t=0;o.s=0;D i=s.T,20=1v,1q=0;L(--i>=0){D x=(k==8)?s[i]&2R:40(s,i);C(x<0){C(s.2U(i)=="-")20=1F;6m}20=1v;C(1q==0)o[o.t++]=x;J C(1q+k>o.O){o[o.t-1]|=(x&((1<<(o.O-1q))-1))<<1q;o[o.t++]=(x>>(o.O-1q))}J o[o.t-1]|=x<<1q;1q+=k;C(1q>=o.O)1q-=o.O}C(k==8&&(s[0]&2S)!=0){o.s=-1;C(1q>0)o[o.t-1]|=((1<<(o.O-1q))-1)<<1q}o.1n();C(20)G.1x.Y(o,o)}E 6G(){D c=o.s&o.1h;L(o.t>0&&o[o.t-1]==c)--o.t}E 6t(b){C(o.s<0)F"-"+o.2L().1t(b);D k;C(b==16)k=4;J C(b==8)k=3;J C(b==2)k=1;J C(b==32)k=5;J C(b==4)k=2;J F o.62(b);D 2N=(1<0){C(p>p)>0){m=1F;r=4b(d)}L(i>=0){C(p>(p+=o.O-k)}J{d=(o[i]>>(p-=k))&2N;C(p<=0){p+=o.O;--i}}C(d>0)m=1F;C(m)r+=4b(d)}}F m?r:"0"}E 6s(){D r=Q();G.1x.Y(o,r);F r}E 6r(){F(o.s<0)?o.2L():o}E 6q(a){D r=o.s-a.s;C(r!=0)F r;D i=o.t;r=i-a.t;C(r!=0)F r;L(--i>=0)C((r=o[i]-a[i])!=0)F r;F 0}E 2O(x){D r=1,t;C((t=x>>>16)!=0){x=t;r+=16}C((t=x>>8)!=0){x=t;r+=8}C((t=x>>4)!=0){x=t;r+=4}C((t=x>>2)!=0){x=t;r+=2}C((t=x>>1)!=0){x=t;r+=1}F r}E 6p(){C(o.t<=0)F 0;F o.O*(o.t-1)+2O(o[o.t-1]^(o.s&o.1h))}E 6F(n,r){D i;P(i=o.t-1;i>=0;--i)r[i+n]=o[i];P(i=n-1;i>=0;--i)r[i]=0;r.t=o.t+n;r.s=o.s}E 6E(n,r){P(D i=n;i=0;--i){r[i+1p+1]=(o[i]>>2t)|c;c=(o[i]&bm)<=0;--i)r[i]=0;r[1p]=c;r.t=o.t+1p+1;r.s=o.s;r.1n()}E 6C(n,r){r.s=o.s;D 1p=1e.1Z(n/o.O);C(1p>=o.t){r.t=0;F}D bs=n%o.O;D 2t=o.O-bs;D bm=(1<>bs;P(D i=1p+1;i>bs}C(bs>0)r[o.t-1p-1]|=(o.s&bm)<<2t;r.t=o.t-1p;r.1n()}E 6B(a,r){D i=0,c=0,m=1e.1N(a.t,o.t);L(i>=o.O}C(a.t>=o.O}c+=o.s}J{c+=o.s;L(i>=o.O}c-=a.s}r.s=(c<0)?-1:0;C(c<-1)r[i++]=o.1m+c;J C(c>0)r[i++]=c;r.t=i;r.1n()}E 6A(a,r){D x=o.1H(),y=a.1H();D i=x.t;r.t=i+y.t;L(--i>=0)r[i]=0;P(i=0;i=0)r[i]=0;P(i=0;i=x.1m){r[i+x.t]-=x.1m;r[i+x.t+1]=1}}C(r.t>0)r[r.t-1]+=x.am(i,x[i],r,2*i,0,1);r.s=0;r.1n()}E 6y(m,q,r){D 21=m.1H();C(21.t<=0)F;D 3r=o.1H();C(3r.t<21.t){C(q!=1b)q.2l(0);C(r!=1b)o.1J(r);F}C(r==1b)r=Q();D y=Q(),45=o.s,6Y=m.s;D 2s=o.O-2O(21[21.t-1]);C(2s>0){21.2m(2s,y);3r.2m(2s,r)}J{21.1J(y);3r.1J(r)}D 1D=y.t;D 3q=y[1D-1];C(3q==0)F;D 49=3q*(1<1)?y[1D-2]>>o.46:0);D 70=o.72/49,6Z=(1<=0){r[r.t++]=1;r.Y(t,r)}G.1w.2q(1D,t);t.Y(y,y);L(y.t<1D)y[y.t++]=0;L(--j>=0){D 3p=(r[--i]==3q)?o.1h:1e.1Z(r[i]*70+(r[i-1]+e)*6Z);C((r[i]+=y.am(0,3p,r,j,0,1D))<3p){y.2q(j,t);r.Y(t,r);L(r[i]<--3p)r.Y(t,r)}}C(q!=1b){r.2Q(1D,q);C(45!=6Y)G.1x.Y(q,q)}r.t=1D;r.1n();C(2s>0)r.1j(2s,r);C(45<0)G.1x.Y(r,r)}E 6o(a){D r=Q();o.1H().1K(a,1b,r);C(o.s<0&&r.1d(G.1x)>0)a.Y(r,r);F r}E 1R(m){o.m=m}E 6X(x){C(x.s<0||x.1d(o.m)>=0)F x.3j(o.m);J F x}E 6W(x){F x}E 6V(x){x.1K(o.m,1b,x)}E 6U(x,y,r){x.2p(y,r);o.1y(r)}E 6T(x,r){x.2P(r);o.1y(r)}1R.H.2o=6X;1R.H.2n=6W;1R.H.1y=6V;1R.H.1W=6U;1R.H.1C=6T;E 6w(){C(o.t<1)F 0;D x=o[0];C((x&1)==0)F 0;D y=x&3;y=(y*(2-(x&3Z)*y))&3Z;y=(y*(2-(x&2R)*y))&2R;y=(y*(2-(((x&3n)*y)&3n)))&3n;y=(y*(2-x*y%o.1m))%o.1m;F(y>0)?o.1m-y:-y}E 1Q(m){o.m=m;o.44=m.6x();o.42=o.44&2V;o.6R=o.44>>15;o.6Q=(1<<(m.O-15))-1;o.6S=2*m.t}E 6O(x){D r=Q();x.1H().2q(o.m.t,r);r.1K(o.m,1b,r);C(x.s<0&&r.1d(G.1x)>0)o.m.Y(r,r);F r}E 6N(x){D r=Q();x.1J(r);o.1y(r);F r}E 6M(x){L(x.t<=o.6S)x[x.t++]=0;P(D i=0;i>15)*o.42)&o.6Q)<<15))&x.1h;j=i+o.m.t;x[j]+=o.m.am(0,6P,x,i,0,o.m.t);L(x[j]>=x.1m){x[j]-=x.1m;x[++j]++}}x.1n();x.2Q(o.m.t,x);C(x.1d(o.m)>=0)x.Y(o.m,x)}E 6K(x,r){x.2P(r);o.1y(r)}E 6L(x,y,r){x.2p(y,r);o.1y(r)}1Q.H.2o=6O;1Q.H.2n=6N;1Q.H.1y=6M;1Q.H.1W=6L;1Q.H.1C=6K;E 6v(){F((o.t>0)?(o[0]&1):o.s)==0}E 6u(e,z){C(e>a5||e<1)F G.1w;D r=Q(),1c=Q(),g=z.2o(o),i=2O(e)-1;g.1J(r);L(--i>=0){z.1C(r,1c);C((e&(1<0)z.1W(1c,g,r);J{D t=r;r=1c;1c=t}}F z.2n(r)}E 6n(e,m){D z;C(e<1S||m.1l())z=V 1R(m);J z=V 1Q(m);F o.3V(e,z)}G.H.1J=6J;G.H.2l=6I;G.H.3o=6H;G.H.1n=6G;G.H.2q=6F;G.H.2Q=6E;G.H.2m=6D;G.H.1j=6C;G.H.Y=6B;G.H.2p=6A;G.H.2P=6z;G.H.1K=6y;G.H.6x=6w;G.H.1l=6v;G.H.3V=6u;G.H.1t=6t;G.H.2L=6s;G.H.1H=6r;G.H.1d=6q;G.H.3T=6p;G.H.3j=6o;G.H.66=6n;G.1x=1I(0);G.1w=1I(1);E 5J(){D r=Q();o.1J(r);F r}E 5I(){C(o.s<0){C(o.t==1)F o[0]-o.1m;J C(o.t==0)F-1}J C(o.t==1)F o[0];J C(o.t==0)F 0;F((o[1]&((1<<(32-o.O))-1))<>24}E 5G(){F(o.t==0)?o.s:(o[0]<<16)>>16}E 65(r){F 1e.1Z(1e.a4*o.O/1e.a3(r))}E 5F(){C(o.s<0)F-1;J C(o.t<=0||(o.t==1&&o[0]<=0))F 0;J F 1}E 60(b){C(b==1b)b=10;C(o.1G()==0||b<2||b>36)F"0";D 2T=o.3Q(b);D a=1e.2I(b,2T);D d=1I(a),y=Q(),z=Q(),r="";o.1K(d,y,z);L(y.1G()>0){r=(a+z.3N()).1t(b).a2(1)+r;y.1K(d,y,z)}F z.3N().1t(b)+r}E 5Y(s,b){o.2l(0);C(b==1b)b=10;D 2T=o.3Q(b);D d=1e.2I(b,2T),20=1v,j=0,w=0;P(D i=0;i=2T){o.3O(d);o.2j(w,0);j=0;w=0}}C(j>0){o.3O(1e.2I(b,j));o.2j(w,0)}C(20)G.1x.Y(o,o)}E 5X(a,b,c){C("6l"==3i b){C(a<2)o.2l(1);J{o.3P(a,c);C(!o.5q(a-1))o.1V(G.1w.3k(a-1),3m,o);C(o.1l())o.2j(1,0);L(!o.5a(b)){o.2j(2,0);C(o.3T()>a)o.Y(G.1w.3k(a-1),o)}}}J{D x=V 1u(),t=a&7;x.T=(a>>3)+1;b.3C(x);C(t>0)x[0]&=((1<0){C(p>p)!=(o.s&o.1h)>>p)r[k++]=d|(o.s<<(o.O-p));L(i>=0){C(p<8){d=(o[i]&((1<>(p+=o.O-8)}J{d=(o[i]>>(p-=8))&2R;C(p<=0){p+=o.O;--i}}C((d&2S)!=0)d|=-1S;C(k==0&&(o.s&2S)!=(d&2S))++k;C(k>0||d!=o.s)r[k++]=d}}F r}E 5D(a){F(o.1d(a)==0)}E 5C(a){F(o.1d(a)<0)?o:a}E 5B(a){F(o.1d(a)>0)?o:a}E 5W(a,1Y,r){D i,f,m=1e.1N(a.t,o.t);P(i=0;i>=16;r+=16}C((x&2R)==0){x>>=8;r+=8}C((x&3Z)==0){x>>=4;r+=4}C((x&3)==0){x>>=2;r+=2}C((x&1)==0)++r;F r}E 5s(){P(D i=0;i=o.t)F(o.s!=0);F((o[j]&(1<<(n%o.O)))!=0)}E 5V(n,1Y){D r=G.1w.3k(n);o.1V(r,1Y,r);F r}E 5o(n){F o.3l(n,3m)}E 5n(n){F o.3l(n,3Y)}E 5m(n){F o.3l(n,3X)}E 5U(a,r){D i=0,c=0,m=1e.1N(a.t,o.t);L(i>=o.O}C(a.t>=o.O}c+=o.s}J{c+=o.s;L(i>=o.O}c+=a.s}r.s=(c<0)?-1:0;C(c>0)r[i++]=c;J C(c<-1)r[i++]=o.1m+c;r.t=i;r.1n()}E 5l(a){D r=Q();o.2K(a,r);F r}E 5k(a){D r=Q();o.Y(a,r);F r}E 5j(a){D r=Q();o.2p(a,r);F r}E 5h(a){D r=Q();o.1K(a,r,1b);F r}E 5g(a){D r=Q();o.1K(a,1b,r);F r}E 5f(a){D q=Q(),r=Q();o.1K(a,q,r);F V 1u(q,r)}E 5T(n){o[o.t]=o.am(0,n-1,o,0,0,o.t);++o.t;o.1n()}E 5S(n,w){L(o.t<=w)o[o.t++]=0;o[w]+=n;L(o[w]>=o.1m){o[w]-=o.1m;C(++w>=o.t)o[o.t++]=0;++o[w]}}E 2r(){}E 3W(x){F x}E 6h(x,y,r){x.2p(y,r)}E 6g(x,r){x.2P(r)}2r.H.2o=3W;2r.H.2n=3W;2r.H.1W=6h;2r.H.1C=6g;E 5c(e){F o.3V(e,V 2r())}E 5Q(a,n,r){D i=1e.1N(o.t+a.t,n);r.s=0;r.t=i;L(i>0)r[--i]=0;D j;P(j=r.t-o.t;i=0)r[i]=0;P(i=1e.3M(n-o.t,0);i2*o.m.t)F x.3j(o.m);J C(x.1d(o.m)<0)F x;J{D r=Q();x.1J(r);o.1y(r);F r}}E 6d(x){F x}E 6c(x){x.2Q(o.m.t-1,o.1c);C(x.t>o.m.t+1){x.t=o.m.t+1;x.1n()}o.6f.5P(o.1c,o.m.t+1,o.3U);o.m.5R(o.3U,o.m.t+1,o.1c);L(x.1d(o.1c)<0)x.2j(1,o.m.t+1);x.Y(o.1c,x);L(x.1d(o.m)>=0)x.Y(o.m,x)}E 6a(x,r){x.2P(r);o.1y(r)}E 6b(x,y,r){x.2p(y,r);o.1y(r)}1X.H.2o=6e;1X.H.2n=6d;1X.H.1y=6c;1X.H.1W=6b;1X.H.1C=6a;E 5e(e,m){D i=e.3T(),k,r=1I(1),z;C(i<=0)F r;J C(i<18)k=1;J C(i<48)k=3;J C(i1){D 3S=Q();z.1C(g[1],3S);L(n<=2N){g[n]=Q();z.1W(3S,g[n-2],g[n]);n+=2}}D j=e.t-1,w,3R=1F,1c=Q(),t;i=2O(e[j])-1;L(j>=0){C(i>=2M)w=(e[j]>>(i-2M))&2N;J{w=(e[j]&((1<<(i+1))-1))<<(2M-i);C(j>0)w|=e[j-1]>>(o.O+i-2M)}n=k;L((w&1)==0){w>>=1;--n}C((i-=n)<0){i+=o.O;--j}C(3R){g[w].1J(r);3R=1v}J{L(n>1){z.1C(r,1c);z.1C(1c,r);n-=2}C(n>0)z.1C(r,1c);J{t=r;r=1c;1c=t}z.1W(1c,g[w],r)}L(j>=0&&(e[j]&(1<0){x.1j(g,x);y.1j(g,y)}L(x.1G()>0){C((i=x.2i())>0)x.1j(i,x);C((i=y.2i())>0)y.1j(i,y);C(x.1d(y)>=0){x.Y(y,x);x.1j(1,x)}J{y.Y(x,y);y.1j(1,y)}}C(g>0)y.2m(g,y);F y}E 5M(n){C(n<=0)F 0;D d=o.1m%n,r=(o.s<0)?n-1:0;C(o.t>0)C(d==0)r=o[0]%n;J P(D i=o.t-1;i>=0;--i)r=(d*r+o[i])%n;F r}E 5d(m){D ac=m.1l();C((o.1l()&&ac)||m.1G()==0)F G.1x;D u=m.2J(),v=o.2J();D a=1I(1),b=1I(0),c=1I(0),d=1I(1);L(u.1G()!=0){L(u.1l()){u.1j(1,u);C(ac){C(!a.1l()||!b.1l()){a.2K(o,a);b.Y(m,b)}a.1j(1,a)}J C(!b.1l())b.Y(m,b);b.1j(1,b)}L(v.1l()){v.1j(1,v);C(ac){C(!c.1l()||!d.1l()){c.2K(o,c);d.Y(m,d)}c.1j(1,c)}J C(!d.1l())d.Y(m,d);d.1j(1,d)}C(u.1d(v)>=0){u.Y(v,u);C(ac)a.Y(c,a);b.Y(d,b)}J{v.Y(u,v);C(ac)c.Y(a,c);d.Y(b,d)}}C(v.1d(G.1w)!=0)F G.1x;C(d.1d(m)>=0)F d.3h(m);C(d.1G()<0)d.2K(m,d);J F d;C(d.1G()<0)F d.3I(m);J F d}D 1k=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,9Z,9Y,9X,9W,9V,69,9U,9T,9S,9R,9Q,9P,9O,9N,9M,9L,9K,9J,9I,9H,9G,9F,9E,9D,9C,9B,9A,9z,9y,9x,9w,9v,9u,9t,9s,9r,9q,9p,9o,9n,9m,9l,9k,9j,9i,9h,9g,9f,9e,9d,9c,9b,9a,99,98,96,95,94,93,92,91,90,8Z,8Y,8X,8W,8V,8U,8T,8S,8R,8Q];D 68=(1<<26)/1k[1k.T-1];E 58(t){D i,x=o.1H();C(x.t==1&&x[0]<=1k[1k.T-1]){P(i=0;i<1k.T;++i)C(x[0]==1k[i])F 1F;F 1v}C(x.1l())F 1v;i=1;L(i<1k.T){D m=1k[i],j=i+1;L(j<1k.T&&m<68)m*=1k[j++];m=x.5N(m);L(i>1;C(t>1k.T)t=1k.T;D a=Q();P(D i=0;i0){D 1O=U.1o.1i("r")[0];C(!1O.1M("a")){3F(1O.1M("s"),1O.1M("B"),p);Z.2D(2g+Z.2E("4H/"),"M="+M,4J)}J 3c(1O.1M("s"),1O.1M("B"),1O.1M("a"),1O.1M("d"))}J C(U.1o.1i("2f").T>0)Z.1z(U.1o.1i("2f")[0])}};E 3F(s,2G,4N){D B=V G(2G,16);D 4O=2G;D u=V G(1A(3J+4O),16);D x=V G(1A(s+1A(I+":"+4N)),16);D 4M=k.3H(g.2h(x,N));D 4L=a.3I(u.3H(x));S=B.3h(4M).2h(4L,N);D 4K=A.1t(16)+B.1t(16)+S.1t(16);M=1A(4K);3d=1A(A.1t(16)+M+S.1t(16));};E 4J(){C(U.3b==4&&U.3a==39){C(U.1o.1i("M").T>0){C(Z.2C(U.1o.1i("M")[0])==3d){Z.4p();2Z=1F}J Z.1z("4x 1B 4w 2b 4v")}J C(U.1o.1i("2f").T>0)Z.1z(Z.2C(U.1o.1i("2f")[0]))}};E 3c(s,2G,3G,4I){4q();E 3D(){C(!2B("34")||!2B("35")){1U.4G(3D,10);F}C(3G=="86")3E=34;J C(3G=="85")3E=35;3F(s,2G,3E(4I+p));Z.2D(2g+Z.2E("3c/4H/"),"M="+M,4z)};1U.4G(3D,10)};E 3A(4F){D 1B=33.84(Z.1B());D 3B=33.82(4F);D 3e=V 1u(16);3g.3C(3e);D 4E=3f.81(3B,0,3B.T,3f.4D.4C);D 4B=3f.3A(4E,3f.4D.4C,1B,1B.T,3e).80;D 2F=33.7Z.7Y(3e.7X(4B));L(2F.7W("+",0)>-1)2F=2F.4A("+","7V");F 2F};E 4z(){C(U.3b==4&&U.3a==39){C(U.1o.1i("M").T>0){C(Z.2C(U.1o.1i("M")[0])==3d){K=1A(S.1t(16));D 4y=2g+Z.2E("3c/7U/");Z.2D(4y,"p="+3A(p)+"&l="+p.T,4u)}J Z.1z("4x 1B 4w 2b 4v")}J C(U.1o.1i("2f").T>0){Z.1z(Z.2C(U.1o.1i("2f")[0]))}}};E 4u(){C(U.3b==4&&U.3a==39){K=1b;C(U.1o.1i("7T").T>0)Z.4t();J Z.1z("7S 7R 2b be 7Q")}};E 2e(4r){D 38=2Y.7P(\'3z\');38.4s=\'7O/7N\';38.4l=4r;2Y.1i(\'7M\')[0].7L(38)};E 4q(){C(2B("34")&&2B("35"))F;D 2A=Z.4m.7K("/");D 2d=2A.7J(0,2A.T-1).7I("/");C(2A[2A.T-1]=="7H.1N.2c")2e(2d+"/7G.1N.2c");J{2e(2d+"/35.2c");2e(2d+"/34.2c");2e(2d+"/33.2c");2e(2d+"/7F.2c")}}o.1B=E(){C(K==1b)C(2Z){K=1A(S.1t(16));F K}J Z.1z("7E 7D 2b 7C 2Z.");J F K};o.4p=E(){4o("7B 7A.")};o.1z=E(t){4o(t)}};4n.H.4m=2Y.1i(\'3z\')[2Y.1i(\'3z\').T-1].1M("4l");',62,722,'||||||||||||||||||||||||this||||||||||||||if|var|function|return|BigInteger|prototype||else||while|||DB|for|nbi|||length|xhr|new|||subTo|that|||||||||||HASH|null|r2|compareTo|Math|safe_add|rng_pptr|DM|getElementsByTagName|rShiftTo|lowprimes|isEven|DV|clamp|responseXML|ds|sh|vv|rng_pool|toString|Array|false|ONE|ZERO|reduce|error_message|SHA256|key|sqrTo|ys|255|true|signum|abs|nbv|copyTo|divRemTo|dbits|getAttribute|min|response|str|Montgomery|Classic|256|utftext|window|bitwiseTo|mulTo|Barrett|op|floor|mi|pm||||||charCodeAt|||rr|not|js|path|import_file|error|url|modPow|getLowestSetBit|dAddOffset|n1|fromInt|lShiftTo|revert|convert|multiplyTo|dlShiftTo|NullExp|nsh|cbs|xh|xl|string|chrsz|fromCharCode|String|arr|isdefined|innerxml|ajaxRequest|paths|retstring|ephemeral|params|pow|clone|addTo|negate|k1|km|nbits|squareTo|drShiftTo|0xff|0x80|cs|charAt|0x7fff|BI_RC|rng_state|document|authenticated||||cryptoHelpers|SHA1|MD5|||scriptElt|200|status|readyState|upgrade|M2|iv|slowAES|rng|subtract|typeof|mod|shiftLeft|changeBit|op_or|0xffff|fromString|qd|y0|pt|BI_FP|navigator|rng_psize|Arcfour|binarray|128|T1|script|encrypt|byteMessage|nextBytes|do_upgrade|hashfun|calculations|algo|multiply|add|Astr|setRequestHeader|SecureRandom|max|intValue|dMultiply|fromNumber|chunkSize|is1|g2|bitLength|q3|exp|nNop|op_xor|op_andnot|0xf|intAt||mpl||mp|ts|F2|||yt|F1|int2char|appName|j_lm|0x3fff|rng_seed_time|hex_tab|bin|T2|0xFFFF|lsw|src|srpPath|SRP|alert|success|import_hashes|fname|type|identify|confirm_verifier|match|does|Server|auth_url|confirm_upgrade|replace|ciphertext|CFB|modeOfOperation|paddedByteMessage|plaintext|setTimeout|authenticate|dsalt|confirm_authentication|Mstr|aux|kgx|pass|Bstr|receive_salts|handshake_url|Ajax|Content|full_url|callback|Microsoft|ActiveXObject|XMLHttpRequest|variable|node|server|password|||username|ser|base_url|Nstr|bnIsProbablePrime||isProbablePrime|bnGCD|bnPow|bnModInverse|bnModPow|bnDivideAndRemainder|bnRemainder|bnDivide|divide|bnMultiply|bnSubtract|bnAdd|bnFlipBit|bnClearBit|bnSetBit|bnTestBit|testBit|bnBitCount|bnGetLowestSetBit|bnShiftRight|shiftRight|bnShiftLeft|bnNot|bnAndNot|bnXor|bnOr|bnAnd|bnMax|bnMin|bnEquals|bnToByteArray|bnSigNum|bnShortValue|bnByteValue|bnIntValue|bnClone|bnpMillerRabin|millerRabin|bnpModInt|modInt|bnpMultiplyUpperTo|multiplyUpperTo|bnpMultiplyLowerTo|multiplyLowerTo|bnpDAddOffset|bnpDMultiply|bnpAddTo|bnpChangeBit|bnpBitwiseTo|bnpFromNumber|bnpFromRadix|fromRadix|bnpToRadix||toRadix|||bnpChunkSize|modPowInt||lplim|127|barrettSqrTo|barrettMulTo|barrettReduce|barrettRevert|barrettConvert|mu|nSqrTo|nMulTo|cbit|lbit|op_and|number|continue|bnModPowInt|bnMod|bnBitLength|bnCompareTo|bnAbs|bnNegate|bnToString|bnpExp|bnpIsEven|bnpInvDigit|invDigit|bnpDivRemTo|bnpSquareTo|bnpMultiplyTo|bnpSubTo|bnpRShiftTo|bnpLShiftTo|bnpDRShiftTo|bnpDLShiftTo|bnpClamp|bnpFromString|bnpFromInt|bnpCopyTo|montSqrTo|montMulTo|montReduce|montRevert|montConvert|u0|um|mph|mt2|cSqrTo|cMulTo|cReduce|cRevert|cConvert|ms|d2|d1||FV||BI_RM|am3|am1|Netscape|am2||0x3fffffff|canary|rng_get_bytes|rng_get_byte|next|init|prng_newstate|random|crypto|rng_seed_int|ARC4next|ARC4init|str2binb|core_sha256|binb2hex|Utf8Encode|0xF|hexcase|mask|Maj|Sigma0256|Ch|Sigma1256|Gamma0256|Gamma1256|msw|successful|Authentication|been|has|User|aes|hash|srp|join|slice|split|appendChild|head|javascript|text|createElement|confirmed|could|Verifier|ok|verifier|_|indexOf|concat|encode|base64|cipher|getPaddedBlock|convertStringToByteArray||toNumbers|md5|sha1|handshake|failed||send|close|Connection|urlencoded|form|www|application|POST|open|onreadystatechange|supported|catch|XMLHTTP|try|undefined|nodeValue|firstChild|django|calcX|getN|getg|geturl|getxhr|getI|c46d46600d87fef149bd79b81119842f3c20241fda67d06ef412d8f6d9479c58|115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3|gcd|modInverse|divideAndRemainder|remainder|flipBit|clearBit|setBit|bitCount|andNot|xor|or|and|equals|toByteArray|shortValue|byteValue|509|503|499|491|487|479|467|463|461|457|449|443|439|433|431|421|419||409|401|397|389|383|379|373|367|359|353|349|347|337|331|317|313|311|307|293|283|281|277|271|269|263|257|251|241|239|233|229|227|223|211|199|197|193|191|181|179|173|167|163|157|151|149|139|137|131|113|109|107|103|101|768|144|substr|log|LN2|0xffffffff|0123456789abcdefghijklmnopqrstuvwxyz|Explorer|Internet|0xfffffff|0x3ffffff|0x4000000||0xefcafe|0xffffff|0xdeadbeefcafe|65536|appVersion|getTime|Date|0123456789abcdef|0123456789ABCDEF||224|192|2048|0x5BE0CD19|0x1F83D9AB|0x9B05688C|0x510E527F|0xA54FF53A|0x3C6EF372|0xBB67AE85|0x6A09E667|0xC67178F2|0xBEF9A3F7|0xA4506CEB|0x90BEFFFA|0x8CC70208|0x84C87814|0x78A5636F|0x748F82EE|0x682E6FF3|0x5B9CCA4F|0x4ED8AA4A|0x391C0CB3|0x34B0BCB5|0x2748774C|0x1E376C08|0x19A4C116|0x106AA070|0xF40E3585|0xD6990624|0xD192E819|0xC76C51A3|0xC24B8B70|0xA81A664B|0xA2BFE8A1|0x92722C85|0x81C2C92E|0x766A0ABB|0x650A7354|0x53380D13|0x4D2C6DFC|0x2E1B2138|0x27B70A85|0x14292967|0x6CA6351|0xD5A79147|0xC6E00BF3|0xBF597FC7|0xB00327C8||0xA831C66D|0x983E5152|0x76F988DA||0x5CB0A9DC|0x4A7484AA|0x2DE92C6F|0x240CA1CC|0xFC19DC6|0xEFBE4786|0xE49B69C1||0xC19BF174|0x9BDC06A7|0x80DEB1FE|0x72BE5D74|0x550C7DC3||0x243185BE|0x12835B01|0xD807AA98|0xAB1C5ED5|0x923F82A4|0x59F111F1|0x3956C25B|0xE9B5DBA5|0xB5C0FBCF|0x71374491|0x428A2F98'.split('|'),0,{})) diff --git a/javascript/srp.js b/javascript/srp.js index ba14324..58a3fe7 100644 --- a/javascript/srp.js +++ b/javascript/srp.js @@ -209,13 +209,28 @@ function SRP(username, password, ser, base_url) hashfun = SHA1; else if(algo == "md5") hashfun = MD5; - alert(hashfun(dsalt+p)); + //alert(hashfun(dsalt+p)); calculations(s, ephemeral, hashfun(dsalt+p)); that.ajaxRequest(url+that.paths("upgrade/authenticate/"), "M="+M, confirm_upgrade); }; window.setTimeout(do_upgrade,10); }; + // Encrypt plaintext using slowAES + function encrypt(plaintext) + { + var key = cryptoHelpers.toNumbers(that.key()); + var byteMessage = cryptoHelpers.convertStringToByteArray(plaintext); + var iv = new Array(16); + rng.nextBytes(iv); + var paddedByteMessage = slowAES.getPaddedBlock(byteMessage, 0, byteMessage.length, slowAES.modeOfOperation.CFB); + var ciphertext = slowAES.encrypt(paddedByteMessage, slowAES.modeOfOperation.CFB, key, key.length, iv).cipher; + var retstring = cryptoHelpers.base64.encode(iv.concat(ciphertext)); + while(retstring.indexOf("+",0) > -1) + retstring = retstring.replace("+", "_"); + return retstring; + }; + // Receive the server's M, confirming that the server has HASH(p) // Next, send P in plaintext (this is the **only** time it should ever be sent plain text) function confirm_upgrade() @@ -225,8 +240,9 @@ function SRP(username, password, ser, base_url) { if(that.innerxml(xhr.responseXML.getElementsByTagName("M")[0]) == M2) { + K = SHA256(S.toString(16)); var auth_url = url + that.paths("upgrade/verifier/"); - that.ajaxRequest(auth_url, "p="+p, confirm_verifier); + that.ajaxRequest(auth_url, "p="+encrypt(p)+"&l="+p.length, confirm_verifier); } else that.error_message("Server key does not match"); @@ -242,6 +258,7 @@ function SRP(username, password, ser, base_url) function confirm_verifier() { if(xhr.readyState == 4 && xhr.status == 200) { + K = null; if(xhr.responseXML.getElementsByTagName("ok").length > 0) that.identify(); else @@ -273,6 +290,8 @@ function SRP(username, password, ser, base_url) { import_file(path+"/MD5.js"); import_file(path+"/SHA1.js"); + import_file(path+"/cryptoHelpers.js"); + import_file(path+"/aes.js"); } } // If someone wants to use the session key for encrypting traffic, they can @@ -282,7 +301,7 @@ function SRP(username, password, ser, base_url) if(K == null) if(authenticated) { - K = SHA256(S); + K = SHA256(S.toString(16)); return K; } else -- cgit v1.2.3