/* * 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);
}