diff --git a/js-crypt-test/js/simple-crypt-deps.js b/js-crypt-test/js/simple-crypt-deps.js new file mode 100644 index 0000000..4d64502 --- /dev/null +++ b/js-crypt-test/js/simple-crypt-deps.js @@ -0,0 +1,6856 @@ +/* + * 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 + }, + + // get a 16 byte block (aes operates on 128bits) + getBlock: function(bytesIn,start,end,mode) + { + if(end - start > 16) + end = start + 16; + + return bytesIn.slice(start, end); + }, + + /* + * 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, iv) + { + var size = key.length; + 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 (mode == this.modeOfOperation.CBC) + this.padBytesIn(bytesIn); + 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.getBlock(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 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,mode,key,iv) + { + var size = key.length; + 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.getBlock(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; + for(var k = 0;k < end-start;k++) + bytesOut.push(byteArray[k]); + input = ciphertext; + } + } + if(mode == this.modeOfOperation.CBC) + this.unpadBytesOut(bytesOut); + } + return bytesOut; + }, + padBytesIn: function(data) { + var len = data.length; + var padByte = 16 - (len % 16); + for (var i = 0; i < padByte; i++) { + data.push(padByte); + } + }, + unpadBytesOut: function(data) { + var padCount = 0; + var padByte = -1; + var blockSize = 16; + for (var i = data.length - 1; i >= data.length-1 - blockSize; i--) { + if (data[i] <= blockSize) { + if (padByte == -1) + padByte = data[i]; + if (data[i] != padByte) { + padCount = 0; + break; + } + padCount++; + } else + break; + if (padCount == padByte) + break; + } + if (padCount > 0) + data.splice(data.length - padCount, padCount); + } + /* + * END MODE OF OPERATION SECTION + */ +}; + +/* +CryptoJS v3.1.2 +code.google.com/p/crypto-js +(c) 2009-2013 by Jeff Mott. All rights reserved. +code.google.com/p/crypto-js/wiki/License +*/ +/** + * CryptoJS core components. + */ +var CryptoJS = CryptoJS || (function (Math, undefined) { + /** + * CryptoJS namespace. + */ + var C = {}; + + /** + * Library namespace. + */ + var C_lib = C.lib = {}; + + /** + * Base object for prototypal inheritance. + */ + var Base = C_lib.Base = (function () { + function F() {} + + return { + /** + * Creates a new object that inherits from this object. + * + * @param {Object} overrides Properties to copy into the new object. + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * field: 'value', + * + * method: function () { + * } + * }); + */ + extend: function (overrides) { + // Spawn + F.prototype = this; + var subtype = new F(); + + // Augment + if (overrides) { + subtype.mixIn(overrides); + } + + // Create default initializer + if (!subtype.hasOwnProperty('init')) { + subtype.init = function () { + subtype.$super.init.apply(this, arguments); + }; + } + + // Initializer's prototype is the subtype object + subtype.init.prototype = subtype; + + // Reference supertype + subtype.$super = this; + + return subtype; + }, + + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + create: function () { + var instance = this.extend(); + instance.init.apply(instance, arguments); + + return instance; + }, + + /** + * Initializes a newly created object. + * Override this method to add some logic when your objects are created. + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * init: function () { + * // ... + * } + * }); + */ + init: function () { + }, + + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn: function (properties) { + for (var propertyName in properties) { + if (properties.hasOwnProperty(propertyName)) { + this[propertyName] = properties[propertyName]; + } + } + + // IE won't copy toString using the loop above + if (properties.hasOwnProperty('toString')) { + this.toString = properties.toString; + } + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone: function () { + return this.init.prototype.extend(this); + } + }; + }()); + + /** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var WordArray = C_lib.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 4; + } + }, + + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString: function (encoder) { + return (encoder || Hex).stringify(this); + }, + + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat: function (wordArray) { + // Shortcuts + var thisWords = this.words; + var thatWords = wordArray.words; + var thisSigBytes = this.sigBytes; + var thatSigBytes = wordArray.sigBytes; + + // Clamp excess bits + this.clamp(); + + // Concat + if (thisSigBytes % 4) { + // Copy one byte at a time + for (var i = 0; i < thatSigBytes; i++) { + var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); + } + } else if (thatWords.length > 0xffff) { + // Copy one word at a time + for (var i = 0; i < thatSigBytes; i += 4) { + thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; + } + } else { + // Copy all words at once + thisWords.push.apply(thisWords, thatWords); + } + this.sigBytes += thatSigBytes; + + // Chainable + return this; + }, + + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp: function () { + // Shortcuts + var words = this.words; + var sigBytes = this.sigBytes; + + // Clamp + words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); + words.length = Math.ceil(sigBytes / 4); + }, + + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone.words = this.words.slice(0); + + return clone; + }, + + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + random: function (nBytes) { + var words = []; + for (var i = 0; i < nBytes; i += 4) { + words.push((Math.random() * 0x100000000) | 0); + } + + return new WordArray.init(words, nBytes); + } + }); + + /** + * Encoder namespace. + */ + var C_enc = C.enc = {}; + + /** + * Hex encoding strategy. + */ + var Hex = C_enc.Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var hexChars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 0x0f).toString(16)); + } + + return hexChars.join(''); + }, + + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse: function (hexStr) { + // Shortcut + var hexStrLength = hexStr.length; + + // Convert + var words = []; + for (var i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); + } + + return new WordArray.init(words, hexStrLength / 2); + } + }; + + /** + * Latin1 encoding strategy. + */ + var Latin1 = C_enc.Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var latin1Chars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + latin1Chars.push(String.fromCharCode(bite)); + } + + return latin1Chars.join(''); + }, + + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse: function (latin1Str) { + // Shortcut + var latin1StrLength = latin1Str.length; + + // Convert + var words = []; + for (var i = 0; i < latin1StrLength; i++) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); + } + + return new WordArray.init(words, latin1StrLength); + } + }; + + /** + * UTF-8 encoding strategy. + */ + var Utf8 = C_enc.Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify: function (wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error('Malformed UTF-8 data'); + } + }, + + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse: function (utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + } + }; + + /** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset: function () { + // Initial values + this._data = new WordArray.init(); + this._nDataBytes = 0; + }, + + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append: function (data) { + // Convert string to WordArray, else assume WordArray already + if (typeof data == 'string') { + data = Utf8.parse(data); + } + + // Append + this._data.concat(data); + this._nDataBytes += data.sigBytes; + }, + + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process: function (doFlush) { + // Shortcuts + var data = this._data; + var dataWords = data.words; + var dataSigBytes = data.sigBytes; + var blockSize = this.blockSize; + var blockSizeBytes = blockSize * 4; + + // Count blocks ready + var nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + // Round up to include partial blocks + nBlocksReady = Math.ceil(nBlocksReady); + } else { + // Round down to include only full blocks, + // less the number of blocks that must remain in the buffer + nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + + // Count words ready + var nWordsReady = nBlocksReady * blockSize; + + // Count bytes ready + var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); + + // Process blocks + if (nWordsReady) { + for (var offset = 0; offset < nWordsReady; offset += blockSize) { + // Perform concrete-algorithm logic + this._doProcessBlock(dataWords, offset); + } + + // Remove processed words + var processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + + // Return processed words + return new WordArray.init(processedWords, nBytesReady); + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone._data = this._data.clone(); + + return clone; + }, + + _minBufferSize: 0 + }); + + /** + * Abstract hasher template. + * + * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ + var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + */ + cfg: Base.extend(), + + /** + * Initializes a newly created hasher. + * + * @param {Object} cfg (Optional) The configuration options to use for this hash computation. + * + * @example + * + * var hasher = CryptoJS.algo.SHA256.create(); + */ + init: function (cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Set initial values + this.reset(); + }, + + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-hasher logic + this._doReset(); + }, + + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update: function (messageUpdate) { + // Append + this._append(messageUpdate); + + // Update the hash + this._process(); + + // Chainable + return this; + }, + + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Final message update + if (messageUpdate) { + this._append(messageUpdate); + } + + // Perform concrete-hasher logic + var hash = this._doFinalize(); + + return hash; + }, + + blockSize: 512/32, + + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} hasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + _createHelper: function (hasher) { + return function (message, cfg) { + return new hasher.init(cfg).finalize(message); + }; + }, + + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} hasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + _createHmacHelper: function (hasher) { + return function (message, key) { + return new C_algo.HMAC.init(hasher, key).finalize(message); + }; + } + }); + + /** + * Algorithm namespace. + */ + var C_algo = C.algo = {}; + + return C; +}(Math)); + +/* +CryptoJS v3.1.2 +code.google.com/p/crypto-js +(c) 2009-2013 by Jeff Mott. All rights reserved. +code.google.com/p/crypto-js/wiki/License +*/ +(function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Initialization and round constants tables + var H = []; + var K = []; + + // Compute constants + (function () { + function isPrime(n) { + var sqrtN = Math.sqrt(n); + for (var factor = 2; factor <= sqrtN; factor++) { + if (!(n % factor)) { + return false; + } + } + + return true; + } + + function getFractionalBits(n) { + return ((n - (n | 0)) * 0x100000000) | 0; + } + + var n = 2; + var nPrime = 0; + while (nPrime < 64) { + if (isPrime(n)) { + if (nPrime < 8) { + H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2)); + } + K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3)); + + nPrime++; + } + + n++; + } + }()); + + // Reusable object + var W = []; + + /** + * SHA-256 hash algorithm. + */ + var SHA256 = C_algo.SHA256 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init(H.slice(0)); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + var f = H[5]; + var g = H[6]; + var h = H[7]; + + // Computation + for (var i = 0; i < 64; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var gamma0x = W[i - 15]; + var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ + ((gamma0x << 14) | (gamma0x >>> 18)) ^ + (gamma0x >>> 3); + + var gamma1x = W[i - 2]; + var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ + ((gamma1x << 13) | (gamma1x >>> 19)) ^ + (gamma1x >>> 10); + + W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; + } + + var ch = (e & f) ^ (~e & g); + var maj = (a & b) ^ (a & c) ^ (b & c); + + var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); + var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); + + var t1 = h + sigma1 + ch + K[i] + W[i]; + var t2 = sigma0 + maj; + + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + H[5] = (H[5] + f) | 0; + H[6] = (H[6] + g) | 0; + H[7] = (H[7] + h) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ + C.SHA256 = Hasher._createHelper(SHA256); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ + C.HmacSHA256 = Hasher._createHmacHelper(SHA256); +}(Math)); + +/* + * JavaScript implementation of Password-Based Key Derivation Function 2 + * (PBKDF2) as defined in RFC 2898. + * Version 1.5 + * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Parvez Anandam + * parvez@anandam.com + * http://anandam.com/pbkdf2 + * + * Distributed under the BSD license + * + * Uses Paul Johnston's excellent SHA-1 JavaScript library sha1.js: + * http://pajhome.org.uk/crypt/md5/sha1.html + * (uses the binb_sha1(), rstr2binb(), binb2str(), rstr2hex() functions from that libary) + * + * Thanks to Felix Gartsman for pointing out a bug in version 1.0 + * Thanks to Thijs Van der Schaeghe for pointing out a bug in version 1.1 + * Thanks to Richard Gautier for asking to clarify dependencies in version 1.2 + * Updated contact information from version 1.3 + * Thanks to Stuart Heinrich for pointing out updates to PAJ's SHA-1 library in version 1.4 + */ + + +/* + * The four arguments to the constructor of the PBKDF2 object are + * the password, salt, number of iterations and number of bytes in + * generated key. This follows the RFC 2898 definition: PBKDF2 (P, S, c, dkLen) + * + * The method deriveKey takes two parameters, both callback functions: + * the first is used to provide status on the computation, the second + * is called with the result of the computation (the generated key in hex). + * + * Example of use: + * + * + * + * + *
+ * + */ + +function PBKDF2(password, salt, num_iterations, num_bytes) +{ + // Remember the password and salt + var m_bpassword = rstr2binb(password); + var m_salt = salt; + + // Total number of iterations + var m_total_iterations = num_iterations; + + // Run iterations in chunks instead of all at once, so as to not block. + // Define size of chunk here; adjust for slower or faster machines if necessary. + var m_iterations_in_chunk = 10; + + // Iteration counter + var m_iterations_done = 0; + + // Key length, as number of bytes + var m_key_length = num_bytes; + + // The hash cache + var m_hash = null; + + // The length (number of bytes) of the output of the pseudo-random function. + // Since HMAC-SHA1 is the standard, and what is used here, it's 20 bytes. + var m_hash_length = 20; + + // Number of hash-sized blocks in the derived key (called 'l' in RFC2898) + var m_total_blocks = Math.ceil(m_key_length/m_hash_length); + + // Start computation with the first block + var m_current_block = 1; + + // Used in the HMAC-SHA1 computations + var m_ipad = new Array(16); + var m_opad = new Array(16); + + // This is where the result of the iterations gets sotred + var m_buffer = new Array(0x0,0x0,0x0,0x0,0x0); + + // The result + var m_key = ""; + + // This object + var m_this_object = this; + + // The function to call with the result + var m_result_func; + + // The function to call with status after computing every chunk + var m_status_func; + + // Set up the HMAC-SHA1 computations + if (m_bpassword.length > 16) m_bpassword = binb_sha1(m_bpassword, password.length * chrsz); + for(var i = 0; i < 16; ++i) + { + m_ipad[i] = m_bpassword[i] ^ 0x36363636; + m_opad[i] = m_bpassword[i] ^ 0x5C5C5C5C; + } + + + // Starts the computation + this.deriveKey = function(status_callback, result_callback) + { + m_status_func = status_callback; + m_result_func = result_callback; + setTimeout(function() { m_this_object.do_PBKDF2_iterations() }, 0); + } + + + // The workhorse + this.do_PBKDF2_iterations = function() + { + var iterations = m_iterations_in_chunk; + if (m_total_iterations - m_iterations_done < m_iterations_in_chunk) + iterations = m_total_iterations - m_iterations_done; + + for(var i=0; i>(p+=this.DB-k);
+ }
+ else {
+ d = (this[i]>>(p-=k))&km;
+ if(p <= 0) { p += this.DB; --i; }
+ }
+ if(d > 0) m = true;
+ if(m) r += int2char(d);
+ }
+ }
+ return m?r:"0";
+}
+
+// (public) -this
+function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
+
+// (public) |this|
+function bnAbs() { return (this.s<0)?this.negate():this; }
+
+// (public) return + if this > a, - if this < a, 0 if equal
+function bnCompareTo(a) {
+ var r = this.s-a.s;
+ if(r != 0) return r;
+ var i = this.t;
+ r = i-a.t;
+ if(r != 0) return (this.s<0)?-r:r;
+ while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
+ return 0;
+}
+
+// returns bit length of the integer x
+function nbits(x) {
+ var r = 1, t;
+ if((t=x>>>16) != 0) { x = t; r += 16; }
+ if((t=x>>8) != 0) { x = t; r += 8; }
+ if((t=x>>4) != 0) { x = t; r += 4; }
+ if((t=x>>2) != 0) { x = t; r += 2; }
+ if((t=x>>1) != 0) { x = t; r += 1; }
+ return r;
+}
+
+// (public) return the number of bits in "this"
+function bnBitLength() {
+ if(this.t <= 0) return 0;
+ return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
+}
+
+// (protected) r = this << n*DB
+function bnpDLShiftTo(n,r) {
+ var i;
+ for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
+ for(i = n-1; i >= 0; --i) r[i] = 0;
+ r.t = this.t+n;
+ r.s = this.s;
+}
+
+// (protected) r = this >> n*DB
+function bnpDRShiftTo(n,r) {
+ for(var i = n; i < this.t; ++i) r[i-n] = this[i];
+ r.t = Math.max(this.t-n,0);
+ r.s = this.s;
+}
+
+// (protected) r = this << n
+function bnpLShiftTo(n,r) {
+ var bs = n%this.DB;
+ var cbs = this.DB-bs;
+ var bm = (1< >(p+=this.DB-8);
+ }
+ else {
+ d = (this[i]>>(p-=8))&0xff;
+ if(p <= 0) { p += this.DB; --i; }
+ }
+ if((d&0x80) != 0) d |= -256;
+ if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
+ if(k > 0 || d != this.s) r[k++] = d;
+ }
+ }
+ return r;
+}
+
+function bnEquals(a) { return(this.compareTo(a)==0); }
+function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
+function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
+
+// (protected) r = this op a (bitwise)
+function bnpBitwiseTo(a,op,r) {
+ var i, f, m = Math.min(a.t,this.t);
+ for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
+ if(a.t < this.t) {
+ f = a.s&this.DM;
+ for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
+ r.t = this.t;
+ }
+ else {
+ f = this.s&this.DM;
+ for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
+ r.t = a.t;
+ }
+ r.s = op(this.s,a.s);
+ r.clamp();
+}
+
+// (public) this & a
+function op_and(x,y) { return x&y; }
+function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
+
+// (public) this | a
+function op_or(x,y) { return x|y; }
+function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
+
+// (public) this ^ a
+function op_xor(x,y) { return x^y; }
+function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
+
+// (public) this & ~a
+function op_andnot(x,y) { return x&~y; }
+function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
+
+// (public) ~this
+function bnNot() {
+ var r = nbi();
+ for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
+ r.t = this.t;
+ r.s = ~this.s;
+ return r;
+}
+
+// (public) this << n
+function bnShiftLeft(n) {
+ var r = nbi();
+ if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
+ return r;
+}
+
+// (public) this >> n
+function bnShiftRight(n) {
+ var r = nbi();
+ if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
+ return r;
+}
+
+// return index of lowest 1-bit in x, x < 2^31
+function lbit(x) {
+ if(x == 0) return -1;
+ var r = 0;
+ if((x&0xffff) == 0) { x >>= 16; r += 16; }
+ if((x&0xff) == 0) { x >>= 8; r += 8; }
+ if((x&0xf) == 0) { x >>= 4; r += 4; }
+ if((x&3) == 0) { x >>= 2; r += 2; }
+ if((x&1) == 0) ++r;
+ return r;
+}
+
+// (public) returns index of lowest 1-bit (or -1 if none)
+function bnGetLowestSetBit() {
+ for(var i = 0; i < this.t; ++i)
+ if(this[i] != 0) return i*this.DB+lbit(this[i]);
+ if(this.s < 0) return this.t*this.DB;
+ return -1;
+}
+
+// return number of 1 bits in x
+function cbit(x) {
+ var r = 0;
+ while(x != 0) { x &= x-1; ++r; }
+ return r;
+}
+
+// (public) return number of set bits
+function bnBitCount() {
+ var r = 0, x = this.s&this.DM;
+ for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
+ return r;
+}
+
+// (public) true iff nth bit is set
+function bnTestBit(n) {
+ var j = Math.floor(n/this.DB);
+ if(j >= this.t) return(this.s!=0);
+ return((this[j]&(1<<(n%this.DB)))!=0);
+}
+
+// (protected) this op (1<
+ * This namespace privides following crytpgrahic classes.
+ *
+ * This class is just provide information about global functions
+ * defined in 'base64x.js'. The 'base64x.js' script file provides
+ * global functions for converting following data each other.
+ *
+ *
+ * All functions in 'base64x.js' are defined in {@link _global_} and not
+ * in this class.
+ *
+ * @class Base64URL and supplementary functions for Tom Wu's base64.js library
+ * @author Kenji Urushima
+ * @version 1.1 (07 May 2012)
+ * @requires base64.js
+ * @see 'jwjws'(JWS JavaScript Library) home page http://kjur.github.com/jsjws/
+ * @see 'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/
+ */
+function Base64x() {
+}
+
+// ==== string / byte array ================================
+/**
+ * convert a string to an array of character codes
+ * @param {String} s
+ * @return {Array of Numbers}
+ */
+function stoBA(s) {
+ var a = new Array();
+ for (var i = 0; i < s.length; i++) {
+ a[i] = s.charCodeAt(i);
+ }
+ return a;
+}
+
+/**
+ * convert an array of character codes to a string
+ * @param {Array of Numbers} a array of character codes
+ * @return {String} s
+ */
+function BAtos(a) {
+ var s = "";
+ for (var i = 0; i < a.length; i++) {
+ s = s + String.fromCharCode(a[i]);
+ }
+ return s;
+}
+
+// ==== byte array / hex ================================
+/**
+ * convert an array of bytes(Number) to hexadecimal string.
+ * @param {Array of Numbers} a array of bytes
+ * @return {String} hexadecimal string
+ */
+function BAtohex(a) {
+ var s = "";
+ for (var i = 0; i < a.length; i++) {
+ var hex1 = a[i].toString(16);
+ if (hex1.length == 1) hex1 = "0" + hex1;
+ s = s + hex1;
+ }
+ return s;
+}
+
+// ==== string / hex ================================
+/**
+ * convert a ASCII string to a hexadecimal string of ASCII codes.
+ * NOTE: This can't be used for non ASCII characters.
+ * @param {s} s ASCII string
+ * @return {String} hexadecimal string
+ */
+function stohex(s) {
+ return BAtohex(stoBA(s));
+}
+
+// ==== string / base64 ================================
+/**
+ * convert a ASCII string to a Base64 encoded string.
+ * NOTE: This can't be used for non ASCII characters.
+ * @param {s} s ASCII string
+ * @return {String} Base64 encoded string
+ */
+function stob64(s) {
+ return hex2b64(stohex(s));
+}
+
+// ==== string / base64url ================================
+/**
+ * convert a ASCII string to a Base64URL encoded string.
+ * NOTE: This can't be used for non ASCII characters.
+ * @param {s} s ASCII string
+ * @return {String} Base64URL encoded string
+ */
+function stob64u(s) {
+ return b64tob64u(hex2b64(stohex(s)));
+}
+
+/**
+ * convert a Base64URL encoded string to a ASCII string.
+ * NOTE: This can't be used for Base64URL encoded non ASCII characters.
+ * @param {s} s Base64URL encoded string
+ * @return {String} ASCII string
+ */
+function b64utos(s) {
+ return BAtos(b64toBA(b64utob64(s)));
+}
+
+// ==== base64 / base64url ================================
+/**
+ * convert a Base64 encoded string to a Base64URL encoded string.
+ * Example: "ab+c3f/==" → "ab-c3f_"
+ * @param {String} s Base64 encoded string
+ * @return {String} Base64URL encoded string
+ */
+function b64tob64u(s) {
+ s = s.replace(/\=/g, "");
+ s = s.replace(/\+/g, "-");
+ s = s.replace(/\//g, "_");
+ return s;
+}
+
+/**
+ * convert a Base64URL encoded string to a Base64 encoded string.
+ * Example: "ab-c3f_" → "ab+c3f/=="
+ * @param {String} s Base64URL encoded string
+ * @return {String} Base64 encoded string
+ */
+function b64utob64(s) {
+ if (s.length % 4 == 2) s = s + "==";
+ else if (s.length % 4 == 3) s = s + "=";
+ s = s.replace(/-/g, "+");
+ s = s.replace(/_/g, "/");
+ return s;
+}
+
+// ==== hex / base64url ================================
+/**
+ * convert a hexadecimal string to a Base64URL encoded string.
+ * @param {String} s hexadecimal string
+ * @return {String} Base64URL encoded string
+ */
+function hextob64u(s) {
+ return b64tob64u(hex2b64(s));
+}
+
+/**
+ * convert a Base64URL encoded string to a hexadecimal string.
+ * @param {String} s Base64URL encoded string
+ * @return {String} hexadecimal string
+ */
+function b64utohex(s) {
+ return b64tohex(b64utob64(s));
+}
+
+var utf8tob64u, b64utoutf8;
+
+if (typeof Buffer === 'function')
+{
+ utf8tob64u = function (s)
+ {
+ return b64tob64u(new Buffer(s, 'utf8').toString('base64'));
+ };
+
+ b64utoutf8 = function (s)
+ {
+ return new Buffer(b64utob64(s), 'base64').toString('utf8');
+ };
+}
+else
+{
+// ==== utf8 / base64url ================================
+/**
+ * convert a UTF-8 encoded string including CJK or Latin to a Base64URL encoded string.
+ * @param {String} s UTF-8 encoded string
+ * @return {String} Base64URL encoded string
+ * @since 1.1
+ */
+ utf8tob64u = function (s)
+ {
+ return hextob64u(uricmptohex(encodeURIComponentAll(s)));
+ };
+
+/**
+ * convert a Base64URL encoded string to a UTF-8 encoded string including CJK or Latin.
+ * @param {String} s Base64URL encoded string
+ * @return {String} UTF-8 encoded string
+ * @since 1.1
+ */
+ b64utoutf8 = function (s)
+ {
+ return decodeURIComponent(hextouricmp(b64utohex(s)));
+ };
+}
+
+// ==== utf8 / base64url ================================
+/**
+ * convert a UTF-8 encoded string including CJK or Latin to a Base64 encoded string.
+ * @param {String} s UTF-8 encoded string
+ * @return {String} Base64 encoded string
+ * @since 1.1.1
+ */
+function utf8tob64(s) {
+ return hex2b64(uricmptohex(encodeURIComponentAll(s)));
+}
+
+/**
+ * convert a Base64 encoded string to a UTF-8 encoded string including CJK or Latin.
+ * @param {String} s Base64 encoded string
+ * @return {String} UTF-8 encoded string
+ * @since 1.1.1
+ */
+function b64toutf8(s) {
+ return decodeURIComponent(hextouricmp(b64tohex(s)));
+}
+
+// ==== utf8 / hex ================================
+/**
+ * convert a UTF-8 encoded string including CJK or Latin to a hexadecimal encoded string.
+ * @param {String} s UTF-8 encoded string
+ * @return {String} hexadecimal encoded string
+ * @since 1.1.1
+ */
+function utf8tohex(s) {
+ return uricmptohex(encodeURIComponentAll(s));
+}
+
+/**
+ * convert a hexadecimal encoded string to a UTF-8 encoded string including CJK or Latin.
+ * Note that when input is improper hexadecimal string as UTF-8 string, this function returns
+ * 'null'.
+ * @param {String} s hexadecimal encoded string
+ * @return {String} UTF-8 encoded string or null
+ * @since 1.1.1
+ */
+function hextoutf8(s) {
+ return decodeURIComponent(hextouricmp(s));
+}
+
+/**
+ * convert a hexadecimal encoded string to raw string including non printable characters.
+ * @param {String} s hexadecimal encoded string
+ * @return {String} raw string
+ * @since 1.1.2
+ * @example
+ * hextorstr("610061") → "a\x00a"
+ */
+function hextorstr(sHex) {
+ var s = "";
+ for (var i = 0; i < sHex.length - 1; i += 2) {
+ s += String.fromCharCode(parseInt(sHex.substr(i, 2), 16));
+ }
+ return s;
+}
+
+/**
+ * convert a raw string including non printable characters to hexadecimal encoded string.
+ * @param {String} s raw string
+ * @return {String} hexadecimal encoded string
+ * @since 1.1.2
+ * @example
+ * rstrtohex("a\x00a") → "610061"
+ */
+function rstrtohex(s) {
+ var result = "";
+ for (var i = 0; i < s.length; i++) {
+ result += ("0" + s.charCodeAt(i).toString(16)).slice(-2);
+ }
+ return result;
+}
+
+// ==== URIComponent / hex ================================
+/**
+ * convert a URLComponent string such like "%67%68" to a hexadecimal string.
+ * @param {String} s URIComponent string such like "%67%68"
+ * @return {String} hexadecimal string
+ * @since 1.1
+ */
+function uricmptohex(s) {
+ return s.replace(/%/g, "");
+}
+
+/**
+ * convert a hexadecimal string to a URLComponent string such like "%67%68".
+ * @param {String} s hexadecimal string
+ * @return {String} URIComponent string such like "%67%68"
+ * @since 1.1
+ */
+function hextouricmp(s) {
+ return s.replace(/(..)/g, "%$1");
+}
+
+// ==== URIComponent ================================
+/**
+ * convert UTFa hexadecimal string to a URLComponent string such like "%67%68".
+ * Note that these "0-9A-Za-z!'()*-._~
" characters will not
+ * converted to "%xx" format by builtin 'encodeURIComponent()' function.
+ * However this 'encodeURIComponentAll()' function will convert
+ * all of characters into "%xx" format.
+ * @param {String} s hexadecimal string
+ * @return {String} URIComponent string such like "%67%68"
+ * @since 1.1
+ */
+function encodeURIComponentAll(u8) {
+ var s = encodeURIComponent(u8);
+ var s2 = "";
+ for (var i = 0; i < s.length; i++) {
+ if (s[i] == "%") {
+ s2 = s2 + s.substr(i, 3);
+ i = i + 2;
+ } else {
+ s2 = s2 + "%" + stohex(s[i]);
+ }
+ }
+ return s2;
+}
+
+// ==== new lines ================================
+/**
+ * convert all DOS new line("\r\n") to UNIX new line("\n") in
+ * a String "s".
+ * @param {String} s string
+ * @return {String} converted string
+ */
+function newline_toUnix(s) {
+ s = s.replace(/\r\n/mg, "\n");
+ return s;
+}
+
+/**
+ * convert all UNIX new line("\r\n") to DOS new line("\n") in
+ * a String "s".
+ * @param {String} s string
+ * @return {String} converted string
+ */
+function newline_toDos(s) {
+ s = s.replace(/\r\n/mg, "\n");
+ s = s.replace(/\n/mg, "\r\n");
+ return s;
+}
+
+
+/*! crypto-1.1.5.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/*
+ * crypto.js - Cryptographic Algorithm Provider class
+ *
+ * Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * http://kjur.github.com/jsrsasign/license
+ *
+ * The above copyright and license notice shall be
+ * included in all copies or substantial portions of the Software.
+ */
+
+/**
+ * @fileOverview
+ * @name crypto-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version 1.1.5 (2013-Oct-06)
+ * @since jsrsasign 2.2
+ * @license MIT License
+ */
+
+/**
+ * kjur's class library name space
+ * @name KJUR
+ * @namespace kjur's class library name space
+ */
+if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
+/**
+ * kjur's cryptographic algorithm provider library name space
+ *
+ *
+ * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
+ *
+ * Currently this supports following algorithm and providers combination:
+ *
+ *
+ * @example
+ * // CryptoJS provider sample
+ * <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/core.js"></script>
+ * <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/sha1.js"></script>
+ * <script src="crypto-1.0.js"></script>
+ * var md = new KJUR.crypto.MessageDigest({alg: "sha1", prov: "cryptojs"});
+ * md.updateString('aaa')
+ * var mdHex = md.digest()
+ *
+ * // SJCL(Stanford JavaScript Crypto Library) provider sample
+ * <script src="http://bitwiseshiftleft.github.io/sjcl/sjcl.js"></script>
+ * <script src="crypto-1.0.js"></script>
+ * var md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "sjcl"}); // sjcl supports sha256 only
+ * md.updateString('aaa')
+ * var mdHex = md.digest()
+ */
+KJUR.crypto.MessageDigest = function(params) {
+ var md = null;
+ var algName = null;
+ var provName = null;
+
+ /**
+ * set hash algorithm and provider
+ * @name setAlgAndProvider
+ * @memberOf KJUR.crypto.MessageDigest
+ * @function
+ * @param {String} alg hash algorithm name
+ * @param {String} prov provider name
+ * @description
+ * @example
+ * // for SHA1
+ * md.setAlgAndProvider('sha1', 'cryptojs');
+ * // for RIPEMD160
+ * md.setAlgAndProvider('ripemd160', 'cryptojs');
+ */
+ this.setAlgAndProvider = function(alg, prov) {
+ if (alg != null && prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
+
+ // for cryptojs
+ if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(alg) != -1 &&
+ prov == 'cryptojs') {
+ try {
+ this.md = eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[alg]).create();
+ } catch (ex) {
+ throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
+ }
+ this.updateString = function(str) {
+ this.md.update(str);
+ };
+ this.updateHex = function(hex) {
+ var wHex = CryptoJS.enc.Hex.parse(hex);
+ this.md.update(wHex);
+ };
+ this.digest = function() {
+ var hash = this.md.finalize();
+ return hash.toString(CryptoJS.enc.Hex);
+ };
+ this.digestString = function(str) {
+ this.updateString(str);
+ return this.digest();
+ };
+ this.digestHex = function(hex) {
+ this.updateHex(hex);
+ return this.digest();
+ };
+ }
+ if (':sha256:'.indexOf(alg) != -1 &&
+ prov == 'sjcl') {
+ try {
+ this.md = new sjcl.hash.sha256();
+ } catch (ex) {
+ throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
+ }
+ this.updateString = function(str) {
+ this.md.update(str);
+ };
+ this.updateHex = function(hex) {
+ var baHex = sjcl.codec.hex.toBits(hex);
+ this.md.update(baHex);
+ };
+ this.digest = function() {
+ var hash = this.md.finalize();
+ return sjcl.codec.hex.fromBits(hash);
+ };
+ this.digestString = function(str) {
+ this.updateString(str);
+ return this.digest();
+ };
+ this.digestHex = function(hex) {
+ this.updateHex(hex);
+ return this.digest();
+ };
+ }
+ };
+
+ /**
+ * update digest by specified string
+ * @name updateString
+ * @memberOf KJUR.crypto.MessageDigest
+ * @function
+ * @param {String} str string to update
+ * @description
+ * @example
+ * md.updateString('New York');
+ */
+ this.updateString = function(str) {
+ throw "updateString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+ };
+
+ /**
+ * update digest by specified hexadecimal string
+ * @name updateHex
+ * @memberOf KJUR.crypto.MessageDigest
+ * @function
+ * @param {String} hex hexadecimal string to update
+ * @description
+ * @example
+ * md.updateHex('0afe36');
+ */
+ this.updateHex = function(hex) {
+ throw "updateHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+ };
+
+ /**
+ * completes hash calculation and returns hash result
+ * @name digest
+ * @memberOf KJUR.crypto.MessageDigest
+ * @function
+ * @description
+ * @example
+ * md.digest()
+ */
+ this.digest = function() {
+ throw "digest() not supported for this alg/prov: " + this.algName + "/" + this.provName;
+ };
+
+ /**
+ * performs final update on the digest using string, then completes the digest computation
+ * @name digestString
+ * @memberOf KJUR.crypto.MessageDigest
+ * @function
+ * @param {String} str string to final update
+ * @description
+ * @example
+ * md.digestString('aaa')
+ */
+ this.digestString = function(str) {
+ throw "digestString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+ };
+
+ /**
+ * performs final update on the digest using hexadecimal string, then completes the digest computation
+ * @name digestHex
+ * @memberOf KJUR.crypto.MessageDigest
+ * @function
+ * @param {String} hex hexadecimal string to final update
+ * @description
+ * @example
+ * md.digestHex('0f2abd')
+ */
+ this.digestHex = function(hex) {
+ throw "digestHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+ };
+
+ if (params !== undefined) {
+ if (params['alg'] !== undefined) {
+ this.algName = params['alg'];
+ if (params['prov'] === undefined)
+ this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+ this.setAlgAndProvider(this.algName, this.provName);
+ }
+ }
+};
+
+/**
+ * Mac(Message Authentication Code) class which is very similar to java.security.Mac class
+ * @name KJUR.crypto.Mac
+ * @class Mac class which is very similar to java.security.Mac class
+ * @param {Array} params parameters for constructor
+ * @description
+ *
+ * Currently this supports following algorithm and providers combination:
+ *
+ *
+ * NOTE: HmacSHA224 and HmacSHA384 issue was fixed since jsrsasign 4.1.4.
+ * Please use 'ext/cryptojs-312-core-fix*.js' instead of 'core.js' of original CryptoJS
+ * to avoid those issue.
+ * @example
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA1", prov: "cryptojs", "pass": "pass"});
+ * mac.updateString('aaa')
+ * var macHex = md.doFinal()
+ */
+KJUR.crypto.Mac = function(params) {
+ var mac = null;
+ var pass = null;
+ var algName = null;
+ var provName = null;
+ var algProv = null;
+
+ this.setAlgAndProvider = function(alg, prov) {
+ if (alg == null) alg = "hmacsha1";
+
+ alg = alg.toLowerCase();
+ if (alg.substr(0, 4) != "hmac") {
+ throw "setAlgAndProvider unsupported HMAC alg: " + alg;
+ }
+
+ if (prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
+ this.algProv = alg + "/" + prov;
+
+ var hashAlg = alg.substr(4);
+
+ // for cryptojs
+ if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(hashAlg) != -1 &&
+ prov == 'cryptojs') {
+ try {
+ var mdObj = eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[hashAlg]);
+ this.mac = CryptoJS.algo.HMAC.create(mdObj, this.pass);
+ } catch (ex) {
+ throw "setAlgAndProvider hash alg set fail hashAlg=" + hashAlg + "/" + ex;
+ }
+ this.updateString = function(str) {
+ this.mac.update(str);
+ };
+ this.updateHex = function(hex) {
+ var wHex = CryptoJS.enc.Hex.parse(hex);
+ this.mac.update(wHex);
+ };
+ this.doFinal = function() {
+ var hash = this.mac.finalize();
+ return hash.toString(CryptoJS.enc.Hex);
+ };
+ this.doFinalString = function(str) {
+ this.updateString(str);
+ return this.doFinal();
+ };
+ this.doFinalHex = function(hex) {
+ this.updateHex(hex);
+ return this.doFinal();
+ };
+ }
+ };
+
+ /**
+ * update digest by specified string
+ * @name updateString
+ * @memberOf KJUR.crypto.Mac
+ * @function
+ * @param {String} str string to update
+ * @description
+ * @example
+ * md.updateString('New York');
+ */
+ this.updateString = function(str) {
+ throw "updateString(str) not supported for this alg/prov: " + this.algProv;
+ };
+
+ /**
+ * update digest by specified hexadecimal string
+ * @name updateHex
+ * @memberOf KJUR.crypto.Mac
+ * @function
+ * @param {String} hex hexadecimal string to update
+ * @description
+ * @example
+ * md.updateHex('0afe36');
+ */
+ this.updateHex = function(hex) {
+ throw "updateHex(hex) not supported for this alg/prov: " + this.algProv;
+ };
+
+ /**
+ * completes hash calculation and returns hash result
+ * @name doFinal
+ * @memberOf KJUR.crypto.Mac
+ * @function
+ * @description
+ * @example
+ * md.digest()
+ */
+ this.doFinal = function() {
+ throw "digest() not supported for this alg/prov: " + this.algProv;
+ };
+
+ /**
+ * performs final update on the digest using string, then completes the digest computation
+ * @name doFinalString
+ * @memberOf KJUR.crypto.Mac
+ * @function
+ * @param {String} str string to final update
+ * @description
+ * @example
+ * md.digestString('aaa')
+ */
+ this.doFinalString = function(str) {
+ throw "digestString(str) not supported for this alg/prov: " + this.algProv;
+ };
+
+ /**
+ * performs final update on the digest using hexadecimal string,
+ * then completes the digest computation
+ * @name doFinalHex
+ * @memberOf KJUR.crypto.Mac
+ * @function
+ * @param {String} hex hexadecimal string to final update
+ * @description
+ * @example
+ * md.digestHex('0f2abd')
+ */
+ this.doFinalHex = function(hex) {
+ throw "digestHex(hex) not supported for this alg/prov: " + this.algProv;
+ };
+
+ if (params !== undefined) {
+ if (params['pass'] !== undefined) {
+ this.pass = params['pass'];
+ }
+ if (params['alg'] !== undefined) {
+ this.algName = params['alg'];
+ if (params['prov'] === undefined)
+ this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+ this.setAlgAndProvider(this.algName, this.provName);
+ }
+ }
+};
+
+/**
+ * Signature class which is very similar to java.security.Signature class
+ * @name KJUR.crypto.Signature
+ * @class Signature class which is very similar to java.security.Signature class
+ * @param {Array} params parameters for constructor
+ * @property {String} state Current state of this signature object whether 'SIGN', 'VERIFY' or null
+ * @description
+ *
+ * As for params of constructor's argument, it can be specify following attributes:
+ *
+ *
+ * SUPPORTED ALGORITHMS AND PROVIDERS
+ * This Signature class supports following signature algorithm and provider names:
+ *
+ *
+ * Here are supported elliptic cryptographic curve names and their aliases for ECDSA:
+ *
+ *
+ * NOTE1: DSA signing algorithm is also supported since crypto 1.1.5.
+ * EXAMPLES
+ * @example
+ * // RSA signature generation
+ * var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
+ * sig.init(prvKeyPEM);
+ * sig.updateString('aaa');
+ * var hSigVal = sig.sign();
+ *
+ * // DSA signature validation
+ * var sig2 = new KJUR.crypto.Signature({"alg": "SHA1withDSA"});
+ * sig2.init(certPEM);
+ * sig.updateString('aaa');
+ * var isValid = sig2.verify(hSigVal);
+ *
+ * // ECDSA signing
+ * var sig = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
+ * sig.init(prvKeyPEM);
+ * sig.updateString('aaa');
+ * var sigValueHex = sig.sign();
+ *
+ * // ECDSA verifying
+ * var sig2 = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
+ * sig.init(certPEM);
+ * sig.updateString('aaa');
+ * var isValid = sig.verify(sigValueHex);
+ */
+KJUR.crypto.Signature = function(params) {
+ var prvKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for signing
+ var pubKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for verifying
+
+ var md = null; // KJUR.crypto.MessageDigest object
+ var sig = null;
+ var algName = null;
+ var provName = null;
+ var algProvName = null;
+ var mdAlgName = null;
+ var pubkeyAlgName = null; // rsa,ecdsa,rsaandmgf1(=rsapss)
+ var state = null;
+ var pssSaltLen = -1;
+ var initParams = null;
+
+ var sHashHex = null; // hex hash value for hex
+ var hDigestInfo = null;
+ var hPaddedDigestInfo = null;
+ var hSign = null;
+
+ this._setAlgNames = function() {
+ if (this.algName.match(/^(.+)with(.+)$/)) {
+ this.mdAlgName = RegExp.$1.toLowerCase();
+ this.pubkeyAlgName = RegExp.$2.toLowerCase();
+ }
+ };
+
+ this._zeroPaddingOfSignature = function(hex, bitLength) {
+ var s = "";
+ var nZero = bitLength / 4 - hex.length;
+ for (var i = 0; i < nZero; i++) {
+ s = s + "0";
+ }
+ return s + hex;
+ };
+
+ /**
+ * set signature algorithm and provider
+ * @name setAlgAndProvider
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @param {String} alg signature algorithm name
+ * @param {String} prov provider name
+ * @description
+ * @example
+ * md.setAlgAndProvider('SHA1withRSA', 'cryptojs/jsrsa');
+ */
+ this.setAlgAndProvider = function(alg, prov) {
+ this._setAlgNames();
+ if (prov != 'cryptojs/jsrsa')
+ throw "provider not supported: " + prov;
+
+ if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(this.mdAlgName) != -1) {
+ try {
+ this.md = new KJUR.crypto.MessageDigest({'alg':this.mdAlgName});
+ } catch (ex) {
+ throw "setAlgAndProvider hash alg set fail alg=" +
+ this.mdAlgName + "/" + ex;
+ }
+
+ this.init = function(keyparam, pass) {
+ var keyObj = null;
+ try {
+ if (pass === undefined) {
+ keyObj = KEYUTIL.getKey(keyparam);
+ } else {
+ keyObj = KEYUTIL.getKey(keyparam, pass);
+ }
+ } catch (ex) {
+ throw "init failed:" + ex;
+ }
+
+ if (keyObj.isPrivate === true) {
+ this.prvKey = keyObj;
+ this.state = "SIGN";
+ } else if (keyObj.isPublic === true) {
+ this.pubKey = keyObj;
+ this.state = "VERIFY";
+ } else {
+ throw "init failed.:" + keyObj;
+ }
+ };
+
+ this.initSign = function(params) {
+ if (typeof params['ecprvhex'] == 'string' &&
+ typeof params['eccurvename'] == 'string') {
+ this.ecprvhex = params['ecprvhex'];
+ this.eccurvename = params['eccurvename'];
+ } else {
+ this.prvKey = params;
+ }
+ this.state = "SIGN";
+ };
+
+ this.initVerifyByPublicKey = function(params) {
+ if (typeof params['ecpubhex'] == 'string' &&
+ typeof params['eccurvename'] == 'string') {
+ this.ecpubhex = params['ecpubhex'];
+ this.eccurvename = params['eccurvename'];
+ } else if (params instanceof KJUR.crypto.ECDSA) {
+ this.pubKey = params;
+ } else if (params instanceof RSAKey) {
+ this.pubKey = params;
+ }
+ this.state = "VERIFY";
+ };
+
+ this.initVerifyByCertificatePEM = function(certPEM) {
+ var x509 = new X509();
+ x509.readCertPEM(certPEM);
+ this.pubKey = x509.subjectPublicKeyRSA;
+ this.state = "VERIFY";
+ };
+
+ this.updateString = function(str) {
+ this.md.updateString(str);
+ };
+ this.updateHex = function(hex) {
+ this.md.updateHex(hex);
+ };
+
+ this.sign = function() {
+ this.sHashHex = this.md.digest();
+ if (typeof this.ecprvhex != "undefined" &&
+ typeof this.eccurvename != "undefined") {
+ var ec = new KJUR.crypto.ECDSA({'curve': this.eccurvename});
+ this.hSign = ec.signHex(this.sHashHex, this.ecprvhex);
+ } else if (this.pubkeyAlgName == "rsaandmgf1") {
+ this.hSign = this.prvKey.signWithMessageHashPSS(this.sHashHex,
+ this.mdAlgName,
+ this.pssSaltLen);
+ } else if (this.pubkeyAlgName == "rsa") {
+ this.hSign = this.prvKey.signWithMessageHash(this.sHashHex,
+ this.mdAlgName);
+ } else if (this.prvKey instanceof KJUR.crypto.ECDSA) {
+ this.hSign = this.prvKey.signWithMessageHash(this.sHashHex);
+ } else if (this.prvKey instanceof KJUR.crypto.DSA) {
+ this.hSign = this.prvKey.signWithMessageHash(this.sHashHex);
+ } else {
+ throw "Signature: unsupported public key alg: " + this.pubkeyAlgName;
+ }
+ return this.hSign;
+ };
+ this.signString = function(str) {
+ this.updateString(str);
+ this.sign();
+ };
+ this.signHex = function(hex) {
+ this.updateHex(hex);
+ this.sign();
+ };
+ this.verify = function(hSigVal) {
+ this.sHashHex = this.md.digest();
+ if (typeof this.ecpubhex != "undefined" &&
+ typeof this.eccurvename != "undefined") {
+ var ec = new KJUR.crypto.ECDSA({curve: this.eccurvename});
+ return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex);
+ } else if (this.pubkeyAlgName == "rsaandmgf1") {
+ return this.pubKey.verifyWithMessageHashPSS(this.sHashHex, hSigVal,
+ this.mdAlgName,
+ this.pssSaltLen);
+ } else if (this.pubkeyAlgName == "rsa") {
+ return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+ } else if (this.pubKey instanceof KJUR.crypto.ECDSA) {
+ return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+ } else if (this.pubKey instanceof KJUR.crypto.DSA) {
+ return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+ } else {
+ throw "Signature: unsupported public key alg: " + this.pubkeyAlgName;
+ }
+ };
+ }
+ };
+
+ /**
+ * Initialize this object for signing or verifying depends on key
+ * @name init
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @param {Object} key specifying public or private key as plain/encrypted PKCS#5/8 PEM file, certificate PEM or {@link RSAKey}, {@link KJUR.crypto.DSA} or {@link KJUR.crypto.ECDSA} object
+ * @param {String} pass (OPTION) passcode for encrypted private key
+ * @since crypto 1.1.3
+ * @description
+ * This method is very useful initialize method for Signature class since
+ * you just specify key then this method will automatically initialize it
+ * using {@link KEYUTIL.getKey} method.
+ * As for 'key', following argument type are supported:
+ * signing
+ *
+ *
+ * verification
+ *
+ *
+ * @example
+ * sig.init(sCertPEM)
+ */
+ this.init = function(key, pass) {
+ throw "init(key, pass) not supported for this alg:prov=" +
+ this.algProvName;
+ };
+
+ /**
+ * Initialize this object for verifying with a public key
+ * @name initVerifyByPublicKey
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @param {Object} param RSAKey object of public key or associative array for ECDSA
+ * @since 1.0.2
+ * @deprecated from crypto 1.1.5. please use init() method instead.
+ * @description
+ * Public key information will be provided as 'param' parameter and the value will be
+ * following:
+ *
+ *
+ * @example
+ * sig.initVerifyByPublicKey(rsaPrvKey)
+ */
+ this.initVerifyByPublicKey = function(rsaPubKey) {
+ throw "initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov=" +
+ this.algProvName;
+ };
+
+ /**
+ * Initialize this object for verifying with a certficate
+ * @name initVerifyByCertificatePEM
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @param {String} certPEM PEM formatted string of certificate
+ * @since 1.0.2
+ * @deprecated from crypto 1.1.5. please use init() method instead.
+ * @description
+ * @example
+ * sig.initVerifyByCertificatePEM(certPEM)
+ */
+ this.initVerifyByCertificatePEM = function(certPEM) {
+ throw "initVerifyByCertificatePEM(certPEM) not supported for this alg:prov=" +
+ this.algProvName;
+ };
+
+ /**
+ * Initialize this object for signing
+ * @name initSign
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @param {Object} param RSAKey object of public key or associative array for ECDSA
+ * @deprecated from crypto 1.1.5. please use init() method instead.
+ * @description
+ * Private key information will be provided as 'param' parameter and the value will be
+ * following:
+ * {'ecpubhex': '041f..', 'eccurvename': 'secp256r1'}
)
+ *
+ *
+ * @example
+ * sig.initSign(prvKey)
+ */
+ this.initSign = function(prvKey) {
+ throw "initSign(prvKey) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * Updates the data to be signed or verified by a string
+ * @name updateString
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @param {String} str string to use for the update
+ * @description
+ * @example
+ * sig.updateString('aaa')
+ */
+ this.updateString = function(str) {
+ throw "updateString(str) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * Updates the data to be signed or verified by a hexadecimal string
+ * @name updateHex
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @param {String} hex hexadecimal string to use for the update
+ * @description
+ * @example
+ * sig.updateHex('1f2f3f')
+ */
+ this.updateHex = function(hex) {
+ throw "updateHex(hex) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * Returns the signature bytes of all data updates as a hexadecimal string
+ * @name sign
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @return the signature bytes as a hexadecimal string
+ * @description
+ * @example
+ * var hSigValue = sig.sign()
+ */
+ this.sign = function() {
+ throw "sign() not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * performs final update on the sign using string, then returns the signature bytes of all data updates as a hexadecimal string
+ * @name signString
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @param {String} str string to final update
+ * @return the signature bytes of a hexadecimal string
+ * @description
+ * @example
+ * var hSigValue = sig.signString('aaa')
+ */
+ this.signString = function(str) {
+ throw "digestString(str) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * performs final update on the sign using hexadecimal string, then returns the signature bytes of all data updates as a hexadecimal string
+ * @name signHex
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @param {String} hex hexadecimal string to final update
+ * @return the signature bytes of a hexadecimal string
+ * @description
+ * @example
+ * var hSigValue = sig.signHex('1fdc33')
+ */
+ this.signHex = function(hex) {
+ throw "digestHex(hex) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * verifies the passed-in signature.
+ * @name verify
+ * @memberOf KJUR.crypto.Signature
+ * @function
+ * @param {String} str string to final update
+ * @return {Boolean} true if the signature was verified, otherwise false
+ * @description
+ * @example
+ * var isValid = sig.verify('1fbcefdca4823a7(snip)')
+ */
+ this.verify = function(hSigVal) {
+ throw "verify(hSigVal) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ this.initParams = params;
+
+ if (params !== undefined) {
+ if (params['alg'] !== undefined) {
+ this.algName = params['alg'];
+ if (params['prov'] === undefined) {
+ this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+ } else {
+ this.provName = params['prov'];
+ }
+ this.algProvName = this.algName + ":" + this.provName;
+ this.setAlgAndProvider(this.algName, this.provName);
+ this._setAlgNames();
+ }
+
+ if (params['psssaltlen'] !== undefined) this.pssSaltLen = params['psssaltlen'];
+
+ if (params['prvkeypem'] !== undefined) {
+ if (params['prvkeypas'] !== undefined) {
+ throw "both prvkeypem and prvkeypas parameters not supported";
+ } else {
+ try {
+ var prvKey = new RSAKey();
+ prvKey.readPrivateKeyFromPEMString(params['prvkeypem']);
+ this.initSign(prvKey);
+ } catch (ex) {
+ throw "fatal error to load pem private key: " + ex;
+ }
+ }
+ }
+ }
+};
+
+/**
+ * static object for cryptographic function utilities
+ * @name KJUR.crypto.OID
+ * @class static object for cryptography related OIDs
+ * @property {Array} oidhex2name key value of hexadecimal OID and its name
+ * (ex. '2a8648ce3d030107' and 'secp256r1')
+ * @since crypto 1.1.3
+ * @description
+ */
+
+
+KJUR.crypto.OID = new function() {
+ this.oidhex2name = {
+ '2a864886f70d010101': 'rsaEncryption',
+ '2a8648ce3d0201': 'ecPublicKey',
+ '2a8648ce380401': 'dsa',
+ '2a8648ce3d030107': 'secp256r1',
+ '2b8104001f': 'secp192k1',
+ '2b81040021': 'secp224r1',
+ '2b8104000a': 'secp256k1',
+ '2b81040023': 'secp521r1',
+ '2b81040022': 'secp384r1',
+ '2a8648ce380403': 'SHA1withDSA', // 1.2.840.10040.4.3
+ '608648016503040301': 'SHA224withDSA', // 2.16.840.1.101.3.4.3.1
+ '608648016503040302': 'SHA256withDSA', // 2.16.840.1.101.3.4.3.2
+ };
+};
+
+/*! rsasign-1.2.7.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/*
+ * rsa-sign.js - adding signing functions to RSAKey class.
+ *
+ * version: 1.2.7 (2013 Aug 25)
+ *
+ * Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * http://kjur.github.com/jsrsasign/license/
+ *
+ * The above copyright and license notice shall be
+ * included in all copies or substantial portions of the Software.
+ */
+
+/**
+ * @fileOverview
+ * @name rsasign-1.2.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version rsasign 1.2.7
+ * @license MIT License
+ */
+
+var _RE_HEXDECONLY = new RegExp("");
+_RE_HEXDECONLY.compile("[^0-9a-f]", "gi");
+
+// ========================================================================
+// Signature Generation
+// ========================================================================
+
+function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
+ var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
+ var sHashHex = hashFunc(s);
+
+ return KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, keySize);
+}
+
+function _zeroPaddingOfSignature(hex, bitLength) {
+ var s = "";
+ var nZero = bitLength / 4 - hex.length;
+ for (var i = 0; i < nZero; i++) {
+ s = s + "0";
+ }
+ return s + hex;
+}
+
+/**
+ * sign for a message string with RSA private key.{'ecprvhex': '1d3f..', 'eccurvename': 'secp256r1'}
)
+ * @name signString
+ * @memberOf RSAKey
+ * @function
+ * @param {String} s message string to be signed.
+ * @param {String} hashAlg hash algorithm name for signing.
+ * @return returns hexadecimal string of signature value.
+ */
+function _rsasign_signString(s, hashAlg) {
+ var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
+ var sHashHex = hashFunc(s);
+
+ return this.signWithMessageHash(sHashHex, hashAlg);
+}
+
+/**
+ * sign hash value of message to be signed with RSA private key.
+ * @name signWithMessageHash
+ * @memberOf RSAKey
+ * @function
+ * @param {String} sHashHex hexadecimal string of hash value of message to be signed.
+ * @param {String} hashAlg hash algorithm name for signing.
+ * @return returns hexadecimal string of signature value.
+ * @since rsasign 1.2.6
+ */
+function _rsasign_signWithMessageHash(sHashHex, hashAlg) {
+ var hPM = KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, this.n.bitLength());
+ var biPaddedMessage = parseBigInt(hPM, 16);
+ var biSign = this.doPrivate(biPaddedMessage);
+ var hexSign = biSign.toString(16);
+ return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
+}
+
+function _rsasign_signStringWithSHA1(s) {
+ return _rsasign_signString.call(this, s, 'sha1');
+}
+
+function _rsasign_signStringWithSHA256(s) {
+ return _rsasign_signString.call(this, s, 'sha256');
+}
+
+// PKCS#1 (PSS) mask generation function
+function pss_mgf1_str(seed, len, hash) {
+ var mask = '', i = 0;
+
+ while (mask.length < len) {
+ mask += hextorstr(hash(rstrtohex(seed + String.fromCharCode.apply(String, [
+ (i & 0xff000000) >> 24,
+ (i & 0x00ff0000) >> 16,
+ (i & 0x0000ff00) >> 8,
+ i & 0x000000ff]))));
+ i += 1;
+ }
+
+ return mask;
+}
+
+/**
+ * sign for a message string with RSA private key by PKCS#1 PSS signing.
+ * @name signStringPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} s message string to be signed.
+ * @param {String} hashAlg hash algorithm name for signing.
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ * There are two special values:
+ *
+ *
+ * DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
+ * @return returns hexadecimal string of signature value.
+ */
+function _rsasign_signStringPSS(s, hashAlg, sLen) {
+ var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); }
+ var hHash = hashFunc(rstrtohex(s));
+
+ if (sLen === undefined) sLen = -1;
+ return this.signWithMessageHashPSS(hHash, hashAlg, sLen);
+}
+
+/**
+ * sign hash value of message with RSA private key by PKCS#1 PSS signing.
+ * @name signWithMessageHashPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} hHash hexadecimal hash value of message to be signed.
+ * @param {String} hashAlg hash algorithm name for signing.
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ * There are two special values:
+ *
+ *
+ * DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
+ * @return returns hexadecimal string of signature value.
+ * @since rsasign 1.2.6
+ */
+function _rsasign_signWithMessageHashPSS(hHash, hashAlg, sLen) {
+ var mHash = hextorstr(hHash);
+ var hLen = mHash.length;
+ var emBits = this.n.bitLength() - 1;
+ var emLen = Math.ceil(emBits / 8);
+ var i;
+ var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); }
+
+ if (sLen === -1 || sLen === undefined) {
+ sLen = hLen; // same as hash length
+ } else if (sLen === -2) {
+ sLen = emLen - hLen - 2; // maximum
+ } else if (sLen < -2) {
+ throw "invalid salt length";
+ }
+
+ if (emLen < (hLen + sLen + 2)) {
+ throw "data too long";
+ }
+
+ var salt = '';
+
+ if (sLen > 0) {
+ salt = new Array(sLen);
+ new SecureRandom().nextBytes(salt);
+ salt = String.fromCharCode.apply(String, salt);
+ }
+
+ var H = hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash + salt)));
+ var PS = [];
+
+ for (i = 0; i < emLen - sLen - hLen - 2; i += 1) {
+ PS[i] = 0x00;
+ }
+
+ var DB = String.fromCharCode.apply(String, PS) + '\x01' + salt;
+ var dbMask = pss_mgf1_str(H, DB.length, hashFunc);
+ var maskedDB = [];
+
+ for (i = 0; i < DB.length; i += 1) {
+ maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+ }
+
+ var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
+ maskedDB[0] &= ~mask;
+
+ for (i = 0; i < hLen; i++) {
+ maskedDB.push(H.charCodeAt(i));
+ }
+
+ maskedDB.push(0xbc);
+
+ return _zeroPaddingOfSignature(this.doPrivate(new BigInteger(maskedDB)).toString(16),
+ this.n.bitLength());
+}
+
+// ========================================================================
+// Signature Verification
+// ========================================================================
+
+function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
+ var rsa = new RSAKey();
+ rsa.setPublic(hN, hE);
+ var biDecryptedSig = rsa.doPublic(biSig);
+ return biDecryptedSig;
+}
+
+function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
+ var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
+ var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
+ return hDigestInfo;
+}
+
+function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
+ for (var algName in KJUR.crypto.Util.DIGESTINFOHEAD) {
+ var head = KJUR.crypto.Util.DIGESTINFOHEAD[algName];
+ var len = head.length;
+ if (hDigestInfo.substring(0, len) == head) {
+ var a = [algName, hDigestInfo.substring(len)];
+ return a;
+ }
+ }
+ return [];
+}
+
+function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
+ var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
+ var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
+ if (digestInfoAry.length == 0) return false;
+ var algName = digestInfoAry[0];
+ var diHashValue = digestInfoAry[1];
+ var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
+ var msgHashValue = ff(sMsg);
+ return (diHashValue == msgHashValue);
+}
+
+function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
+ var biSig = parseBigInt(hSig, 16);
+ var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
+ this.n.toString(16),
+ this.e.toString(16));
+ return result;
+}
+
+/**
+ * verifies a sigature for a message string with RSA public key.
+ * @name verifyString
+ * @memberOf RSAKey#
+ * @function
+ * @param {String} sMsg message string to be verified.
+ * @param {String} hSig hexadecimal string of siganture.
+ * non-hexadecimal charactors including new lines will be ignored.
+ * @return returns 1 if valid, otherwise 0
+ */
+function _rsasign_verifyString(sMsg, hSig) {
+ hSig = hSig.replace(_RE_HEXDECONLY, '');
+ hSig = hSig.replace(/[ \n]+/g, "");
+ var biSig = parseBigInt(hSig, 16);
+ if (biSig.bitLength() > this.n.bitLength()) return 0;
+ var biDecryptedSig = this.doPublic(biSig);
+ var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
+ var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
+
+ if (digestInfoAry.length == 0) return false;
+ var algName = digestInfoAry[0];
+ var diHashValue = digestInfoAry[1];
+ var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
+ var msgHashValue = ff(sMsg);
+ return (diHashValue == msgHashValue);
+}
+
+/**
+ * verifies a sigature for a message string with RSA public key.
+ * @name verifyWithMessageHash
+ * @memberOf RSAKey
+ * @function
+ * @param {String} sHashHex hexadecimal hash value of message to be verified.
+ * @param {String} hSig hexadecimal string of siganture.
+ * non-hexadecimal charactors including new lines will be ignored.
+ * @return returns 1 if valid, otherwise 0
+ * @since rsasign 1.2.6
+ */
+function _rsasign_verifyWithMessageHash(sHashHex, hSig) {
+ hSig = hSig.replace(_RE_HEXDECONLY, '');
+ hSig = hSig.replace(/[ \n]+/g, "");
+ var biSig = parseBigInt(hSig, 16);
+ if (biSig.bitLength() > this.n.bitLength()) return 0;
+ var biDecryptedSig = this.doPublic(biSig);
+ var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
+ var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
+
+ if (digestInfoAry.length == 0) return false;
+ var algName = digestInfoAry[0];
+ var diHashValue = digestInfoAry[1];
+ return (diHashValue == sHashHex);
+}
+
+/**
+ * verifies a sigature for a message string with RSA public key by PKCS#1 PSS sign.
+ * @name verifyStringPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} sMsg message string to be verified.
+ * @param {String} hSig hexadecimal string of signature value
+ * @param {String} hashAlg hash algorithm name
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ * There are two special values:
+ *
+ *
+ * DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
+ * @return returns true if valid, otherwise false
+ */
+function _rsasign_verifyStringPSS(sMsg, hSig, hashAlg, sLen) {
+ var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
+ var hHash = hashFunc(rstrtohex(sMsg));
+
+ if (sLen === undefined) sLen = -1;
+ return this.verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen);
+}
+
+/**
+ * verifies a sigature for a hash value of message string with RSA public key by PKCS#1 PSS sign.
+ * @name verifyWithMessageHashPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} hHash hexadecimal hash value of message string to be verified.
+ * @param {String} hSig hexadecimal string of signature value
+ * @param {String} hashAlg hash algorithm name
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ * There are two special values:
+ *
+ *
+ * DEFAULT is -1 (NOTE: OpenSSL's default is -2.)
+ * @return returns true if valid, otherwise false
+ * @since rsasign 1.2.6
+ */
+function _rsasign_verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen) {
+ var biSig = new BigInteger(hSig, 16);
+
+ if (biSig.bitLength() > this.n.bitLength()) {
+ return false;
+ }
+
+ var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
+ var mHash = hextorstr(hHash);
+ var hLen = mHash.length;
+ var emBits = this.n.bitLength() - 1;
+ var emLen = Math.ceil(emBits / 8);
+ var i;
+
+ if (sLen === -1 || sLen === undefined) {
+ sLen = hLen; // same as hash length
+ } else if (sLen === -2) {
+ sLen = emLen - hLen - 2; // recover
+ } else if (sLen < -2) {
+ throw "invalid salt length";
+ }
+
+ if (emLen < (hLen + sLen + 2)) {
+ throw "data too long";
+ }
+
+ var em = this.doPublic(biSig).toByteArray();
+
+ for (i = 0; i < em.length; i += 1) {
+ em[i] &= 0xff;
+ }
+
+ while (em.length < emLen) {
+ em.unshift(0);
+ }
+
+ if (em[emLen -1] !== 0xbc) {
+ throw "encoded message does not end in 0xbc";
+ }
+
+ em = String.fromCharCode.apply(String, em);
+
+ var maskedDB = em.substr(0, emLen - hLen - 1);
+ var H = em.substr(maskedDB.length, hLen);
+
+ var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
+
+ if ((maskedDB.charCodeAt(0) & mask) !== 0) {
+ throw "bits beyond keysize not zero";
+ }
+
+ var dbMask = pss_mgf1_str(H, maskedDB.length, hashFunc);
+ var DB = [];
+
+ for (i = 0; i < maskedDB.length; i += 1) {
+ DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+ }
+
+ DB[0] &= ~mask;
+
+ var checkLen = emLen - hLen - sLen - 2;
+
+ for (i = 0; i < checkLen; i += 1) {
+ if (DB[i] !== 0x00) {
+ throw "leftmost octets not zero";
+ }
+ }
+
+ if (DB[checkLen] !== 0x01) {
+ throw "0x01 marker not found";
+ }
+
+ return H === hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash +
+ String.fromCharCode.apply(String, DB.slice(-sLen)))));
+}
+
+RSAKey.prototype.signWithMessageHash = _rsasign_signWithMessageHash;
+RSAKey.prototype.signString = _rsasign_signString;
+RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
+RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
+RSAKey.prototype.sign = _rsasign_signString;
+RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
+RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;
+
+RSAKey.prototype.signWithMessageHashPSS = _rsasign_signWithMessageHashPSS;
+RSAKey.prototype.signStringPSS = _rsasign_signStringPSS;
+RSAKey.prototype.signPSS = _rsasign_signStringPSS;
+RSAKey.SALT_LEN_HLEN = -1;
+RSAKey.SALT_LEN_MAX = -2;
+
+RSAKey.prototype.verifyWithMessageHash = _rsasign_verifyWithMessageHash;
+RSAKey.prototype.verifyString = _rsasign_verifyString;
+RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
+RSAKey.prototype.verify = _rsasign_verifyString;
+RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;
+
+RSAKey.prototype.verifyWithMessageHashPSS = _rsasign_verifyWithMessageHashPSS;
+RSAKey.prototype.verifyStringPSS = _rsasign_verifyStringPSS;
+RSAKey.prototype.verifyPSS = _rsasign_verifyStringPSS;
+RSAKey.SALT_LEN_RECOVER = -2;
+
+/**
+ * @name RSAKey
+ * @class key of RSA public key algorithm
+ * @description Tom Wu's RSA Key class and extension
+ */
+
+//
+// rsa-pem.js - adding function for reading/writing PKCS#1 & PKCS#8 PEM private key
+// and reading/wriring x509 public key to RSAKey class
+//
+// version: 1.0 (2010-Jun-03)
+// version: 1.1 (2012-Feb-21)
+// version: 1.2 (2012-Jun-23)
+//
+// Copyright (c) 2010 Kenji Urushima (kenji.urushima@gmail.com)
+// Copyright (c) 2012 Adrian Pasternak (["adrian", "pasternak", "@", "gmail", ".", "com"].join(""))
+//
+// This software is licensed under the terms of the MIT License.
+// http://www.opensource.org/licenses/mit-license.php
+//
+// The above copyright and license notice shall be
+// included in all copies or substantial portions of the Software.
+//
+
+function _rsapem_extractEncodedData(sPEMPrivateKey) {
+ var s = sPEMPrivateKey;
+ s = s.replace(/[ \n]+/g, "");
+ return s;
+}
+
+function _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey) {
+ var a = new Array();
+ var v1 = _asnhex_getStartPosOfV_AtObj(hPrivateKey, 0);
+ var n1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, v1);
+ var e1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, n1);
+ var d1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, e1);
+ var p1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, d1);
+ var q1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, p1);
+ var dp1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, q1);
+ var dq1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, dp1);
+ var co1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, dq1);
+ a.push(v1, n1, e1, d1, p1, q1, dp1, dq1, co1);
+ return a;
+}
+
+function _rsapem_getHexValueArrayOfChildrenFromHex(hPrivateKey) {
+ var posArray = _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey);
+ var v = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[0]);
+ var n = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[1]);
+ var e = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[2]);
+ var d = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[3]);
+ var p = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[4]);
+ var q = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[5]);
+ var dp = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[6]);
+ var dq = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[7]);
+ var co = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[8]);
+ var a = new Array();
+ a.push(v, n, e, d, p, q, dp, dq, co);
+ return a;
+}
+
+function _rsapem_getPosArrayOfChildrenFromPublicKeyHex(hPrivateKey) {
+ var a = new Array();
+ var header = _asnhex_getStartPosOfV_AtObj(hPrivateKey, 0);
+ var keys = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, header);
+ a.push(header, keys);
+ return a;
+}
+
+function _rsapem_getPosArrayOfChildrenFromPrivateKeyHex(hPrivateKey) {
+ var a = new Array();
+ var integer = _asnhex_getStartPosOfV_AtObj(hPrivateKey, 0);
+ var header = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, integer);
+ var keys = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, header);
+ a.push(integer, header, keys);
+ return a;
+}
+
+function _rsapem_getHexValueArrayOfChildrenFromPublicKeyHex(hPrivateKey) {
+ var posArray = _rsapem_getPosArrayOfChildrenFromPublicKeyHex(hPrivateKey);
+ var headerVal = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[0]);
+ var keysVal = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[1]);
+
+ var keysSequence = keysVal.substring(2);
+ posArray = _rsapem_getPosArrayOfChildrenFromPublicKeyHex(keysSequence);
+ var modulus = _asnhex_getHexOfV_AtObj(keysSequence, posArray[0]);
+ var publicExp = _asnhex_getHexOfV_AtObj(keysSequence, posArray[1]);
+
+ var a = new Array();
+ a.push(modulus, publicExp);
+ return a;
+}
+
+
+function _rsapem_getHexValueArrayOfChildrenFromPrivateKeyHex(hPrivateKey) {
+ var posArray = _rsapem_getPosArrayOfChildrenFromPrivateKeyHex(hPrivateKey);
+ var integerVal = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[0]);
+ var headerVal = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[1]);
+ var keysVal = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[2]);
+
+ var keysSequence = keysVal.substring(2);
+ return _rsapem_getHexValueArrayOfChildrenFromHex(keysSequence);
+}
+
+function _rsapem_readPrivateKeyFromPkcs1PemString(keyPEM) {
+ var keyB64 = _rsapem_extractEncodedData(keyPEM);
+ var keyHex = b64tohex(keyB64) // depends base64.js
+ var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
+ this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
+}
+
+function _rsapem_readPrivateKeyFromPkcs8PemString(keyPEM) {
+ var keyB64 = _rsapem_extractEncodedData(keyPEM);
+ var keyHex = b64tohex(keyB64) // depends base64.js
+ var a = _rsapem_getHexValueArrayOfChildrenFromPrivateKeyHex(keyHex);
+ this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
+}
+
+function _rsapem_readPublicKeyFromX509PemString(keyPEM) {
+ var keyB64 = _rsapem_extractEncodedData(keyPEM);
+ var keyHex = b64tohex(keyB64) // depends base64.js
+ var a = _rsapem_getHexValueArrayOfChildrenFromPublicKeyHex(keyHex);
+ this.setPublic(a[0],a[1]);
+}
+
+/**
+* Pad string with leading zeros, to use even number of bytes.
+*/
+function _rsapem_padWithZero(numString) {
+ if (numString.length % 2 == 1) {
+ return "0" + numString;
+ }
+ return numString;
+}
+
+/**
+* Encode length in DER format (if length <0x80, then one byte, else first byte is 0x80 + length of length :) + n-bytes of length).
+*/
+function _rsapem_encodeLength(length) {
+ if (length >= parseInt("80", 16)) {
+ var realLength = _rsapem_padWithZero(length.toString(16));
+ var lengthOfLength = (realLength.length / 2);
+ return (parseInt("80", 16) + lengthOfLength).toString(16) + realLength;
+ } else {
+ return _rsapem_padWithZero(length.toString(16));
+ }
+}
+
+/**
+* Encode number in DER encoding ("02" + length + number).
+*/
+function _rsapem_derEncodeNumber(number) {
+ var numberString = _rsapem_padWithZero(number.toString(16));
+ if (numberString[0] > '7') {
+ numberString = "00" + numberString;
+ }
+ var lenString = _rsapem_encodeLength(numberString.length / 2);
+ return "02" + lenString + numberString;
+}
+
+/**
+* Converts private & public part of given key to ASN1 Hex String.
+*/
+function _rsapem_privateKeyToPkcs1HexString(rsaKey) {
+ var result = _rsapem_derEncodeNumber(0);
+ result += _rsapem_derEncodeNumber(rsaKey.n);
+ result += _rsapem_derEncodeNumber(rsaKey.e);
+ result += _rsapem_derEncodeNumber(rsaKey.d);
+ result += _rsapem_derEncodeNumber(rsaKey.p);
+ result += _rsapem_derEncodeNumber(rsaKey.q);
+ result += _rsapem_derEncodeNumber(rsaKey.dmp1);
+ result += _rsapem_derEncodeNumber(rsaKey.dmq1);
+ result += _rsapem_derEncodeNumber(rsaKey.coeff);
+
+ var fullLen = _rsapem_encodeLength(result.length / 2);
+ return '30' + fullLen + result;
+}
+
+/**
+* Converts private & public part of given key to PKCS#8 Hex String.
+*/
+function _rsapem_privateKeyToPkcs8HexString(rsaKey) {
+ var zeroInteger = "020100";
+ var encodedIdentifier = "06092A864886F70D010101";
+ var encodedNull = "0500";
+ var headerSequence = "300D" + encodedIdentifier + encodedNull;
+ var keySequence = _rsapem_privateKeyToPkcs1HexString(rsaKey);
+
+ var keyOctetString = "04" + _rsapem_encodeLength(keySequence.length / 2) + keySequence;
+
+ var mainSequence = zeroInteger + headerSequence + keyOctetString;
+ return "30" + _rsapem_encodeLength(mainSequence.length / 2) + mainSequence;
+}
+
+/**
+* Converts public part of given key to ASN1 Hex String.
+*/
+function _rsapem_publicKeyToX509HexString(rsaKey) {
+ var encodedIdentifier = "06092A864886F70D010101";
+ var encodedNull = "0500";
+ var headerSequence = "300D" + encodedIdentifier + encodedNull;
+
+ var keys = _rsapem_derEncodeNumber(rsaKey.n);
+ keys += _rsapem_derEncodeNumber(rsaKey.e);
+
+ var keySequence = "0030" + _rsapem_encodeLength(keys.length / 2) + keys;
+ var bitstring = "03" + _rsapem_encodeLength(keySequence.length / 2) + keySequence;
+
+ var mainSequence = headerSequence + bitstring;
+
+ return "30" + _rsapem_encodeLength(mainSequence.length / 2) + mainSequence;
+}
+
+/**
+* Output private & public part of the key in PKCS#1 PEM format.
+*/
+function _rsapem_privateKeyToPkcs1PemString() {
+ return hex2b64(_rsapem_privateKeyToPkcs1HexString(this));
+}
+
+/**
+* Output private & public part of the key in PKCS#8 PEM format.
+*/
+function _rsapem_privateKeyToPkcs8PemString() {
+ return hex2b64(_rsapem_privateKeyToPkcs8HexString(this));
+}
+
+/**
+* Output public part of the key in x509 PKCS#1 PEM format.
+*/
+function _rsapem_publicKeyToX509PemString() {
+ return hex2b64(_rsapem_publicKeyToX509HexString(this));
+}
+
+function _rsa_splitKey(key, line) {
+ var splitKey = "";
+ for (var i = 0; i < key.length; i++) {
+ if (i % line == 0 && i != 0 && i != (key.length - 1)) {
+ splitKey += "\n";
+ }
+ splitKey += key[i];
+ }
+
+ return splitKey;
+}
+
+RSAKey.prototype.readPrivateKeyFromPkcs1PemString = _rsapem_readPrivateKeyFromPkcs1PemString;
+RSAKey.prototype.privateKeyToPkcs1PemString = _rsapem_privateKeyToPkcs1PemString;
+
+RSAKey.prototype.readPrivateKeyFromPkcs8PemString = _rsapem_readPrivateKeyFromPkcs8PemString;
+RSAKey.prototype.privateKeyToPkcs8PemString = _rsapem_privateKeyToPkcs8PemString;
+
+RSAKey.prototype.readPublicKeyFromX509PEMString = _rsapem_readPublicKeyFromX509PemString;
+RSAKey.prototype.publicKeyToX509PemString = _rsapem_publicKeyToX509PemString;
+
+
+
+/*global RSAKey: false,
+ ASN1HEX: false,
+ Uint8Array: false */
+/*jslint browser: true, nomen: true */
+
+function SecureRandom()
+{
+ "use strict";
+ return undefined;
+}
+
+SecureRandom.prototype.nextBytes = function (ba)
+{
+ "use strict";
+
+ var ua = new Uint8Array(ba.length), i;
+
+ window.crypto.getRandomValues(ua);
+
+ for (i = 0; i < ba.length; i += 1)
+ {
+ ba[i] = ua[i];
+ }
+};
+
+var _prvKeyHead = "-----BEGIN RSA PRIVATE KEY-----";
+var _prvKeyFoot = "-----END RSA PRIVATE KEY-----";
+var _pubKeyHead = "-----BEGIN PUBLIC KEY-----";
+var _pubKeyFoot = "-----END PUBLIC KEY-----";
+/*jslint regexp: true */
+var _re_pem = /(.{1,64})/g;
+/*jslint regexp: false */
+
+function _rsapem_extractEncodedData2(sPEMKey)
+{
+ "use strict";
+ var s = sPEMKey;
+ s = s.replace(_prvKeyHead, "");
+ s = s.replace(_prvKeyFoot, "");
+ s = s.replace(_pubKeyHead, "");
+ s = s.replace(_pubKeyFoot, "");
+ s = s.replace(/[ \n]+/g, "");
+ return s;
+}
+
+RSAKey.prototype.readPrivateKeyFromPEMString = function (keyPEM)
+{
+ "use strict";
+ return this.readPrivateKeyFromPkcs1PemString(_rsapem_extractEncodedData2(keyPEM));
+};
+
+RSAKey.prototype.readPublicKeyFromPEMString = function (keyPEM)
+{
+ "use strict";
+ return this.readPublicKeyFromX509PEMString(_rsapem_extractEncodedData2(keyPEM));
+};
+
+function _asnhex_getStartPosOfV_AtObj(s, pos)
+{
+ "use strict";
+ return ASN1HEX.getStartPosOfV_AtObj(s, pos);
+}
+
+function _asnhex_getPosOfNextSibling_AtObj(s, pos)
+{
+ "use strict";
+ return ASN1HEX.getPosOfNextSibling_AtObj(s, pos);
+}
+
+function _asnhex_getHexOfV_AtObj(s, pos)
+{
+ "use strict";
+ return ASN1HEX.getHexOfV_AtObj(s, pos);
+}
diff --git a/js-crypt-test/js/simple-crypt.js b/js-crypt-test/js/simple-crypt.js
new file mode 100644
index 0000000..d92ba64
--- /dev/null
+++ b/js-crypt-test/js/simple-crypt.js
@@ -0,0 +1,1178 @@
+/*global require: false,
+ slowAES: false,
+ window: false,
+ exports: false,
+ rstr_hmac_sha256: false,
+ b64tohex: false,
+ hex2b64: false,
+ rstr_sha256: false,
+ Uint8Array: false,
+ escape: false,
+ unescape: false,
+ PBKDF2: false,
+ rstr_sha1: false,
+ Buffer: false,
+ RSAKey: false,
+ process: false */
+/*jslint nomen: true */
+
+// Simple symmetric and asymmetric crypto.
+// Note: Keep an eye on http://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-02
+
+var SHA1_SIZE = 20,
+ SHA256_SIZE = 32,
+ AES_BLOCK_SIZE = 16,
+ AES_128_KEY_SIZE = 16,
+
+Crypt = function (parsed_key, options)
+{
+ "use strict";
+
+ this.key = parsed_key;
+
+ options = options || {};
+
+ this.options = {};
+ this.options.json = options.json !== false;
+ this.options.check = options.check !== false;
+ this.options.pad = options.pad !== false;
+ this.options.custom = options.custom;
+};
+
+Crypt.make = function (key, options, cb)
+{
+ "use strict";
+
+ if (!cb)
+ {
+ cb = options;
+ options = {};
+ }
+
+ if (!cb)
+ {
+ cb = key;
+ key = undefined;
+ }
+
+ if (typeof cb !== 'function')
+ {
+ options = cb;
+ cb = undefined;
+ }
+
+ var This = this,
+ crypt = new This(undefined, options);
+
+ This.parse_key(key, function (err, parsed_key)
+ {
+ if (err)
+ {
+ cb(err);
+ return;
+ }
+
+ crypt.key = parsed_key;
+
+ if (cb)
+ {
+ cb(null, crypt);
+ }
+ });
+
+ return crypt;
+};
+
+Crypt.get_version = function ()
+{
+ "use strict";
+ return 1;
+};
+
+Crypt.get_key_size = function ()
+{
+ "use strict";
+ return AES_128_KEY_SIZE;
+};
+
+Crypt.prototype.get_key = function ()
+{
+ "use strict";
+ return this.key;
+};
+
+Crypt.prototype.check_version = function (data, f)
+{
+ "use strict";
+
+ if (data.version > Crypt.get_version())
+ {
+ f.call(this, 'unsupported version');
+ return false;
+ }
+
+ return true;
+};
+
+Crypt.prototype.maybe_encrypt = function (arg_encrypt,
+ arg_data,
+ arg_f,
+ arg_get_key)
+{
+ "use strict";
+
+ var ths = this, encrypt, data, f, get_key, get_key_data,
+
+ encrypted = function (err, edata, key_data)
+ {
+ if (err)
+ {
+ f.call(this, err);
+ }
+ else
+ {
+ f.call(this, null, { encrypted: true, data: edata, key_data: key_data });
+ }
+ },
+
+ not_encrypted = function ()
+ {
+ f.call(this, null, { encrypted: false, data: data });
+ };
+
+ if (typeof arg_data === 'function')
+ {
+ get_key_data = Array.prototype.slice.call(arguments, 3);
+ get_key = arg_f;
+ f = arg_data;
+ data = arg_encrypt;
+ encrypt = (get_key !== undefined) || this.key;
+ }
+ else
+ {
+ get_key_data = Array.prototype.slice.call(arguments, 4);
+ get_key = arg_get_key;
+ f = arg_f;
+ data = arg_data;
+ encrypt = arg_encrypt;
+ }
+
+ if (encrypt)
+ {
+ if (get_key !== undefined)
+ {
+ get_key_data.push(function (err, key, key_data, iv)
+ {
+ if (err)
+ {
+ f.call(ths, err);
+ }
+ else if (key)
+ {
+ Crypt.make(key, ths.options, function (err, crypt)
+ {
+ if (err)
+ {
+ f.call(ths, err);
+ }
+ else
+ {
+ crypt.encrypt(data, iv, function (err, data)
+ {
+ encrypted.call(this, err, data, key_data);
+ });
+ }
+ });
+ }
+ else
+ {
+ not_encrypted.call(ths);
+ }
+ });
+
+ get_key.apply(this, get_key_data);
+ }
+ else
+ {
+ this.encrypt(data, encrypted);
+ }
+ }
+ else
+ {
+ not_encrypted.call(this);
+ }
+};
+
+Crypt.prototype.maybe_decrypt = function (data, f, get_key)
+{
+ "use strict";
+
+ if (data.encrypted)
+ {
+ if (get_key !== undefined)
+ {
+ var ths = this,
+ get_key_data = Array.prototype.slice.call(arguments, 3);
+
+ get_key_data.push(function (err, key)
+ {
+ if (err)
+ {
+ f.call(ths, err);
+ }
+ else
+ {
+ Crypt.make(key, ths.options, function (err, crypt)
+ {
+ if (err)
+ {
+ f.call(ths, err);
+ }
+ else
+ {
+ crypt.decrypt(data.data, f);
+ }
+ });
+ }
+ });
+
+ get_key_data.push(data.key_data);
+
+ get_key.apply(this, get_key_data);
+ }
+ else
+ {
+ this.decrypt(data.data, f);
+ }
+ }
+ else
+ {
+ f.call(this, null, data.data);
+ }
+};
+
+Crypt.prototype.maybe_sign = function (arg_sign, arg_data, arg_f, arg_get_key)
+{
+ "use strict";
+
+ var ths = this, sign, data, f, get_key, get_key_data,
+
+ signed = function (err, sdata, key_data)
+ {
+ if (err)
+ {
+ f.call(this, err);
+ }
+ else
+ {
+ f.call(this, null, { signed: true, data: sdata, key_data: key_data });
+ }
+ },
+
+ not_signed = function ()
+ {
+ f.call(this, null, { signed: false, data: data });
+ };
+
+ if (typeof arg_data === 'function')
+ {
+ get_key_data = Array.prototype.slice.call(arguments, 3);
+ get_key = arg_f;
+ f = arg_data;
+ data = arg_sign;
+ sign = (get_key !== undefined) || this.key;
+ }
+ else
+ {
+ get_key_data = Array.prototype.slice.call(arguments, 4);
+ get_key = arg_get_key;
+ f = arg_f;
+ data = arg_data;
+ sign = arg_sign;
+ }
+
+ if (sign)
+ {
+ if (get_key !== undefined)
+ {
+ get_key_data.push(function (err, key, key_data)
+ {
+ if (err)
+ {
+ f.call(ths, err);
+ }
+ else if (key)
+ {
+ Crypt.make(key, ths.options, function (err, crypt)
+ {
+ if (err)
+ {
+ f.call(ths, err);
+ }
+ else
+ {
+ crypt.sign(data, function (err, data)
+ {
+ signed.call(this, err, data, key_data);
+ });
+ }
+ });
+ }
+ else
+ {
+ not_signed.call(ths);
+ }
+ });
+
+ get_key.apply(this, get_key_data);
+ }
+ else
+ {
+ this.sign(data, signed);
+ }
+ }
+ else
+ {
+ not_signed.call(this);
+ }
+};
+
+Crypt.prototype.maybe_verify = function (data, f, get_key)
+{
+ "use strict";
+
+ if (data.signed)
+ {
+ if (get_key !== undefined)
+ {
+ var ths = this,
+ get_key_data = Array.prototype.slice.call(arguments, 3);
+
+ get_key_data.push(function (err, key)
+ {
+ if (err)
+ {
+ f.call(ths, err);
+ }
+ else
+ {
+ Crypt.make(key, ths.options, function (err, crypt)
+ {
+ if (err)
+ {
+ f.call(ths, err);
+ }
+ else
+ {
+ crypt.verify(data.data, f);
+ }
+ });
+ }
+ });
+
+ get_key_data.push(data.key_data);
+
+ get_key.apply(this, get_key_data);
+ }
+ else
+ {
+ this.verify(data.data, f);
+ }
+ }
+ else
+ {
+ f.call(this, null, data.data);
+ }
+};
+
+Crypt.sign_encrypt_sign = function (signing_key, encryption_key, data, iv, f)
+{
+ "use strict";
+
+ if (!f)
+ {
+ f = iv;
+ iv = null;
+ }
+
+ var This = this;
+
+ This.make(signing_key, function (err, signer)
+ {
+ if (err)
+ {
+ f(err);
+ return;
+ }
+
+ This.make(encryption_key, function (err, encrypter)
+ {
+ if (err)
+ {
+ f(err);
+ return;
+ }
+
+ signer.sign(data, function (err, sv)
+ {
+ if (err)
+ {
+ f(err);
+ return;
+ }
+
+ encrypter.encrypt(sv, iv, function (err, ev)
+ {
+ if (err)
+ {
+ f(err);
+ return;
+ }
+
+ signer.sign(ev, f);
+ });
+ });
+ });
+ });
+};
+
+Crypt.verify_decrypt_verify = function (decryption_key, verifying_key, data, f)
+{
+ "use strict";
+
+ var This = this;
+
+ This.make(verifying_key, function (err, verifier)
+ {
+ if (err)
+ {
+ f(err);
+ return;
+ }
+
+ This.make(decryption_key, function (err, decrypter)
+ {
+ if (err)
+ {
+ f(err);
+ return;
+ }
+
+ verifier.verify(data, function (err, vv)
+ {
+ if (err)
+ {
+ f(err);
+ return;
+ }
+
+ decrypter.decrypt(vv, function (err, dv)
+ {
+ if (err)
+ {
+ f(err);
+ return;
+ }
+
+ verifier.verify(dv, f);
+ });
+ });
+ });
+ });
+};
+
+var SlowCrypt;
+
+if (typeof require === 'function')
+{
+ var crypto = require('crypto'),
+ ursa = require('ursa'),
+ workaround = process.version.lastIndexOf('v0.8', 0) === 0;
+
+ Crypt.parse_key = function (key, cb)
+ {
+ "use strict";
+
+ if ((typeof key === 'string') &&
+ (key.lastIndexOf('-----BEGIN', 0) === 0))
+ {
+ if (key.indexOf('PUBLIC KEY') > 0)
+ {
+ key = ursa.createPublicKey(key, 'utf8');
+ }
+ else if (key.indexOf('PRIVATE KEY') > 0)
+ {
+ key = ursa.createPrivateKey(key, '', 'utf8');
+ }
+
+ cb(null, key);
+ }
+ else if (key && key.password)
+ {
+ var salt = key.salt || crypto.randomBytes(SHA1_SIZE),
+ hash;
+
+ if (salt.length < SHA1_SIZE)
+ {
+ hash = crypto.createHash('sha1');
+ hash.update(salt);
+ salt = hash.digest();
+ }
+
+ crypto.pbkdf2(key.password, salt, key.iterations, AES_128_KEY_SIZE,
+ function (err, derived_key)
+ {
+ if (err)
+ {
+ cb(err);
+ return;
+ }
+
+ if (key.progress)
+ {
+ key.progress(100);
+ }
+
+ cb(null,
+ {
+ key: derived_key,
+ salt: salt
+ });
+ });
+ }
+ else
+ {
+ cb(null, key);
+ }
+ };
+
+ Crypt.prototype.stringify = function (data)
+ {
+ "use strict";
+ return this.options.json ? new Buffer(JSON.stringify(data), 'utf8') : data;
+ };
+
+ Crypt.prototype.parse = function (data)
+ {
+ "use strict";
+ return this.options.json ? JSON.parse(data.toString('utf8')) : data;
+ };
+
+ Crypt.prototype.encrypt = function (data, iv, f)
+ {
+ "use strict";
+
+ var key, ekey, iv64, cipher, jdata, edata = '',
+ encoding = workaround ? 'hex' : 'base64';
+
+ try
+ {
+ if (!f)
+ {
+ f = iv;
+ iv = null;
+ }
+
+ if (this.key.privateEncrypt)
+ {
+ f.call(this, "can't encrypt using private key");
+ return;
+ }
+
+ if (this.key.encrypt)
+ {
+ key = crypto.randomBytes(AES_128_KEY_SIZE);
+ ekey = this.key.encrypt(key, undefined, 'base64', ursa.RSA_PKCS1_OAEP_PADDING);
+ }
+ else
+ {
+ key = this.key.key || this.key;
+ }
+
+ iv = iv || crypto.randomBytes(AES_BLOCK_SIZE);
+ iv64 = iv.toString('base64');
+
+ cipher = crypto.createCipheriv('AES-128-CBC', key, iv);
+ cipher.setAutoPadding(this.options.pad);
+
+ jdata = this.stringify(data);
+
+ if (this.options.check)
+ {
+ edata = cipher.update(crypto.createHash('sha256')
+ .update(jdata)
+ .digest(), null, encoding);
+ }
+
+ edata += cipher.update(jdata, null, encoding);
+
+ edata += cipher.final(encoding);
+
+ if (workaround)
+ {
+ edata = new Buffer(edata, encoding).toString('base64');
+ }
+ }
+ catch (ex)
+ {
+ f.call(this, ex);
+ return;
+ }
+
+ f.call(this, null, { iv: iv64, data: edata, ekey: ekey, version: Crypt.get_version() });
+ };
+
+ Crypt.prototype.decrypt = function (data, f)
+ {
+ "use strict";
+
+ var key, decipher, ddata, jdata;
+
+ try
+ {
+ if (!this.check_version(data, f))
+ {
+ return;
+ }
+
+ if (this.key.decrypt)
+ {
+ key = this.key.decrypt(data.ekey, 'base64', undefined, ursa.RSA_PKCS1_OAEP_PADDING);
+ }
+ else if (!this.key.publicDecrypt)
+ {
+ key = this.key.key || this.key;
+ }
+ else
+ {
+ f.call(this, "can't decrypt using public key");
+ return;
+ }
+
+ decipher = crypto.createDecipheriv(
+ 'AES-128-CBC',
+ key,
+ new Buffer(data.iv, 'base64'));
+ decipher.setAutoPadding(this.options.pad);
+
+ ddata = decipher.update(data.data, 'base64');
+
+ if (workaround)
+ {
+ ddata = new Buffer(ddata + decipher.final(), 'binary');
+ }
+ else
+ {
+ ddata = Buffer.concat([ddata, decipher.final()]);
+ }
+
+ if (this.options.check)
+ {
+ jdata = ddata.slice(SHA256_SIZE);
+
+ if (crypto.createHash('sha256')
+ .update(jdata)
+ .digest('base64') !== ddata.toString('base64', 0, SHA256_SIZE))
+ {
+ f.call(this, 'digest mismatch');
+ return;
+ }
+ }
+ else
+ {
+ jdata = ddata;
+ }
+
+ jdata = this.parse(jdata);
+ }
+ catch (ex)
+ {
+ f.call(this, ex);
+ return;
+ }
+
+ f.call(this, null, jdata);
+ };
+
+ Crypt.prototype.sign = function (data, f)
+ {
+ "use strict";
+
+ var jdata, signature;
+
+ try
+ {
+ jdata = this.stringify(data);
+
+ if (this.key.hashAndSign)
+ {
+ signature = this.key.hashAndSign('sha256', jdata, null, 'base64', ursa.RSA_PKCS1_PSS_PADDING);
+ }
+ else if (!this.key.encrypt)
+ {
+ signature = crypto.createHmac('sha256', this.key.key || this.key)
+ .update(jdata)
+ .digest('base64');
+ }
+ else
+ {
+ f.call(this, "can't sign using public key");
+ return;
+ }
+
+ jdata = jdata.toString('base64');
+ }
+ catch (ex)
+ {
+ f.call(this, ex);
+ return;
+ }
+
+ f.call(this, null, { data: jdata, signature: signature, version: Crypt.get_version() });
+ };
+
+ Crypt.prototype.verify = function (data, f)
+ {
+ "use strict";
+
+ var match, ddata, jdata;
+
+ try
+ {
+ if (!this.check_version(data, f))
+ {
+ return;
+ }
+
+ ddata = new Buffer(data.data, 'base64');
+
+ if (this.key.decrypt)
+ {
+ f.call(this, "can't verify using private key");
+ return;
+ }
+
+ if (this.key.hashAndVerify)
+ {
+ match = this.key.hashAndVerify(
+ 'sha256',
+ data.data,
+ data.signature,
+ 'base64',
+ ursa.RSA_PKCS1_PSS_PADDING);
+ }
+ else
+ {
+ match = crypto.createHmac('sha256', this.key.key || this.key)
+ .update(ddata)
+ .digest('base64') === data.signature;
+ }
+
+ if (match)
+ {
+ jdata = this.parse(ddata);
+ }
+ else
+ {
+ f.call(this, 'digest mismatch');
+ return;
+ }
+ }
+ catch (ex)
+ {
+ f.call(this, ex);
+ return;
+ }
+
+ f.call(this, null, jdata);
+ };
+
+ SlowCrypt = function ()
+ {
+ "use strict";
+ Crypt.apply(this, arguments);
+ };
+
+ SlowCrypt.make = Crypt.make;
+ SlowCrypt.get_version = Crypt.get_version;
+ SlowCrypt.get_key_size = Crypt.get_key_size;
+ SlowCrypt.sign_encrypt_sign = Crypt.sign_encrypt_sign;
+ SlowCrypt.verify_decrypt_verify = Crypt.verify_decrypt_verify;
+
+ SlowCrypt.prototype = Object.create(Crypt.prototype);
+}
+else
+{
+ SlowCrypt = Crypt;
+}
+
+var get_char_codes = function(s)
+{
+ "use strict";
+
+ var r = [], i;
+
+ for (i = 0; i < s.length; i += 1)
+ {
+ r.push(s.charCodeAt(i));
+ }
+
+ return r;
+};
+
+SlowCrypt.parse_key = function (key, cb)
+{
+ "use strict";
+
+ var rsa_key, salt, pbkdf2;
+
+ if (typeof key === 'string')
+ {
+ if (key.lastIndexOf('-----BEGIN', 0) === 0)
+ {
+ if (key.indexOf('PUBLIC KEY') > 0)
+ {
+ rsa_key = new RSAKey();
+ rsa_key.readPublicKeyFromPEMString(key);
+ cb(null, rsa_key);
+ return;
+ }
+
+ if (key.indexOf('PRIVATE KEY') > 0)
+ {
+ rsa_key = new RSAKey();
+ rsa_key.readPrivateKeyFromPEMString(key);
+ cb(null, rsa_key);
+ return;
+ }
+ }
+
+ cb(null, get_char_codes(key));
+ }
+ else if (key && key.password)
+ {
+ salt = key.salt;
+
+ if (!salt)
+ {
+ salt = new Uint8Array(SHA1_SIZE);
+ window.crypto.getRandomValues(salt);
+ salt = String.fromCharCode.apply(String, Array.prototype.slice.call(salt));
+ }
+
+ if (salt.length < SHA1_SIZE)
+ {
+ salt = rstr_sha1(salt);
+ }
+
+ pbkdf2 = new PBKDF2(key.password,
+ salt,
+ key.iterations,
+ AES_128_KEY_SIZE);
+
+ pbkdf2.deriveKey(
+ key.progress || function () { return undefined; },
+ function (derived_key)
+ {
+ var bytes = [], i;
+
+ for (i = 0; i < derived_key.length; i += 2)
+ {
+ bytes.push(parseInt(derived_key.substr(i, 2), 16));
+ }
+
+ cb(null,
+ {
+ key: bytes,
+ salt: salt
+ });
+ });
+ }
+ else
+ {
+ cb(null, key);
+ }
+};
+
+SlowCrypt.prototype.stringify = function (data)
+{
+ "use strict";
+
+ // http://ecmanaut.blogspot.co.uk/2006/07/encoding-decoding-utf8-in-javascript.html
+ return this.options.json ? unescape(encodeURIComponent(JSON.stringify(data))) : data;
+};
+
+SlowCrypt.prototype.parse = function (data)
+{
+ "use strict";
+ return this.options.json ? JSON.parse(decodeURIComponent(escape(data))) : data;
+};
+
+SlowCrypt.prototype.encrypt = function (data, iv, f)
+{
+ "use strict";
+
+ var key_arr, ekey, iv64, jdata, edata;
+
+ try
+ {
+ if (!f)
+ {
+ f = iv;
+ iv = null;
+ }
+
+ if (this.key.isPrivate)
+ {
+ f.call(this, "can't encrypt using private key");
+ return;
+ }
+
+ if (this.key.isPublic)
+ {
+ key_arr = new Uint8Array(AES_128_KEY_SIZE);
+ window.crypto.getRandomValues(key_arr);
+ ekey = hex2b64(this.key.encryptOAEP(String.fromCharCode.apply(String, Array.prototype.slice.call(key_arr))/*, rstr_sha256, 32*/));
+ }
+ else
+ {
+ key_arr = this.key.key || this.key;
+ }
+
+ if (!iv)
+ {
+ iv = new Uint8Array(AES_BLOCK_SIZE);
+ window.crypto.getRandomValues(iv);
+ }
+
+ iv64 = window.btoa(String.fromCharCode.apply(String, Array.prototype.slice.call(iv)));
+
+ jdata = this.stringify(data);
+
+ if (!this.options.pad)
+ {
+ slowAES._padBytesIn_save = slowAES.padBytesIn;
+ slowAES.padBytesIn = function (data)
+ {
+ return data;
+ };
+ }
+
+ if (this.options.check)
+ {
+ if (typeof jdata !== 'string')
+ {
+ jdata = String.fromCharCode.apply(String, jdata);
+ }
+
+ jdata = get_char_codes(rstr_sha256(jdata) + jdata);
+ }
+ else if (typeof jdata === 'string')
+ {
+ jdata = get_char_codes(jdata);
+ }
+
+ try
+ {
+ edata = slowAES.encrypt(
+ jdata,
+ slowAES.modeOfOperation.CBC,
+ key_arr,
+ iv);
+ }
+ finally
+ {
+ if (!this.options.pad)
+ {
+ slowAES.padBytesIn = slowAES._padBytesIn_save;
+ }
+ }
+
+ edata = window.btoa(String.fromCharCode.apply(String, edata));
+ }
+ catch (ex)
+ {
+ f.call(this, ex);
+ return;
+ }
+
+ f.call(this, null, { iv: iv64, data: edata, ekey: ekey, version: SlowCrypt.get_version() });
+};
+
+SlowCrypt.prototype.decrypt = function (data, f)
+{
+ "use strict";
+
+ var key_arr, ddata, jdata;
+
+ try
+ {
+ if (!this.check_version(data, f))
+ {
+ return;
+ }
+
+ if (this.key.isPublic)
+ {
+ f.call(this, "can't decrypt using public key");
+ return;
+ }
+
+ if (this.key.isPrivate)
+ {
+ key_arr = get_char_codes(this.key.decryptOAEP(b64tohex(data.ekey)/*, rstr_sha256, 32*/));
+ }
+ else
+ {
+ key_arr = this.key.key || this.key;
+ }
+
+ if (!this.options.pad)
+ {
+ slowAES._unpadBytesOut_save = slowAES.unpadBytesOut;
+ slowAES.unpadBytesOut = function (data)
+ {
+ return data;
+ };
+ }
+
+ try
+ {
+ ddata = String.fromCharCode.apply(String, slowAES.decrypt(
+ get_char_codes(window.atob(data.data)),
+ slowAES.modeOfOperation.CBC,
+ key_arr,
+ get_char_codes(window.atob(data.iv))));
+ }
+ finally
+ {
+ if (!this.options.pad)
+ {
+ slowAES.unpadBytesOut = slowAES._unpadBytesOut_save;
+ }
+ }
+
+ if (this.options.check)
+ {
+ jdata = ddata.substr(SHA256_SIZE);
+
+ if (rstr_sha256(jdata) !== ddata.substr(0, SHA256_SIZE))
+ {
+ f.call(this, 'digest mismatch');
+ return;
+ }
+ }
+ else
+ {
+ jdata = ddata;
+ }
+
+ jdata = this.parse(jdata);
+ }
+ catch (ex)
+ {
+ f.call(this, ex);
+ return;
+ }
+
+ f.call(this, null, jdata);
+};
+
+SlowCrypt.prototype.sign = function (data, f)
+{
+ "use strict";
+
+ var jdata, signature;
+
+ try
+ {
+ if (this.key.isPublic)
+ {
+ f.call(this, "can't sign using public key");
+ return;
+ }
+
+ jdata = this.stringify(data);
+
+ if (typeof jdata !== 'string')
+ {
+ jdata = String.fromCharCode.apply(String, jdata);
+ }
+
+ if (this.key.isPrivate)
+ {
+ signature = hex2b64(this.key.signPSS(jdata, 'sha256'));
+ }
+ else
+ {
+ signature = window.btoa(rstr_hmac_sha256(String.fromCharCode.apply(
+ String, this.key.key || this.key), jdata));
+ }
+
+ jdata = window.btoa(jdata);
+ }
+ catch (ex)
+ {
+ f.call(this, ex);
+ return;
+ }
+
+ f.call(this, null, { data: jdata, signature: signature, version: SlowCrypt.get_version() });
+};
+
+SlowCrypt.prototype.verify = function (data, f)
+{
+ "use strict";
+
+ var match, ddata, jdata;
+
+ try
+ {
+ if (!this.check_version(data, f))
+ {
+ return;
+ }
+
+ ddata = window.atob(data.data);
+
+ if (this.key.isPrivate)
+ {
+ f.call(this, "can't verify using private key");
+ return;
+ }
+
+ if (this.key.isPublic)
+ {
+ match = this.key.verifyPSS(ddata, b64tohex(data.signature), 'sha256');
+ }
+ else
+ {
+ match = window.btoa(rstr_hmac_sha256(String.fromCharCode.apply(
+ String, this.key.key || this.key), ddata)) ===
+ data.signature;
+ }
+
+ if (match)
+ {
+ jdata = this.parse(ddata);
+ }
+ else
+ {
+ f.call(this, 'digest mismatch');
+ return;
+ }
+ }
+ catch (ex)
+ {
+ f.call(this, ex);
+ return;
+ }
+
+ f.call(this, null, jdata);
+};
+
+if (typeof exports === 'object')
+{
+ exports.Crypt = Crypt;
+ exports.SlowCrypt = SlowCrypt;
+}
diff --git a/js-crypt-test/test.html b/js-crypt-test/test.html
new file mode 100644
index 0000000..8adb78b
--- /dev/null
+++ b/js-crypt-test/test.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+...
+
diff --git a/meshenger_roadmap b/meshenger_roadmap
index f3e8af3..4478dbf 100644
--- a/meshenger_roadmap
+++ b/meshenger_roadmap
@@ -7,3 +7,10 @@
-file deletion or time to live (client side?)
+# Cryptoshit
+
+encrypt / decrypt:
+http://www.davedoesdev.com/a-simple-and-consistent-wrapper-for-javascript-crypto/
+
+generating keys:
+https://bitbucket.org/adrianpasternak/js-rsa-pem/wiki/Home