First draft of the development version

This commit is contained in:
varjolintu 2017-03-29 16:49:28 +03:00
parent 18121ae792
commit 797d9eda01
74 changed files with 7551 additions and 0 deletions

View file

@ -0,0 +1,780 @@
/*
* 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 the next block of 16 bytes (aes operates on 128bits)
getNextBlock: 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.getNextBlock(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.getNextBlock(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
*/
};

View file

@ -0,0 +1,266 @@
var browserAction = {};
var BLINK_TIMEOUT_DEFAULT = 7500;
var BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT = -1;
var BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT = 1;
browserAction.show = function(callback, tab) {
var data = {};
if(!page.tabs[tab.id] || page.tabs[tab.id].stack.length == 0) {
browserAction.showDefault(callback, tab);
return;
}
else {
data = page.tabs[tab.id].stack[page.tabs[tab.id].stack.length - 1];
}
chrome.browserAction.setIcon({
tabId: tab.id,
path: "/icons/19x19/" + browserAction.generateIconName(data.iconType, data.icon)
});
if(data.popup) {
chrome.browserAction.setPopup({
tabId: tab.id,
popup: "popups/" + data.popup
});
}
}
browserAction.update = function(interval) {
if(!page.tabs[page.currentTabId] || page.tabs[page.currentTabId].stack.length == 0) {
return;
}
var data = page.tabs[page.currentTabId].stack[page.tabs[page.currentTabId].stack.length - 1];
if(typeof data.visibleForMilliSeconds != "undefined") {
if(data.visibleForMilliSeconds <= 0) {
browserAction.stackPop(page.currentTabId);
browserAction.show(null, {"id": page.currentTabId});
page.clearCredentials(page.currentTabId);
return;
}
data.visibleForMilliSeconds -= interval;
}
if(data.intervalIcon) {
data.intervalIcon.counter += 1;
if(data.intervalIcon.counter < data.intervalIcon.max) {
return;
}
data.intervalIcon.counter = 0;
data.intervalIcon.index += 1;
if(data.intervalIcon.index > data.intervalIcon.icons.length - 1) {
data.intervalIcon.index = 0;
}
chrome.browserAction.setIcon({
tabId: page.currentTabId,
path: "/icons/19x19/" + browserAction.generateIconName(null, data.intervalIcon.icons[data.intervalIcon.index])
});
}
}
browserAction.showDefault = function(callback, tab) {
var stackData = {
level: 1,
iconType: "normal",
popup: "popup.html"
}
if(!keepass.isConfigured() || keepass.isDatabaseClosed || !keepass.isKeePassXCAvailable || page.tabs[tab.id].errorMessage) {
stackData.iconType = "cross";
}
if(page.tabs[tab.id].loginList.length > 0) {
stackData.iconType = "questionmark";
stackData.popup = "popup_login.html";
}
browserAction.stackUnshift(stackData, tab.id);
browserAction.show(null, tab);
}
browserAction.stackAdd = function(callback, tab, icon, popup, level, push, visibleForMilliSeconds, visibleForPageUpdates, redirectOffset, dontShow) {
var id = tab.id || page.currentTabId;
if(!level) {
level = 1;
}
var stackData = {
"level": level,
"icon": icon
}
if(popup) {
stackData.popup = popup;
}
if(visibleForMilliSeconds) {
stackData.visibleForMilliSeconds = visibleForMilliSeconds;
}
if(visibleForPageUpdates) {
stackData.visibleForPageUpdates = visibleForPageUpdates;
}
if(redirectOffset) {
stackData.redirectOffset = redirectOffset;
}
if(push) {
browserAction.stackPush(stackData, id);
}
else {
browserAction.stackUnshift(stackData, id);
}
if(!dontShow) {
browserAction.show(null, {"id": id});
}
}
browserAction.removeLevelFromStack = function(callback, tab, level, type, dontShow) {
if(!page.tabs[tab.id]) {
return;
}
if(!type) {
type = "<=";
}
var newStack = [];
for(var i = 0; i < page.tabs[tab.id].stack.length; i++) {
if(
(type == "<" && page.tabs[tab.id].stack[i].level >= level) ||
(type == "<=" && page.tabs[tab.id].stack[i].level > level) ||
(type == "=" && page.tabs[tab.id].stack[i].level != level) ||
(type == "==" && page.tabs[tab.id].stack[i].level != level) ||
(type == "!=" && page.tabs[tab.id].stack[i].level == level) ||
(type == ">" && page.tabs[tab.id].stack[i].level <= level) ||
(type == ">=" && page.tabs[tab.id].stack[i].level < level)
) {
newStack.push(page.tabs[tab.id].stack[i]);
}
}
page.tabs[tab.id].stack = newStack;
if(!dontShow) {
browserAction.show(callback, tab);
}
}
browserAction.stackPop = function(tabId) {
var id = tabId || page.currentTabId;
page.tabs[id].stack.pop();
};
browserAction.stackPush = function(data, tabId) {
var id = tabId || page.currentTabId;
browserAction.removeLevelFromStack(null, {"id": id}, data.level, "<=", true);
page.tabs[id].stack.push(data);
};
browserAction.stackUnshift = function(data, tabId) {
var id = tabId || page.currentTabId;
browserAction.removeLevelFromStack(null, {"id": id}, data.level, "<=", true);
page.tabs[id].stack.unshift(data);
};
browserAction.removeRememberPopup = function(callback, tab, removeImmediately) {
if(!page.tabs[tab.id]) {
return;
}
if(page.tabs[tab.id].stack.length == 0) {
page.clearCredentials(tab.id);
return;
}
var data = page.tabs[tab.id].stack[page.tabs[tab.id].stack.length - 1];
if(removeImmediately || !isNaN(data.visibleForPageUpdates)) {
var currentMS = Date.now();
if( removeImmediately || (data.visibleForPageUpdates <= 0 && data.redirectOffset > 0)) {
browserAction.stackPop(tab.id);
browserAction.show(null, {"id": tab.id});
page.clearCredentials(tab.id);
return;
}
else if (!isNaN(data.visibleForPageUpdates) && data.redirectOffset > 0 && currentMS >= data.redirectOffset) {
data.visibleForPageUpdates = data.visibleForPageUpdates - 1;
}
}
};
browserAction.setRememberPopup = function(tabId, username, password, url, usernameExists, credentialsList) {
var settings = typeof(localStorage.settings)=='undefined' ? {} : JSON.parse(localStorage.settings);
var id = tabId || page.currentTabId;
var timeoutMinMillis = parseInt(getValueOrDefault(settings, "blinkMinTimeout", BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT, 0)) ;
if (timeoutMinMillis > 0) {
timeoutMinMillis += Date.now();
}
var blinkTimeout = getValueOrDefault(settings, "blinkTimeout", BLINK_TIMEOUT_DEFAULT, 0);
var pageUpdateAllowance = getValueOrDefault(settings, "allowedRedirect", BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT, 0);
var stackData = {
visibleForMilliSeconds: blinkTimeout,
visibleForPageUpdates: pageUpdateAllowance,
redirectOffset: timeoutMinMillis,
level: 10,
intervalIcon: {
index: 0,
counter: 0,
max: 2,
icons: ["icon_remember_red_background_19x19.png", "icon_remember_red_lock_19x19.png"]
},
icon: "icon_remember_red_background_19x19.png",
popup: "popup_remember.html"
}
browserAction.stackPush(stackData, id);
page.tabs[id].credentials = {
"username": username,
"password": password,
"url": url,
"usernameExists": usernameExists,
"list": credentialsList
};
browserAction.show(null, {"id": id});
}
function getValueOrDefault(settings, key, defaultVal, min) {
try {
var val = settings[key];
if (isNaN(val) || val < min) {
val = defaultVal;
}
return val;
} catch(e) { return defaultVal; }
}
browserAction.generateIconName = function(iconType, icon) {
if(icon) {
return icon;
}
var name = "icon_";
name += (keepass.keePassXCUpdateAvailable()) ? "new_" : "";
name += (!iconType || iconType == "normal") ? "normal" : iconType;
name += "_19x19.png";
return name;
}

View file

@ -0,0 +1,181 @@
/*
* cryptoHelpers.js: implements AES - Advanced Encryption Standard
* from the SlowAES project, http://code.google.com/p/slowaes/
*
* Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ),
* Mark Percival ( http://mpercival.com ),
* Johan Sundstrom ( http://ecmanaut.blogspot.com ),
* John Resig ( http://ejohn.org )
*
* Licensed under the Apache License, Version 2.0
* http://www.apache.org/licenses/
*/
var cryptoHelpers = {
// encodes a unicode string to UTF8 (8 bit characters are critical to AES functioning properly)
encode_utf8:function(s)
{
try{return unescape(encodeURIComponent(s));}
catch(e){throw 'error during utf8 encoding: cryptoHelpers.encode_utf8.';}
},
// decodes a UTF8 string back to unicode
decode_utf8:function(s)
{
try{return decodeURIComponent(escape(s));}
catch(e){throw('error during utf8 decoding: cryptoHelpers.decode_utf8.');}
},
//convert a number array to a hex string
toHex:function()
{
var array = [];
if(arguments.length == 1 && arguments[0].constructor == Array)
array = arguments[0];
else
array = arguments;
var ret = '';
for(var i = 0;i < array.length;i++)
ret += (array[i] < 16 ? '0' : '') + array[i].toString(16);
return ret.toLowerCase();
},
//convert a hex string to a number array
toNumbers:function(s)
{
var ret = [];
s.replace(/(..)/g,function(s){
ret.push(parseInt(s,16));
});
return ret;
},
// get a random number in the range [min,max]
getRandom:function(min,max)
{
if(min === null)
min = 0;
if(max === null)
max = 1;
return Math.floor(Math.random()*(max+1)) + min;
},
generateSharedKey:function(len)
{
if(len === null)
len = 16;
var key = [];
for(var i = 0; i < len*2; i++)
key.push(this.getRandom(0,255));
return key;
},
generatePrivateKey:function(s,size)
{
var sha = jsHash.sha2.arr_sha256(s);
return sha.slice(0,size);
},
convertStringToByteArray: function(s)
{
var byteArray = [];
for(var i = 0;i < s.length;i++)
{
byteArray.push(s.charCodeAt(i));
}
return byteArray;
},
convertByteArrayToString: function(byteArray)
{
var s = '';
for(var i = 0;i < byteArray.length;i++)
{
s += String.fromCharCode(byteArray[i])
}
return s;
},
base64: {
// Takes a Nx16x1 byte array and converts it to Base64
chars: [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/',
'=', // for decoding purposes
],
encode_line: function(flatArr){
var b64 = '';
for (var i = 0; i < flatArr.length; i += 3){
b64 += this.chars[flatArr[i] >> 2];
b64 += this.chars[((flatArr[i] & 3) << 4) | (flatArr[i + 1] >> 4)];
if (!(flatArr[i + 1] == null)){
b64 += this.chars[((flatArr[i + 1] & 15) << 2) | (flatArr[i + 2] >> 6)];
}else{
b64 += '=';
}
if (!(flatArr[i + 2] == null)){
b64 += this.chars[flatArr[i + 2] & 63];
}else{
b64 += '=';
}
}
return b64;
},
encode: function(flatArr)
{
var b64 = this.encode_line(flatArr);
// OpenSSL is super particular about line breaks
var broken_b64 = b64.slice(0, 64) + '\n';
for (var i = 1; i < (Math.ceil(b64.length / 64)); i++)
{
broken_b64 += b64.slice(i * 64, i * 64 + 64) + (Math.ceil(b64.length / 64) == i + 1 ? '': '\n');
}
return broken_b64;
},
decode: function(string)
{
string = string.replace(/[\r\n\t ]+/g, '') + '===='; // drop all whitespaces and pad with '=' (end of b64 marker)
var flatArr = [];
var c = [];
var b = [];
for (var i = 0; ; i = i + 4){
c[0] = this.chars.indexOf(string.charAt(i));
if(c[0] == 64){
return flatArr;
}
c[1] = this.chars.indexOf(string.charAt(i + 1));
c[2] = this.chars.indexOf(string.charAt(i + 2));
c[3] = this.chars.indexOf(string.charAt(i + 3));
if(
(c[0] < 0) || // char1 is wrong
(c[1] < 0) || (c[1] == 64) || // char2 is wrong
(c[2] < 0) || // char3 is neither an valid char nor '='
(c[3] < 0) // char4 is neither an valid char nor '='
){
throw 'error during base64 decoding at pos '+i+': cryptoHelpers.base64.decode.';
}
flatArr.push((c[0] << 2) | (c[1] >> 4));
if(c[2] >= 0 && c[2] < 64){
flatArr.push(((c[1] & 15) << 4) | (c[2] >> 2));
if(c[3] >= 0 && c[2] < 64){
flatArr.push(((c[2] & 3) << 6) | c[3]);
}
}
}
},
},
};

View file

@ -0,0 +1,245 @@
var event = {};
event.onMessage = function(request, sender, callback) {
if (request.action in event.messageHandlers) {
//console.log("onMessage(" + request.action + ") for #" + sender.tab.id);
if(!sender.hasOwnProperty('tab') || sender.tab.id < 1) {
sender.tab = {};
sender.tab.id = page.currentTabId;
}
event.invoke(event.messageHandlers[request.action], callback, sender.tab.id, request.args);
// onMessage closes channel for callback automatically
// if this method does not return true
if(callback) {
return true;
}
}
}
/**
* Get interesting information about the given tab.
* Function adapted from AdBlock-Plus.
*
* @param {function} handler to call after invoke
* @param {function} callback to call after handler or null
* @param {integer} senderTabId
* @param {array} args
* @param {bool} secondTime
* @returns null (asynchronous)
*/
event.invoke = function(handler, callback, senderTabId, args, secondTime) {
if(senderTabId < 1) {
return;
}
if(!page.tabs[senderTabId]) {
page.createTabEntry(senderTabId);
}
// remove information from no longer existing tabs
page.removePageInformationFromNotExistingTabs();
chrome.tabs.get(senderTabId, function(tab) {
//chrome.tabs.query({"active": true, "windowId": chrome.windows.WINDOW_ID_CURRENT}, function(tabs) {
//if (tabs.length === 0)
// return; // For example: only the background devtools or a popup are opened
//var tab = tabs[0];
if(!tab) {
return;
}
if (!tab.url) {
// Issue 6877: tab URL is not set directly after you opened a window
// using window.open()
if (!secondTime) {
window.setTimeout(function() {
event.invoke(handler, callback, senderTabId, args, true);
}, 250);
}
return;
}
if(!page.tabs[tab.id]) {
page.createTabEntry(tab.id);
}
args = args || [];
args.unshift(tab);
args.unshift(callback);
if(handler) {
handler.apply(this, args);
}
else {
console.log("undefined handler for tab " + tab.id);
}
});
}
event.onShowAlert = function(callback, tab, message) {
if( page.settings.supressAlerts ){ console.log(message); }
else { alert(message); }
}
event.onLoadSettings = function(callback, tab) {
page.settings = (typeof(localStorage.settings) == 'undefined') ? {} : JSON.parse(localStorage.settings);
}
event.onLoadKeyRing = function(callback, tab) {
keepass.keyRing = (typeof(localStorage.keyRing) == 'undefined') ? {} : JSON.parse(localStorage.keyRing);
if(keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) {
keepass.associated = {
"value": false,
"hash": null
};
}
}
event.onGetSettings = function(callback, tab) {
event.onLoadSettings();
callback({ data: page.settings });
}
event.onSaveSettings = function(callback, tab, settings) {
localStorage.settings = JSON.stringify(settings);
event.onLoadSettings();
}
event.onGetStatus = function(callback, tab) {
keepass.testAssociation(tab);
var configured = keepass.isConfigured();
var keyId = null;
if (configured) {
keyId = keepass.keyRing[keepass.databaseHash].id;
}
browserAction.showDefault(null, tab);
callback({
identifier: keyId,
configured: configured,
databaseClosed: keepass.isDatabaseClosed,
keePassXCAvailable: keepass.isKeePassXCAvailable,
encryptionKeyUnrecognized: keepass.isEncryptionKeyUnrecognized,
associated: keepass.isAssociated(),
error: page.tabs[tab.id].errorMessage
});
}
event.onPopStack = function(callback, tab) {
browserAction.stackPop(tab.id);
browserAction.show(null, tab);
}
event.onGetTabInformation = function(callback, tab) {
var id = tab.id || page.currentTabId;
callback(page.tabs[id]);
}
event.onGetConnectedDatabase = function(callback, tab) {
callback({
"count": Object.keys(keepass.keyRing).length,
"identifier": (keepass.keyRing[keepass.associated.hash]) ? keepass.keyRing[keepass.associated.hash].id : null
});
}
event.onGetKeePassXCVersions = function(callback, tab) {
if(keepass.currentKeePassXC.version == 0) {
keepass.getDatabaseHash(tab);
}
callback({"current": keepass.currentKeePassXC.version, "latest": keepass.latestKeePassXC.version});
}
event.onCheckUpdateKeePassXC = function(callback, tab) {
keepass.checkForNewKeePassXCVersion();
callback({"current": keepass.currentKeePassXC.version, "latest": keepass.latestKeePassXC.version});
}
event.onUpdateAvailableKeePassXC = function(callback, tab) {
callback(keepass.keePassXCUpdateAvailable());
}
event.onRemoveCredentialsFromTabInformation = function(callback, tab) {
var id = tab.id || page.currentTabId;
page.clearCredentials(id);
}
event.onSetRememberPopup = function(callback, tab, username, password, url, usernameExists, credentialsList) {
browserAction.setRememberPopup(tab.id, username, password, url, usernameExists, credentialsList);
}
event.onLoginPopup = function(callback, tab, logins) {
var stackData = {
level: 1,
iconType: "questionmark",
popup: "popup_login.html"
}
browserAction.stackUnshift(stackData, tab.id);
page.tabs[tab.id].loginList = logins;
browserAction.show(null, tab);
}
event.onHTTPAuthPopup = function(callback, tab, data) {
var stackData = {
level: 1,
iconType: "questionmark",
popup: "popup_httpauth.html"
}
browserAction.stackUnshift(stackData, tab.id);
page.tabs[tab.id].loginList = data;
browserAction.show(null, tab);
}
event.onMultipleFieldsPopup = function(callback, tab) {
var stackData = {
level: 1,
iconType: "normal",
popup: "popup_multiple-fields.html"
}
browserAction.stackUnshift(stackData, tab.id);
browserAction.show(null, tab);
}
// all methods named in this object have to be declared BEFORE this!
event.messageHandlers = {
'add_credentials': keepass.addCredentials,
'alert': event.onShowAlert,
'associate': keepass.associate,
'check_update_keepassxc': event.onCheckUpdateKeePassXC,
'get_connected_database': event.onGetConnectedDatabase,
'get_keepassxc_versions': event.onGetKeePassXCVersions,
'get_settings': event.onGetSettings,
'get_status': event.onGetStatus,
'get_tab_information': event.onGetTabInformation,
'load_keyring': event.onLoadKeyRing,
'load_settings': event.onLoadSettings,
'pop_stack': event.onPopStack,
'popup_login': event.onLoginPopup,
'popup_multiple-fields': event.onMultipleFieldsPopup,
'remove_credentials_from_tab_information': event.onRemoveCredentialsFromTabInformation,
'retrieve_credentials': keepass.retrieveCredentials,
'show_default_browseraction': browserAction.showDefault,
'update_credentials': keepass.updateCredentials,
'save_settings': event.onSaveSettings,
'set_remember_credentials': event.onSetRememberPopup,
'stack_add': browserAction.stackAdd,
'update_available_keepassxc': event.onUpdateAvailableKeePassXC,
'generate_password': keepass.generatePassword,
'copy_password': keepass.copyPassword
};

View file

@ -0,0 +1,65 @@
var httpAuth = httpAuth || {};
httpAuth.pendingCallbacks = [];
httpAuth.requestId = "";
httpAuth.callback = null;
httpAuth.tabId = 0;
httpAuth.url = null;
httpAuth.isProxy = false;
httpAuth.proxyUrl = null;
httpAuth.handleRequest = function (details, callback) {
if(httpAuth.requestId == details.requestId || !page.tabs[details.tabId]) {
callback({});
}
else {
httpAuth.requestId = details.requestId;
httpAuth.pendingCallbacks.push(callback);
httpAuth.processPendingCallbacks(details);
}
}
httpAuth.processPendingCallbacks = function(details) {
httpAuth.callback = httpAuth.pendingCallbacks.pop();
httpAuth.tabId = details.tabId;
httpAuth.url = details.url;
httpAuth.isProxy = details.isProxy;
if(details.challenger){
httpAuth.proxyUrl = details.challenger.host;
}
// WORKAROUND: second parameter should be tab, but is an own object with tab-id
// but in background.js only tab.id is used. To get tabs we could use
// chrome.tabs.get(tabId, callback) <-- but what should callback be?
var url = (httpAuth.isProxy && httpAuth.proxyUrl) ? httpAuth.proxyUrl : httpAuth.url;
keepass.retrieveCredentials(httpAuth.loginOrShowCredentials, { "id" : details.tabId }, url, url, true);
}
httpAuth.loginOrShowCredentials = function(logins) {
// at least one login found --> use first to login
if (logins.length > 0) {
var url = (httpAuth.isProxy && httpAuth.proxyUrl) ? httpAuth.proxyUrl : httpAuth.url;
event.onHTTPAuthPopup(null, {"id": httpAuth.tabId}, {"logins": logins, "url": url});
//generate popup-list for HTTP Auth usernames + descriptions
if(page.settings.autoFillAndSend) {
httpAuth.callback({
authCredentials: {
username: logins[0].Login,
password: logins[0].Password
}
});
}
else {
httpAuth.callback({});
}
}
// no logins found
else {
httpAuth.callback({});
}
}

View file

@ -0,0 +1,152 @@
// since version 2.0 the extension is using a keyRing instead of a single key-name-pair
keepass.convertKeyToKeyRing();
// load settings
page.initSettings();
// create tab information structure for every opened tab
page.initOpenedTabs();
// initial connection with KeePassXC
keepass.connectToNative();
keepass.getDatabaseHash(null);
// set initial tab-ID
chrome.tabs.query({"active": true, "windowId": chrome.windows.WINDOW_ID_CURRENT}, function(tabs) {
if (tabs.length === 0)
return; // For example: only the background devtools or a popup are opened
page.currentTabId = tabs[0].id;
});
// Milliseconds for intervall (e.g. to update browserAction)
var _interval = 250;
/**
* Generate information structure for created tab and invoke all needed
* functions if tab is created in foreground
* @param {object} tab
*/
chrome.tabs.onCreated.addListener(function(tab) {
if(tab.id > 0) {
//console.log("chrome.tabs.onCreated(" + tab.id+ ")");
if(tab.selected) {
page.currentTabId = tab.id;
event.invoke(page.switchTab, null, tab.id, []);
}
}
});
/**
* Remove information structure of closed tab for freeing memory
* @param {integer} tabId
* @param {object} removeInfo
*/
chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
delete page.tabs[tabId];
if(page.currentTabId == tabId) {
page.currentTabId = -1;
}
});
/**
* Remove stored credentials on switching tabs.
* Invoke functions to retrieve credentials for focused tab
* @param {object} activeInfo
*/
chrome.tabs.onActivated.addListener(function(activeInfo) {
// remove possible credentials from old tab information
page.clearCredentials(page.currentTabId, true);
browserAction.removeRememberPopup(null, {"id": page.currentTabId}, true);
chrome.tabs.get(activeInfo.tabId, function(info) {
//console.log(info.id + ": " + info.url);
if(info && info.id) {
page.currentTabId = info.id;
if(info.status == "complete") {
//console.log("event.invoke(page.switchTab, null, "+info.id + ", []);");
event.invoke(page.switchTab, null, info.id, []);
}
}
});
});
/**
* Update browserAction on every update of the page
* @param {integer} tabId
* @param {object} changeInfo
*/
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if(changeInfo.status == "complete") {
event.invoke(browserAction.removeRememberPopup, null, tabId, []);
}
});
/**
* Retrieve Credentials and try auto-login for HTTPAuth requests
*/
chrome.webRequest.onAuthRequired.addListener(httpAuth.handleRequest,
{ urls: ["<all_urls>"] }, ["asyncBlocking"]
);
/**
* Interaction between background-script and front-script
*/
chrome.extension.onMessage.addListener(event.onMessage);
/**
* Add context menu entry for filling in username + password
*/
chrome.contextMenus.create({
"title": "Fill &User + Pass",
"contexts": [ "editable" ],
"onclick": function(info, tab) {
chrome.tabs.sendMessage(tab.id, {
action: "fill_user_pass"
});
}
});
/**
* Add context menu entry for filling in only password which matches for given username
*/
chrome.contextMenus.create({
"title": "Fill &Pass Only",
"contexts": [ "editable" ],
"onclick": function(info, tab) {
chrome.tabs.sendMessage(tab.id, {
action: "fill_pass_only"
});
}
});
/**
* Add context menu entry for creating icon for generate-password dialog
*/
chrome.contextMenus.create({
"title": "Show Password &Generator Icons",
"contexts": [ "editable" ],
"onclick": function(info, tab) {
chrome.tabs.sendMessage(tab.id, {
action: "activate_password_generator"
});
}
});
/**
* Add context menu entry for creating icon for generate-password dialog
*/
chrome.contextMenus.create({
"title": "&Save credentials",
"contexts": [ "editable" ],
"onclick": function(info, tab) {
chrome.tabs.sendMessage(tab.id, {
action: "remember_credentials"
});
}
});
/**
* Interval which updates the browserAction (e.g. blinking icon)
*/
window.setInterval(function() {
browserAction.update(_interval);
}, _interval);

View file

@ -0,0 +1,632 @@
var keepass = {};
keepass.associated = {"value": false, "hash": null};
keepass.isDatabaseClosed = false;
keepass.isKeePassHttpAvailable = false;
keepass.isEncryptionKeyUnrecognized = false;
keepass.currentKeePassHttp = {"version": 0, "versionParsed": 0};
keepass.latestKeePassHttp = (typeof(localStorage.latestKeePassHttp) == 'undefined') ? {"version": 0, "versionParsed": 0, "lastChecked": null} : JSON.parse(localStorage.latestKeePassHttp);
keepass.keySize = 8; // wtf? stupid cryptoHelpers
keepass.pluginUrlDefault = "http://localhost:19455/";
keepass.latestVersionUrl = "https://passifox.appspot.com/kph/latest-version.txt";
keepass.cacheTimeout = 30 * 1000; // milliseconds
keepass.databaseHash = "no-hash"; //no-hash = keepasshttp is too old and does not return a hash value
keepass.keyRing = (typeof(localStorage.keyRing) == 'undefined') ? {} : JSON.parse(localStorage.keyRing);
keepass.keyId = "chromeipass-cryptokey-name";
keepass.keyBody = "chromeipass-key";
keepass.to_s = cryptoHelpers.convertByteArrayToString;
keepass.to_b = cryptoHelpers.convertStringToByteArray;
keepass.addCredentials = function(callback, tab, username, password, url) {
keepass.updateCredentials(callback, tab, null, username, password, url);
}
keepass.updateCredentials = function(callback, tab, entryId, username, password, url) {
page.debug("keepass.updateCredentials(callback, {1}, {2}, {3}, [password], {4})", tab.id, entryId, username, url);
// unset error message
page.tabs[tab.id].errorMessage = null;
// is browser associated to keepass?
if(!keepass.testAssociation(tab)) {
browserAction.showDefault(null, tab);
callback("error");
return;
}
// build request
var request = {
RequestType: "set-login"
};
var verifier = keepass.setVerifier(request);
var id = verifier[0];
var key = verifier[1];
var iv = request.Nonce;
request.Login = keepass.encrypt(cryptoHelpers.encode_utf8(username), key, iv);
request.Password = keepass.encrypt(cryptoHelpers.encode_utf8(password), key, iv);
request.Url = keepass.encrypt(url, key, iv);
request.SubmitUrl = keepass.encrypt(url, key, iv);
if(entryId) {
request.Uuid = keepass.encrypt(entryId, key, iv);
}
// send request
var result = keepass.send(request);
var status = result[0];
var response = result[1];
// verify response
var code = "error";
if(keepass.checkStatus(status, tab)) {
var r = JSON.parse(response);
if (keepass.verifyResponse(r, key, id)) {
code = "success";
}
else {
code = "error";
}
}
callback(code);
}
keepass.retrieveCredentials = function (callback, tab, url, submiturl, forceCallback, triggerUnlock) {
page.debug("keepass.retrieveCredentials(callback, {1}, {2}, {3}, {4})", tab.id, url, submiturl, forceCallback);
// unset error message
page.tabs[tab.id].errorMessage = null;
// is browser associated to keepass?
if(!keepass.testAssociation(tab, triggerUnlock)) {
browserAction.showDefault(null, tab);
if(forceCallback) {
callback([]);
}
return;
}
// build request
var request = {
"RequestType": "get-logins",
"SortSelection": "true",
"TriggerUnlock": (triggerUnlock === true) ? "true" : "false"
};
var verifier = keepass.setVerifier(request);
var id = verifier[0];
var key = verifier[1];
var iv = request.Nonce;
request.Url = keepass.encrypt(url, key, iv);
if(submiturl) {
request.SubmitUrl = keepass.encrypt(submiturl, key, iv);
}
// send request
var result = keepass.send(request);
var status = result[0];
var response = result[1];
var entries = [];
// verify response
if(keepass.checkStatus(status, tab)) {
var r = JSON.parse(response);
keepass.setCurrentKeePassHttpVersion(r.Version);
if (keepass.verifyResponse(r, key, id)) {
var rIv = r.Nonce;
for (var i = 0; i < r.Entries.length; i++) {
keepass.decryptEntry(r.Entries[i], key, rIv);
}
entries = r.Entries;
keepass.updateLastUsed(keepass.databaseHash);
if(entries.length == 0) {
//questionmark-icon is not triggered, so we have to trigger for the normal symbol
browserAction.showDefault(null, tab);
}
}
else {
console.log("RetrieveCredentials for " + url + " rejected");
}
}
else {
browserAction.showDefault(null, tab);
}
page.debug("keepass.retrieveCredentials() => entries.length = {1}", entries.length);
callback(entries);
}
keepass.generatePassword = function (callback, tab, forceCallback) {
// is browser associated to keepass?
if(!keepass.testAssociation(tab)) {
browserAction.showDefault(null, tab);
if(forceCallback) {
callback([]);
}
return;
}
if(keepass.currentKeePassHttp.versionParsed < 1400) {
callback([]);
return;
}
// build request
var request = {
RequestType: "generate-password"
};
var verifier = keepass.setVerifier(request);
var id = verifier[0];
var key = verifier[1];
// send request
var result = keepass.send(request);
var status = result[0];
var response = result[1];
var passwords = [];
// verify response
if(keepass.checkStatus(status, tab)) {
var r = JSON.parse(response);
keepass.setCurrentKeePassHttpVersion(r.Version);
if (keepass.verifyResponse(r, key, id)) {
var rIv = r.Nonce;
if(r.Entries) {
for (var i = 0; i < r.Entries.length; i++) {
keepass.decryptEntry(r.Entries[i], key, rIv);
}
passwords = r.Entries;
keepass.updateLastUsed(keepass.databaseHash);
}
else {
console.log("No entries returned. Is KeePassHttp up-to-date?");
}
}
else {
console.log("GeneratePassword rejected");
}
}
else {
browserAction.showDefault(null, tab);
}
callback(passwords);
}
keepass.copyPassword = function(callback, tab, password) {
var bg = chrome.extension.getBackgroundPage();
var c2c = bg.document.getElementById("copy2clipboard");
if(!c2c) {
var input = document.createElement('input');
input.type = "text";
input.id = "copy2clipboard";
bg.document.getElementsByTagName('body')[0].appendChild(input);
c2c = bg.document.getElementById("copy2clipboard");
}
c2c.value = password;
c2c.select();
document.execCommand("copy");
c2c.value = "";
callback(true);
}
keepass.associate = function(callback, tab) {
if(keepass.isAssociated()) {
return;
}
keepass.getDatabaseHash(tab);
if(keepass.isDatabaseClosed || !keepass.isKeePassHttpAvailable) {
return;
}
page.tabs[tab.id].errorMessage = null;
var rawKey = cryptoHelpers.generateSharedKey(keepass.keySize * 2);
var key = keepass.b64e(rawKey);
var request = {
RequestType: "associate",
Key: key
};
keepass.setVerifier(request, key);
var result = keepass.send(request);
if(keepass.checkStatus(result[0], tab)) {
var r = JSON.parse(result[1]);
if(r.Version) {
keepass.currentKeePassHttp = {
"version": r.Version,
"versionParsed": parseInt(r.Version.replace(/\./g,""))
};
}
var id = r.Id;
if(!keepass.verifyResponse(r, key)) {
page.tabs[tab.id].errorMessage = "KeePass association failed, try again.";
}
else {
keepass.setCryptoKey(id, key);
keepass.associated.value = true;
keepass.associated.hash = r.Hash || 0;
}
browserAction.show(callback, tab);
}
}
keepass.isConfigured = function() {
if(typeof(keepass.databaseHash) == "undefined") {
keepass.getDatabaseHash();
}
return (keepass.databaseHash in keepass.keyRing);
}
keepass.isAssociated = function() {
return (keepass.associated.value && keepass.associated.hash && keepass.associated.hash == keepass.databaseHash);
}
keepass.send = function(request) {
var xhr = new XMLHttpRequest();
xhr.open("POST", keepass.getPluginUrl(), false);
xhr.setRequestHeader("Content-Type", "application/json");
try {
var r = JSON.stringify(request);
page.debug("Request: {1}", r);
xhr.send(r);
}
catch (e) {
console.log("KeePassHttp: " + e);
}
page.debug("Response: {1} => {2}", xhr.status, xhr.responseText);
return [xhr.status, xhr.responseText];
}
keepass.checkStatus = function (status, tab) {
var success = (status >= 200 && status <= 299);
keepass.isDatabaseClosed = false;
keepass.isKeePassHttpAvailable = true;
if(tab && page.tabs[tab.id]) {
delete page.tabs[tab.id].errorMessage;
}
if (!success) {
keepass.associated.value = false;
keepass.associated.hash = null;
if(tab && page.tabs[tab.id]) {
page.tabs[tab.id].errorMessage = "Unknown error: " + status;
}
console.log("Error: "+ status);
if (status == 503) {
keepass.isDatabaseClosed = true;
console.log("KeePass database is not opened");
if(tab && page.tabs[tab.id]) {
page.tabs[tab.id].errorMessage = "KeePass database is not opened.";
}
}
else if (status == 0) {
keepass.isKeePassHttpAvailable = false;
console.log("Could not connect to keepass");
if(tab && page.tabs[tab.id]) {
page.tabs[tab.id].errorMessage = "Is KeePassHttp installed and is KeePass running?";
}
}
}
page.debug("keepass.checkStatus({1}, [tabID]) => {2}", status, success);
return success;
}
keepass.convertKeyToKeyRing = function() {
if(keepass.keyId in localStorage && keepass.keyBody in localStorage && !("keyRing" in localStorage)) {
var hash = keepass.getDatabaseHash(null);
keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]);
}
if("keyRing" in localStorage) {
delete localStorage[keepass.keyId];
delete localStorage[keepass.keyBody];
}
}
keepass.saveKey = function(hash, id, key) {
if(!(hash in keepass.keyRing)) {
keepass.keyRing[hash] = {
"id": id,
"key": key,
"icon": "blue",
"created": new Date(),
"last-used": new Date()
}
}
else {
keepass.keyRing[hash].id = id;
keepass.keyRing[hash].key = key;
}
localStorage.keyRing = JSON.stringify(keepass.keyRing);
}
keepass.updateLastUsed = function(hash) {
if((hash in keepass.keyRing)) {
keepass.keyRing[hash].lastUsed = new Date();
localStorage.keyRing = JSON.stringify(keepass.keyRing);
}
}
keepass.deleteKey = function(hash) {
delete keepass.keyRing[hash];
localStorage.keyRing = JSON.stringify(keepass.keyRing);
}
keepass.getIconColor = function() {
return ((keepass.databaseHash in keepass.keyRing) && keepass.keyRing[keepass.databaseHash].icon) ? keepass.keyRing[keepass.databaseHash].icon : "blue";
}
keepass.getPluginUrl = function() {
if(page.settings.hostname && page.settings.port) {
return "http://" + page.settings.hostname + ":" + page.settings.port;
}
return keepass.pluginUrlDefault;
}
keepass.setCurrentKeePassHttpVersion = function(version) {
if(version) {
keepass.currentKeePassHttp = {
"version": version,
"versionParsed": parseInt(version.replace(/\./g,""))
};
}
}
keepass.keePassHttpUpdateAvailable = function() {
if(page.settings.checkUpdateKeePassHttp && page.settings.checkUpdateKeePassHttp > 0) {
var lastChecked = (keepass.latestKeePassHttp.lastChecked) ? new Date(keepass.latestKeePassHttp.lastChecked) : new Date("11/21/1986");
var daysSinceLastCheck = Math.floor(((new Date()).getTime()-lastChecked.getTime())/86400000);
if(daysSinceLastCheck >= page.settings.checkUpdateKeePassHttp) {
keepass.checkForNewKeePassHttpVersion();
}
}
return (keepass.currentKeePassHttp.versionParsed > 0 && keepass.currentKeePassHttp.versionParsed < keepass.latestKeePassHttp.versionParsed);
}
keepass.checkForNewKeePassHttpVersion = function() {
var xhr = new XMLHttpRequest();
xhr.open("GET", keepass.latestVersionUrl, false);
xhr.setRequestHeader("Content-Type", "application/json");
try {
xhr.send();
var $version = xhr.responseText;
if($version.substring(0, 1) == ":") {
$version = $version.substring(xhr.responseText.indexOf("KeePassHttp") + 12);
$version = $version.substring(0, $version.indexOf(":") - 1);
keepass.latestKeePassHttp.version = $version;
keepass.latestKeePassHttp.versionParsed = parseInt($version.replace(/\./g,""));
}
else {
$version = -1;
}
}
catch (e) {
console.log("Error: " + e);
}
if($version != -1) {
localStorage.latestKeePassHttp = JSON.stringify(keepass.latestKeePassHttp);
}
keepass.latestKeePassHttp.lastChecked = new Date();
}
keepass.testAssociation = function (tab, triggerUnlock) {
keepass.getDatabaseHash(tab, triggerUnlock);
if(keepass.isDatabaseClosed || !keepass.isKeePassHttpAvailable) {
return false;
}
if(keepass.isAssociated()) {
return true;
}
var request = {
"RequestType": "test-associate",
"TriggerUnlock": (triggerUnlock === true) ? "true" : false
};
var verifier = keepass.setVerifier(request);
if(!verifier) {
keepass.associated.value = false;
keepass.associated.hash = null;
return false;
}
var result = keepass.send(request);
var status = result[0];
var response = result[1];
if(keepass.checkStatus(status, tab)) {
var r = JSON.parse(response);
var id = verifier[0];
var key = verifier[1];
if(r.Version) {
keepass.currentKeePassHttp = {
"version": r.Version,
"versionParsed": parseInt(r.Version.replace(/\./g,""))
};
}
keepass.isEncryptionKeyUnrecognized = false;
if(!keepass.verifyResponse(r, key, id)) {
var hash = r.Hash || 0;
keepass.deleteKey(hash);
keepass.isEncryptionKeyUnrecognized = true;
console.log("Encryption key is not recognized!");
page.tabs[tab.id].errorMessage = "Encryption key is not recognized.";
keepass.associated.value = false;
keepass.associated.hash = null;
}
else if(!keepass.isAssociated()) {
console.log("Association was not successful");
page.tabs[tab.id].errorMessage = "Association was not successful.";
}
}
return keepass.isAssociated();
}
keepass.getDatabaseHash = function (tab, triggerUnlock) {
var request = {
"RequestType": "test-associate",
"TriggerUnlock": (triggerUnlock === true) ? "true" : false
};
var oldDatabaseHash = keepass.databaseHash;
var result = keepass.send(request);
if(keepass.checkStatus(result[0], tab)) {
var response = JSON.parse(result[1]);
keepass.setCurrentKeePassHttpVersion(response.Version);
keepass.databaseHash = response.Hash || "no-hash";
}
else {
keepass.databaseHash = "no-hash";
}
if(oldDatabaseHash && oldDatabaseHash != keepass.databaseHash) {
//console.log("clear association (old db hash != new db hash ==> " + oldDatabaseHash + " != " + keepass.databaseHash);
keepass.associated.value = false;
keepass.associated.hash = null;
}
return keepass.databaseHash;
}
keepass.setVerifier = function(request, inputKey) {
var key = inputKey || null;
var id = null;
if(!key) {
var info = keepass.getCryptoKey();
if (info == null) {
return null;
}
id = info[0];
key = info[1];
}
if(id) {
request.Id = id;
}
var iv = cryptoHelpers.generateSharedKey(keepass.keySize);
request.Nonce = keepass.b64e(iv);
//var decodedKey = keepass.b64d(key);
request.Verifier = keepass.encrypt(request.Nonce, key, request.Nonce);
return [id, key];
}
keepass.verifyResponse = function(response, key, id) {
keepass.associated.value = response.Success;
if (!response.Success) {
keepass.associated.hash = null;
return false;
}
keepass.associated.hash = keepass.databaseHash;
var iv = response.Nonce;
var value = keepass.decrypt(response.Verifier, key, iv, true);
keepass.associated.value = (value == iv);
if(id) {
keepass.associated.value = (keepass.associated.value && id == response.Id);
}
keepass.associated.hash = (keepass.associated.value) ? keepass.databaseHash : null;
return keepass.isAssociated();
}
keepass.b64e = function(d) {
return btoa(keepass.to_s(d));
}
keepass.b64d = function(d) {
return keepass.to_b(atob(d));
}
keepass.getCryptoKey = function() {
if(!(keepass.databaseHash in keepass.keyRing)) {
return null;
}
var id = keepass.keyRing[keepass.databaseHash].id;
var key = null;
if(id) {
key = keepass.keyRing[keepass.databaseHash].key;
}
return key ? [id, key] : null;
}
keepass.setCryptoKey = function(id, key) {
keepass.saveKey(keepass.databaseHash, id, key);
}
keepass.encrypt = function(input, key, iv) {
return keepass.b64e(
slowAES.encrypt(
keepass.to_b(input),
slowAES.modeOfOperation.CBC,
keepass.b64d(key),
keepass.b64d(iv)
)
);
}
keepass.decrypt = function(input, key, iv, toStr) {
var output = slowAES.decrypt(
keepass.b64d(input),
slowAES.modeOfOperation.CBC,
keepass.b64d(key),
keepass.b64d(iv)
);
return toStr ? keepass.to_s(output) : output;
}
keepass.decryptEntry = function (e, key, iv) {
e.Uuid = keepass.decrypt(e.Uuid, key, iv, true);
e.Name = UTF8.decode(keepass.decrypt(e.Name, key, iv, true));
e.Login = UTF8.decode(keepass.decrypt(e.Login, key, iv, true));
e.Password = UTF8.decode(keepass.decrypt(e.Password, key, iv, true));
if(e.StringFields) {
for(var i = 0; i < e.StringFields.length; i++) {
e.StringFields[i].Key = UTF8.decode(keepass.decrypt(e.StringFields[i].Key, key, iv, true))
e.StringFields[i].Value = UTF8.decode(keepass.decrypt(e.StringFields[i].Value, key, iv, true))
}
}
}

View file

@ -0,0 +1,642 @@
var keepass = {};
keepass.associated = {"value": false, "hash": null};
keepass.isConnected = false;
keepass.isDatabaseClosed = false;
keepass.isKeePassXCAvailable = false;
keepass.useSecretBox = false;
keepass.isEncryptionKeyUnrecognized = false;
keepass.currentKeePassXC = {"version": 0, "versionParsed": 0};
keepass.latestKeePassXC = (typeof(localStorage.latestKeePassXC) == 'undefined') ? {"version": 0, "versionParsed": 0, "lastChecked": null} : JSON.parse(localStorage.latestKeePassXC);
keepass.requiredKeePassXC = 212;
keepass.nativeHostName = "com.varjolintu.chromekeepassxc";
keepass.nativePort = null;
keepass.keySize = 8; // wtf? stupid cryptoHelpers
keepass.latestVersionUrl = "https://raw.githubusercontent.com/keepassxreboot/keepassxc/develop/CHANGELOG";
keepass.cacheTimeout = 30 * 1000; // milliseconds
keepass.databaseHash = "no-hash"; //no-hash = keepasshttp is too old and does not return a hash value
keepass.keyRing = (typeof(localStorage.keyRing) == 'undefined') ? {} : JSON.parse(localStorage.keyRing);
keepass.keyId = "chromekeepassxc-cryptokey-name";
keepass.keyBody = "chromekeepassxc-key";
keepass.to_s = cryptoHelpers.convertByteArrayToString;
keepass.to_b = cryptoHelpers.convertStringToByteArray;
keepass.addCredentials = function(callback, tab, username, password, url) {
keepass.updateCredentials(callback, tab, null, username, password, url);
}
keepass.updateCredentials = function(callback, tab, entryId, username, password, url) {
page.debug("keepass.updateCredentials(callback, {1}, {2}, {3}, [password], {4})", tab.id, entryId, username, url);
// unset error message
page.tabs[tab.id].errorMessage = null;
// is browser associated to keepass?
if(!keepass.testAssociation(tab)) {
browserAction.showDefault(null, tab);
callback("error");
return;
}
// build request
var request = {
RequestType: "set-login"
};
var verifier = keepass.setVerifier(request);
var id = verifier[0];
var key = verifier[1];
var iv = request.Nonce;
request.Login = keepass.encrypt(nacl.util.encode_UTF8(username), key, iv);
request.Password = keepass.encrypt(nacl.util.encode_UTF8(password), key, iv);
request.Url = keepass.encrypt(url, key, iv);
request.SubmitUrl = keepass.encrypt(url, key, iv);
if(entryId) {
request.Uuid = keepass.encrypt(entryId, key, iv);
}
// send request
var result = keepass.send(request);
var status = result[0];
var response = result[1];
// verify response
var code = "error";
if(keepass.checkStatus(status, tab)) {
var r = JSON.parse(response);
if (keepass.verifyResponse(r, key, id)) {
code = "success";
}
else {
code = "error";
}
}
callback(code);
}
keepass.retrieveCredentials = function (callback, tab, url, submiturl, forceCallback, triggerUnlock) {
page.debug("keepass.retrieveCredentials(callback, {1}, {2}, {3}, {4})", tab.id, url, submiturl, forceCallback);
// is browser associated to keepass?
if(!keepass.testAssociation(tab)) {
browserAction.showDefault(null, tab);
callback("error");
return;
}
// unset error message
page.tabs[tab.id].errorMessage = null;
if (!keepass.isConnected) {
return;
}
var entries = [];
message = {
"action": "get-logins",
"url": url
};
var verifier = keepass.setVerifier(message);
var id = verifier[0];
var key = verifier[1];
var iv = message.nonce;
var entries = [];
keepass.callbackOnId(keepass.nativePort.onMessage, "get-logins-reply", function(response) {
if (response) {
keepass.setcurrentKeePassXCVersion(response.version);
if (keepass.verifyResponse(response, key, id)) {
var rIv = response.nonce;
for (var i = 0; i < response.entries.length; i++) {
keepass.decryptEntry(response.entries[i], key, rIv);
}
entries = response.entries;
keepass.updateLastUsed(keepass.databaseHash);
if(entries.length == 0) {
//questionmark-icon is not triggered, so we have to trigger for the normal symbol
browserAction.showDefault(null, tab);
}
callback(entries);
}
else {
console.log("RetrieveCredentials for " + url + " rejected");
}
}
else {
browserAction.showDefault(null, tab);
}
});
keepass.nativePort.postMessage(message);
page.debug("keepass.retrieveCredentials() => entries.length = {1}", entries.length);
}
// Handles the replies with callback provided
keepass.handleReply = function (msg) {
var reply;
if (msg.action == "generate-reply") {
console.log("Handling generate-reply");
var a = [];
var response = JSON.stringify({ login: (msg.password.length * 8), password: msg.password });
keepass.updateLastUsed(keepass.databaseHash);
a.push(response);
reply = a;
}
/*else if (msg.action == "get-logins-reply") {
console.log("Handling get-logins-reply");
if (msg.count) {
var a = [];
for (var i = 0; i < msg.count; i++) {
var response = JSON.stringify({ login: msg.entries[i].login, name: msg.entries[i].name, password: msg.entries[i].password });
keepass.updateLastUsed(keepass.databaseHash);
console.log(response);
a.push(response);
}
reply = a;
}
}*/
else {
reply = msg;
}
return reply;
}
// Redirects the callback to a listener (handleReply())
keepass.callbackOnId = function (ev, id, callback) {
var listener = ( function(port, id) {
var handler = function(msg) {
if(msg.action == id) {
var reply = keepass.handleReply(msg);
ev.removeListener(handler);
callback(reply);
}
}
return handler;
})(ev, id, callback);
ev.addListener(listener);
}
keepass.generatePassword = function (callback, tab, forceCallback) {
if (!keepass.isConnected) {
return;
}
// is browser associated to keepass?
if(!keepass.testAssociation(tab)) {
browserAction.showDefault(null, tab);
callback("error");
return;
}
if(keepass.currentKeePassXC.versionParsed < keepass.requiredKeePassXC) {
callback([]);
return;
}
var passwords = [];
message = { "action": "generate-password" };
keepass.callbackOnId(keepass.nativePort.onMessage, "generate-reply", callback);
keepass.nativePort.postMessage(message);
}
keepass.copyPassword = function(callback, tab, password) {
var bg = chrome.extension.getBackgroundPage();
var c2c = bg.document.getElementById("copy2clipboard");
if(!c2c) {
var input = document.createElement('input');
input.type = "text";
input.id = "copy2clipboard";
bg.document.getElementsByTagName('body')[0].appendChild(input);
c2c = bg.document.getElementById("copy2clipboard");
}
c2c.value = password;
c2c.select();
document.execCommand("copy");
c2c.value = "";
callback(true);
}
keepass.associate = function(callback, tab) {
if(keepass.isAssociated()) {
return;
}
keepass.getDatabaseHash(callback, tab);
if(keepass.isDatabaseClosed || !keepass.isKeePassXCAvailable) {
return;
}
page.tabs[tab.id].errorMessage = null;
var rawKey = nacl.randomBytes(keepass.keySize * 2);
//var rawKey = [41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56]; // This is just for testing with the test client. KSorLC0uLzAxMjM0NTY3OA== )*+,-./012345678
console.log(rawKey);
var key = keepass.b64e(rawKey);
var request = {
action: "associate",
key: key
};
keepass.setVerifier(request, key);
keepass.callbackOnId(keepass.nativePort.onMessage, "associate-reply", function(response) {
if (response.version) {
keepass.currentKeePassXC = {
"version": response.version,
"versionParsed": parseInt(response.version.replace(/\./g,""))}
;
}
var id = response.id;
if(!keepass.verifyResponse(response, key)) {
page.tabs[tab.id].errorMessage = "KeePassXC association failed, try again.";
}
else {
keepass.setCryptoKey(id, key);
keepass.associated.value = true;
keepass.associated.hash = response.hash || 0;
}
browserAction.show(callback, tab);
});
keepass.nativePort.postMessage(request);
}
keepass.testAssociation = function (tab, triggerUnlock) {
keepass.getDatabaseHash(null, tab, triggerUnlock);
if(keepass.isDatabaseClosed || !keepass.isKeePassXCAvailable) {
return false;
}
if(keepass.isAssociated()) {
return true;
}
var message = {
"action": "test-associate",
};
var verifier = keepass.setVerifier(message);
if(!verifier) {
keepass.associated.value = false;
keepass.associated.hash = null;
return false;
}
keepass.callbackOnId(keepass.nativePort.onMessage, "test-associate-reply", function(response) {
if (response) {
var id = verifier[0];
var key = verifier[1];
if(response.version) {
keepass.currentKeePassXC = {
"version": response.version,
"versionParsed": parseInt(response.version.replace(/\./g,""))
};
}
keepass.isEncryptionKeyUnrecognized = false;
if(!keepass.verifyResponse(response, key, id)) {
var hash = response.hash || 0;
keepass.deleteKey(hash);
keepass.isEncryptionKeyUnrecognized = true;
console.log("Encryption key is not recognized!");
page.tabs[tab.id].errorMessage = "Encryption key is not recognized.";
keepass.associated.value = false;
keepass.associated.hash = null;
}
else if(!keepass.isAssociated()) {
console.log("Association was not successful");
page.tabs[tab.id].errorMessage = "Association was not successful.";
}
}
});
keepass.nativePort.postMessage(message);
return keepass.isAssociated();
}
keepass.getDatabaseHash = function (callback, tab, triggerUnlock) {
if (!keepass.isConnected) {
return;
}
message = { "action": "get-databasehash" };
keepass.callbackOnId(keepass.nativePort.onMessage, "hash-reply", function(response) {
console.log("hash-reply received: "+ response.hash);
var oldDatabaseHash = keepass.databaseHash;
keepass.setcurrentKeePassXCVersion(response.version);
keepass.databaseHash = response.hash || "no-hash";
if(oldDatabaseHash && oldDatabaseHash != keepass.databaseHash) {
keepass.associated.value = false;
keepass.associated.hash = null;
}
statusOK();
return keepass.databaseHash;
});
keepass.nativePort.postMessage(message);
}
keepass.isConfigured = function() {
if(typeof(keepass.databaseHash) == "undefined") {
keepass.getDatabaseHash();
}
return (keepass.databaseHash in keepass.keyRing);
}
keepass.isAssociated = function() {
return (keepass.associated.value && keepass.associated.hash && keepass.associated.hash == keepass.databaseHash);
}
// Needed?
keepass.checkStatus = function (status, tab) {
var success = (status >= 200 && status <= 299);
keepass.isDatabaseClosed = false;
keepass.isKeePassXCAvailable = true;
if(tab && page.tabs[tab.id]) {
delete page.tabs[tab.id].errorMessage;
}
if (!success) {
keepass.associated.value = false;
keepass.associated.hash = null;
if(tab && page.tabs[tab.id]) {
page.tabs[tab.id].errorMessage = "Unknown error: " + status;
}
console.log("Error: "+ status);
if (status == 503) {
keepass.isDatabaseClosed = true;
console.log("KeePass database is not opened");
if(tab && page.tabs[tab.id]) {
page.tabs[tab.id].errorMessage = "KeePass database is not opened.";
}
}
else if (status == 0) {
keepass.isKeePassXCAvailable = false;
console.log("Could not connect to keepass");
if(tab && page.tabs[tab.id]) {
page.tabs[tab.id].errorMessage = "Is KeePassXC installed and running?";
}
}
}
page.debug("keepass.checkStatus({1}, [tabID]) => {2}", status, success);
return success;
}
keepass.convertKeyToKeyRing = function() {
if(keepass.keyId in localStorage && keepass.keyBody in localStorage && !("keyRing" in localStorage)) {
//var hash = keepass.getDatabaseHash(null);
//keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]);
keepass.getDatabaseHash(function(hash) {
keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]);
}, null);
}
if("keyRing" in localStorage) {
delete localStorage[keepass.keyId];
delete localStorage[keepass.keyBody];
}
}
keepass.saveKey = function(hash, id, key) {
if(!(hash in keepass.keyRing)) {
keepass.keyRing[hash] = {
"id": id,
"key": key,
"icon": "blue",
"created": new Date(),
"last-used": new Date()
}
}
else {
keepass.keyRing[hash].id = id;
keepass.keyRing[hash].key = key;
}
localStorage.keyRing = JSON.stringify(keepass.keyRing);
}
keepass.updateLastUsed = function(hash) {
if((hash in keepass.keyRing)) {
keepass.keyRing[hash].lastUsed = new Date();
localStorage.keyRing = JSON.stringify(keepass.keyRing);
}
}
keepass.deleteKey = function(hash) {
delete keepass.keyRing[hash];
localStorage.keyRing = JSON.stringify(keepass.keyRing);
}
keepass.getIconColor = function() {
return ((keepass.databaseHash in keepass.keyRing) && keepass.keyRing[keepass.databaseHash].icon) ? keepass.keyRing[keepass.databaseHash].icon : "blue";
}
keepass.setcurrentKeePassXCVersion = function(version) {
if(version) {
keepass.currentKeePassXC = {
"version": version,
"versionParsed": parseInt(version.replace(/\./g,""))
};
}
}
keepass.keePassXCUpdateAvailable = function() {
if(page.settings.checkUpdateKeePassXC && page.settings.checkUpdateKeePassXC > 0) {
var lastChecked = (keepass.latestKeePassXC.lastChecked) ? new Date(keepass.latestKeePassXC.lastChecked) : new Date("11/21/1986");
var daysSinceLastCheck = Math.floor(((new Date()).getTime()-lastChecked.getTime())/86400000);
if(daysSinceLastCheck >= page.settings.checkUpdateKeePassXC) {
keepass.checkForNewKeePassXCVersion();
}
}
return (keepass.currentKeePassXC.versionParsed > 0 && keepass.currentKeePassXC.versionParsed < keepass.latestKeePassXC.versionParsed);
}
keepass.checkForNewKeePassXCVersion = function() {
var xhr = new XMLHttpRequest();
xhr.open("GET", keepass.latestVersionUrl, true);
xhr.onload = function(e) {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var $version = xhr.responseText;
if($version.substring(0, 1) == "2") {
$version = $version.substring(0, $version.indexOf(" "));
keepass.latestKeePassXC.version = $version;
keepass.latestKeePassXC.versionParsed = parseInt($version.replace(/\./g,""));
}
}
else {
$version = -1;
}
}
if($version != -1) {
localStorage.latestKeePassXC = JSON.stringify(keepass.latestKeePassXC);
}
};
xhr.onerror = function(e) {
console.log("checkForNewKeePassXCVersion error: " + e);
}
xhr.send();
keepass.latestKeePassXC.lastChecked = new Date();
}
keepass.connectToNative = function() {
if (!keepass.isConnected) {
keepass.nativeConnect();
}
}
function statusOK() {
keepass.isDatabaseClosed = false;
keepass.isKeePassXCAvailable = true;
}
keepass.onNativeMessage = function (response) {
console.log("Received message: " + JSON.stringify(response));
}
function onDisconnected() {
console.log("Failed to connect: " + chrome.runtime.lastError.message);
keepass.nativePort = null;
keepass.isConnected = false;
}
keepass.nativeConnect = function() {
console.log("Connecting to native messaging host " + keepass.nativeHostName)
keepass.nativePort = chrome.runtime.connectNative(keepass.nativeHostName);
keepass.nativePort.onMessage.addListener(keepass.onNativeMessage);
keepass.nativePort.onDisconnect.addListener(onDisconnected);
keepass.isConnected = true;
}
keepass.setVerifier = function(request, inputKey) {
var key = inputKey || null;
var id = null;
if(!key) {
var info = keepass.getCryptoKey();
if (info == null) {
return null;
}
id = info[0];
key = info[1];
}
if(id) {
request.id = id;
}
//var iv = cryptoHelpers.generateSharedKey(keepass.keySize);
var nonce = nacl.randomBytes(keepass.keySize * 2);
request.nonce = keepass.b64e(nonce);
//var decodedKey = keepass.b64d(key);
request.verifier = keepass.encrypt(request.nonce, key, request.nonce);
var test = keepass.encrypt("Aeh9maerCjE5v5V8Tz2YxA==", key, "Aeh9maerCjE5v5V8Tz2YxA==");
console.log(test);
return [id, key];
}
keepass.verifyResponse = function(response, key, id) {
keepass.associated.value = response.success;
if (!response.success) {
keepass.associated.hash = null;
return false;
}
keepass.associated.hash = keepass.databaseHash;
var nonce = response.nonce;
var value = keepass.decrypt(response.verifier, key, nonce, true);
keepass.associated.value = (value == nonce);
if(id) {
keepass.associated.value = (keepass.associated.value && id == response.id);
}
keepass.associated.hash = (keepass.associated.value) ? keepass.databaseHash : null;
return keepass.isAssociated();
}
keepass.b64e = function(d) {
//return nacl.util.encodeBase64(d);
return btoa(keepass.to_s(d));
}
keepass.b64d = function(d) {
//return nacl.util.decodeBase64(d);
return keepass.to_b(atob(d));
}
keepass.getCryptoKey = function() {
if(!(keepass.databaseHash in keepass.keyRing)) {
return null;
}
var id = keepass.keyRing[keepass.databaseHash].id;
var key = null;
if(id) {
key = keepass.keyRing[keepass.databaseHash].key;
}
return key ? [id, key] : null;
}
keepass.setCryptoKey = function(id, key) {
keepass.saveKey(keepass.databaseHash, id, key);
}
keepass.encrypt = function(input, key, nonce) {
return keepass.b64e(slowAES.encrypt(keepass.to_b(input), slowAES.modeOfOperation.CBC, keepass.b64d(key), keepass.b64d(nonce)));
//return keepass.b64e(nacl.secretbox(keepass.to_b(input), keepass.b64d(nonce), keepass.b64d(key)));
}
keepass.decrypt = function(input, key, nonce, toStr) {
var output = slowAES.decrypt(keepass.b64d(input), slowAES.modeOfOperation.CBC, keepass.b64d(key), keepass.b64d(nonce));
//var output = nacl.secretbox.open(keepass.b64d(input), keepass.b64d(nonce), keepass.b64d(key));
return toStr ? keepass.to_s(output) : output;
}
keepass.decryptEntry = function (box, key, nonce) {
var e = keepass.useSecretBox ? nacl.secretbox.open(box, nonce, key) : box;
if (e)
{
e.uuid = keepass.decrypt(e.uuid, key, nonce, true);
e.name = UTF8.decode(keepass.decrypt(e.name, key, nonce, true));
e.login = UTF8.decode(keepass.decrypt(e.login, key, nonce, true));
e.password = UTF8.decode(keepass.decrypt(e.password, key, nonce, true));
if(e.StringFields) {
for(var i = 0; i < e.StringFields.length; i++) {
e.StringFields[i].Key = UTF8.decode(keepass.decrypt(e.StringFields[i].Key, key, nonce, true))
e.StringFields[i].Value = UTF8.decode(keepass.decrypt(e.StringFields[i].Value, key, nonce, true))
}
}
}
}

View file

@ -0,0 +1,51 @@
// Written in 2014-2016 by Dmitry Chestnykh and Devi Mandiri.
// Public domain.
(function(root, f) {
'use strict';
if (typeof module !== 'undefined' && module.exports) module.exports = f();
else if (root.nacl) root.nacl.util = f();
else {
root.nacl = {};
root.nacl.util = f();
}
}(this, function() {
'use strict';
var util = {};
util.decodeUTF8 = function(s) {
if (typeof s !== 'string') throw new TypeError('expected string');
var i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length);
for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
return b;
};
util.encodeUTF8 = function(arr) {
var i, s = [];
for (i = 0; i < arr.length; i++) s.push(String.fromCharCode(arr[i]));
return decodeURIComponent(escape(s.join('')));
};
util.encodeBase64 = function(arr) {
if (typeof btoa === 'undefined') {
return (new Buffer(arr)).toString('base64');
} else {
var i, s = [], len = arr.length;
for (i = 0; i < len; i++) s.push(String.fromCharCode(arr[i]));
return btoa(s.join(''));
}
};
util.decodeBase64 = function(s) {
if (typeof atob === 'undefined') {
return new Uint8Array(Array.prototype.slice.call(new Buffer(s, 'base64'), 0));
} else {
var i, d = atob(s), b = new Uint8Array(d.length);
for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
return b;
}
};
return util;
}));

1
chromeKeePassXC/background/nacl.min.js vendored Executable file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,136 @@
var page = {};
// special information for every tab
page.tabs = {};
page.currentTabId = -1;
page.settings = (typeof(localStorage.settings) == 'undefined') ? {} : JSON.parse(localStorage.settings);
page.blockedTabs = {};
page.initSettings = function() {
event.onLoadSettings();
if(!("checkUpdateKeePassXC" in page.settings)) {
page.settings.checkUpdateKeePassXC = 3;
}
if(!("autoCompleteUsernames" in page.settings)) {
page.settings.autoCompleteUsernames = 1;
}
if(!("autoFillAndSend" in page.settings)) {
page.settings.autoFillAndSend = 1;
}
if(!("usePasswordGenerator" in page.settings)) {
page.settings.usePasswordGenerator = 1;
}
if(!("autoFillSingleEntry" in page.settings)) {
page.settings.autoFillSingleEntry = 1;
}
if(!("autoRetrieveCredentials" in page.settings)) {
page.settings.autoRetrieveCredentials = 1;
}
if(!("hostname" in page.settings)) {
page.settings.hostname = "localhost";
}
if(!("port" in page.settings)) {
page.settings.port = "19455";
}
localStorage.settings = JSON.stringify(page.settings);
}
page.initOpenedTabs = function() {
chrome.tabs.query({}, function(tabs) {
for(var i = 0; i < tabs.length; i++) {
page.createTabEntry(tabs[i].id);
}
});
}
page.isValidProtocol = function(url) {
var protocol = url.substring(0, url.indexOf(":"));
protocol = protocol.toLowerCase();
return !(url.indexOf(".") == -1 || (protocol != "http" && protocol != "https" && protocol != "ftp" && protocol != "sftp"));
}
page.switchTab = function(callback, tab) {
browserAction.showDefault(null, tab);
chrome.tabs.sendMessage(tab.id, {action: "activated_tab"});
}
page.clearCredentials = function(tabId, complete) {
if(!page.tabs[tabId]) {
return;
}
page.tabs[tabId].credentials = {};
delete page.tabs[tabId].credentials;
if(complete) {
page.tabs[tabId].loginList = [];
chrome.tabs.sendMessage(tabId, {
action: "clear_credentials"
});
}
}
page.createTabEntry = function(tabId) {
//console.log("page.createTabEntry("+tabId+")");
page.tabs[tabId] = {
"stack": [],
"errorMessage": null,
"loginList": {}
};
}
page.removePageInformationFromNotExistingTabs = function() {
var rand = Math.floor(Math.random()*1001);
if(rand == 28) {
chrome.tabs.query({}, function(tabs) {
var $tabIds = {};
var $infoIds = Object.keys(page.tabs);
for(var i = 0; i < tabs.length; i++) {
$tabIds[tabs[i].id] = true;
}
for(var i = 0; i < $infoIds.length; i++) {
if(!($infoIds[i] in $tabIds)) {
delete page.tabs[$infoIds[i]];
}
}
});
}
};
page.debugConsole = function() {
if(arguments.length > 1) {
console.log(page.sprintf(arguments[0], arguments));
}
else {
console.log(arguments[0]);
}
};
page.sprintf = function(input, args) {
return input.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined'
? (typeof args[number] == 'object' ? JSON.stringify(args[number]) : args[number])
: match
;
});
}
page.debugDummy = function() {};
page.debug = page.debugDummy;
page.setDebug = function(bool) {
if(bool) {
page.debug = page.debugConsole;
return "Debug mode enabled";
}
else {
page.debug = page.debugDummy;
return "Debug mode disabled";
}
};

View file

@ -0,0 +1,573 @@
/** @fileOverview Javascript cryptography implementation.
*
* Crush to remove comments, shorten variable names and
* generally reduce transmission size.
*
* @author Emily Stark
* @author Mike Hamburg
* @author Dan Boneh
*/
"use strict";
/*jslint indent: 2, bitwise: false, nomen: false, plusplus: false, white: false, regexp: false */
/*global document, window, escape, unescape */
/** @namespace The Stanford Javascript Crypto Library, top-level namespace. */
var sjcl = {
/** @namespace Symmetric ciphers. */
cipher: {},
/** @namespace Hash functions. Right now only SHA256 is implemented. */
hash: {},
/** @namespace Key exchange functions. Right now only SRP is implemented. */
keyexchange: {},
/** @namespace Block cipher modes of operation. */
mode: {},
/** @namespace Miscellaneous. HMAC and PBKDF2. */
misc: {},
/**
* @namespace Bit array encoders and decoders.
*
* @description
* The members of this namespace are functions which translate between
* SJCL's bitArrays and other objects (usually strings). Because it
* isn't always clear which direction is encoding and which is decoding,
* the method names are "fromBits" and "toBits".
*/
codec: {},
/** @namespace Exceptions. */
exception: {
/** @class Ciphertext is corrupt. */
corrupt: function(message) {
this.toString = function() { return "CORRUPT: "+this.message; };
this.message = message;
},
/** @class Invalid parameter. */
invalid: function(message) {
this.toString = function() { return "INVALID: "+this.message; };
this.message = message;
},
/** @class Bug or missing feature in SJCL. */
bug: function(message) {
this.toString = function() { return "BUG: "+this.message; };
this.message = message;
},
/** @class Something isn't ready. */
notReady: function(message) {
this.toString = function() { return "NOT READY: "+this.message; };
this.message = message;
}
}
};
/** @fileOverview Low-level AES implementation.
*
* This file contains a low-level implementation of AES, optimized for
* size and for efficiency on several browsers. It is based on
* OpenSSL's aes_core.c, a public-domain implementation by Vincent
* Rijmen, Antoon Bosselaers and Paulo Barreto.
*
* An older version of this implementation is available in the public
* domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,
* Stanford University 2008-2010 and BSD-licensed for liability
* reasons.
*
* @author Emily Stark
* @author Mike Hamburg
* @author Dan Boneh
*/
/**
* Schedule out an AES key for both encryption and decryption. This
* is a low-level class. Use a cipher mode to do bulk encryption.
*
* @constructor
* @param {Array} key The key as an array of 4, 6 or 8 words.
*
* @class Advanced Encryption Standard (low-level interface)
*/
sjcl.cipher.aes = function (key) {
if (!this._tables[0][0][0]) {
this._precompute();
}
var i, j, tmp,
encKey, decKey,
sbox = this._tables[0][4], decTable = this._tables[1],
keyLen = key.length, rcon = 1;
if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
throw new sjcl.exception.invalid("invalid aes key size");
}
this._key = [encKey = key.slice(0), decKey = []];
// schedule encryption keys
for (i = keyLen; i < 4 * keyLen + 28; i++) {
tmp = encKey[i-1];
// apply sbox
if (i%keyLen === 0 || (keyLen === 8 && i%keyLen === 4)) {
tmp = sbox[tmp>>>24]<<24 ^ sbox[tmp>>16&255]<<16 ^ sbox[tmp>>8&255]<<8 ^ sbox[tmp&255];
// shift rows and add rcon
if (i%keyLen === 0) {
tmp = tmp<<8 ^ tmp>>>24 ^ rcon<<24;
rcon = rcon<<1 ^ (rcon>>7)*283;
}
}
encKey[i] = encKey[i-keyLen] ^ tmp;
}
// schedule decryption keys
for (j = 0; i; j++, i--) {
tmp = encKey[j&3 ? i : i - 4];
if (i<=4 || j<4) {
decKey[j] = tmp;
} else {
decKey[j] = decTable[0][sbox[tmp>>>24 ]] ^
decTable[1][sbox[tmp>>16 & 255]] ^
decTable[2][sbox[tmp>>8 & 255]] ^
decTable[3][sbox[tmp & 255]];
}
}
};
sjcl.cipher.aes.prototype = {
// public
/* Something like this might appear here eventually
name: "AES",
blockSize: 4,
keySizes: [4,6,8],
*/
/**
* Encrypt an array of 4 big-endian words.
* @param {Array} data The plaintext.
* @return {Array} The ciphertext.
*/
encrypt:function (data) { return this._crypt(data,0); },
/**
* Decrypt an array of 4 big-endian words.
* @param {Array} data The ciphertext.
* @return {Array} The plaintext.
*/
decrypt:function (data) { return this._crypt(data,1); },
/**
* The expanded S-box and inverse S-box tables. These will be computed
* on the client so that we don't have to send them down the wire.
*
* There are two tables, _tables[0] is for encryption and
* _tables[1] is for decryption.
*
* The first 4 sub-tables are the expanded S-box with MixColumns. The
* last (_tables[01][4]) is the S-box itself.
*
* @private
*/
_tables: [[[],[],[],[],[]],[[],[],[],[],[]]],
/**
* Expand the S-box tables.
*
* @private
*/
_precompute: function () {
var encTable = this._tables[0], decTable = this._tables[1],
sbox = encTable[4], sboxInv = decTable[4],
i, x, xInv, d=[], th=[], x2, x4, x8, s, tEnc, tDec;
// Compute double and third tables
for (i = 0; i < 256; i++) {
th[( d[i] = i<<1 ^ (i>>7)*283 )^i]=i;
}
for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
// Compute sbox
s = xInv ^ xInv<<1 ^ xInv<<2 ^ xInv<<3 ^ xInv<<4;
s = s>>8 ^ s&255 ^ 99;
sbox[x] = s;
sboxInv[s] = x;
// Compute MixColumns
x8 = d[x4 = d[x2 = d[x]]];
tDec = x8*0x1010101 ^ x4*0x10001 ^ x2*0x101 ^ x*0x1010100;
tEnc = d[s]*0x101 ^ s*0x1010100;
for (i = 0; i < 4; i++) {
encTable[i][x] = tEnc = tEnc<<24 ^ tEnc>>>8;
decTable[i][s] = tDec = tDec<<24 ^ tDec>>>8;
}
}
// Compactify. Considerable speedup on Firefox.
for (i = 0; i < 5; i++) {
encTable[i] = encTable[i].slice(0);
decTable[i] = decTable[i].slice(0);
}
},
/**
* Encryption and decryption core.
* @param {Array} input Four words to be encrypted or decrypted.
* @param dir The direction, 0 for encrypt and 1 for decrypt.
* @return {Array} The four encrypted or decrypted words.
* @private
*/
_crypt:function (input, dir) {
if (input.length !== 4) {
throw new sjcl.exception.invalid("invalid aes block size");
}
var key = this._key[dir],
// state variables a,b,c,d are loaded with pre-whitened data
a = input[0] ^ key[0],
b = input[dir ? 3 : 1] ^ key[1],
c = input[2] ^ key[2],
d = input[dir ? 1 : 3] ^ key[3],
a2, b2, c2,
nInnerRounds = key.length/4 - 2,
i,
kIndex = 4,
out = [0,0,0,0],
table = this._tables[dir],
// load up the tables
t0 = table[0],
t1 = table[1],
t2 = table[2],
t3 = table[3],
sbox = table[4];
// Inner rounds. Cribbed from OpenSSL.
for (i = 0; i < nInnerRounds; i++) {
a2 = t0[a>>>24] ^ t1[b>>16 & 255] ^ t2[c>>8 & 255] ^ t3[d & 255] ^ key[kIndex];
b2 = t0[b>>>24] ^ t1[c>>16 & 255] ^ t2[d>>8 & 255] ^ t3[a & 255] ^ key[kIndex + 1];
c2 = t0[c>>>24] ^ t1[d>>16 & 255] ^ t2[a>>8 & 255] ^ t3[b & 255] ^ key[kIndex + 2];
d = t0[d>>>24] ^ t1[a>>16 & 255] ^ t2[b>>8 & 255] ^ t3[c & 255] ^ key[kIndex + 3];
kIndex += 4;
a=a2; b=b2; c=c2;
}
// Last round.
for (i = 0; i < 4; i++) {
out[dir ? 3&-i : i] =
sbox[a>>>24 ]<<24 ^
sbox[b>>16 & 255]<<16 ^
sbox[c>>8 & 255]<<8 ^
sbox[d & 255] ^
key[kIndex++];
a2=a; a=b; b=c; c=d; d=a2;
}
return out;
}
};
/** @fileOverview Arrays of bits, encoded as arrays of Numbers.
*
* @author Emily Stark
* @author Mike Hamburg
* @author Dan Boneh
*/
/** @namespace Arrays of bits, encoded as arrays of Numbers.
*
* @description
* <p>
* These objects are the currency accepted by SJCL's crypto functions.
* </p>
*
* <p>
* Most of our crypto primitives operate on arrays of 4-byte words internally,
* but many of them can take arguments that are not a multiple of 4 bytes.
* This library encodes arrays of bits (whose size need not be a multiple of 8
* bits) as arrays of 32-bit words. The bits are packed, big-endian, into an
* array of words, 32 bits at a time. Since the words are double-precision
* floating point numbers, they fit some extra data. We use this (in a private,
* possibly-changing manner) to encode the number of bits actually present
* in the last word of the array.
* </p>
*
* <p>
* Because bitwise ops clear this out-of-band data, these arrays can be passed
* to ciphers like AES which want arrays of words.
* </p>
*/
sjcl.bitArray = {
/**
* Array slices in units of bits.
* @param {bitArray a} The array to slice.
* @param {Number} bstart The offset to the start of the slice, in bits.
* @param {Number} bend The offset to the end of the slice, in bits. If this is undefined,
* slice until the end of the array.
* @return {bitArray} The requested slice.
*/
bitSlice: function (a, bstart, bend) {
a = sjcl.bitArray._shiftRight(a.slice(bstart/32), 32 - (bstart & 31)).slice(1);
return (bend === undefined) ? a : sjcl.bitArray.clamp(a, bend-bstart);
},
/**
* Extract a number packed into a bit array.
* @param {bitArray} a The array to slice.
* @param {Number} bstart The offset to the start of the slice, in bits.
* @param {Number} length The length of the number to extract.
* @return {Number} The requested slice.
*/
extract: function(a, bstart, blength) {
// FIXME: this Math.floor is not necessary at all, but for some reason
// seems to suppress a bug in the Chromium JIT.
var x, sh = Math.floor((-bstart-blength) & 31);
if ((bstart + blength - 1 ^ bstart) & -32) {
// it crosses a boundary
x = (a[bstart/32|0] << (32 - sh)) ^ (a[bstart/32+1|0] >>> sh);
} else {
// within a single word
x = a[bstart/32|0] >>> sh;
}
return x & ((1<<blength) - 1);
},
/**
* Concatenate two bit arrays.
* @param {bitArray} a1 The first array.
* @param {bitArray} a2 The second array.
* @return {bitArray} The concatenation of a1 and a2.
*/
concat: function (a1, a2) {
if (a1.length === 0 || a2.length === 0) {
return a1.concat(a2);
}
var out, i, last = a1[a1.length-1], shift = sjcl.bitArray.getPartial(last);
if (shift === 32) {
return a1.concat(a2);
} else {
return sjcl.bitArray._shiftRight(a2, shift, last|0, a1.slice(0,a1.length-1));
}
},
/**
* Find the length of an array of bits.
* @param {bitArray} a The array.
* @return {Number} The length of a, in bits.
*/
bitLength: function (a) {
var l = a.length, x;
if (l === 0) { return 0; }
x = a[l - 1];
return (l-1) * 32 + sjcl.bitArray.getPartial(x);
},
/**
* Truncate an array.
* @param {bitArray} a The array.
* @param {Number} len The length to truncate to, in bits.
* @return {bitArray} A new array, truncated to len bits.
*/
clamp: function (a, len) {
if (a.length * 32 < len) { return a; }
a = a.slice(0, Math.ceil(len / 32));
var l = a.length;
len = len & 31;
if (l > 0 && len) {
a[l-1] = sjcl.bitArray.partial(len, a[l-1] & 0x80000000 >> (len-1), 1);
}
return a;
},
/**
* Make a partial word for a bit array.
* @param {Number} len The number of bits in the word.
* @param {Number} x The bits.
* @param {Number} [0] _end Pass 1 if x has already been shifted to the high side.
* @return {Number} The partial word.
*/
partial: function (len, x, _end) {
if (len === 32) { return x; }
return (_end ? x|0 : x << (32-len)) + len * 0x10000000000;
},
/**
* Get the number of bits used by a partial word.
* @param {Number} x The partial word.
* @return {Number} The number of bits used by the partial word.
*/
getPartial: function (x) {
return Math.round(x/0x10000000000) || 32;
},
/**
* Compare two arrays for equality in a predictable amount of time.
* @param {bitArray} a The first array.
* @param {bitArray} b The second array.
* @return {boolean} true if a == b; false otherwise.
*/
equal: function (a, b) {
if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) {
return false;
}
var x = 0, i;
for (i=0; i<a.length; i++) {
x |= a[i]^b[i];
}
return (x === 0);
},
/** Shift an array right.
* @param {bitArray} a The array to shift.
* @param {Number} shift The number of bits to shift.
* @param {Number} [carry=0] A byte to carry in
* @param {bitArray} [out=[]] An array to prepend to the output.
* @private
*/
_shiftRight: function (a, shift, carry, out) {
var i, last2=0, shift2;
if (out === undefined) { out = []; }
for (; shift >= 32; shift -= 32) {
out.push(carry);
carry = 0;
}
if (shift === 0) {
return out.concat(a);
}
for (i=0; i<a.length; i++) {
out.push(carry | a[i]>>>shift);
carry = a[i] << (32-shift);
}
last2 = a.length ? a[a.length-1] : 0;
shift2 = sjcl.bitArray.getPartial(last2);
out.push(sjcl.bitArray.partial(shift+shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(),1));
return out;
},
/** xor a block of 4 words together.
* @private
*/
_xor4: function(x,y) {
return [x[0]^y[0],x[1]^y[1],x[2]^y[2],x[3]^y[3]];
}
};
/** @fileOverview CBC mode implementation
*
* @author Emily Stark
* @author Mike Hamburg
* @author Dan Boneh
*/
/** @namespace
* Dangerous: CBC mode with PKCS#5 padding.
*
* @author Emily Stark
* @author Mike Hamburg
* @author Dan Boneh
*/
sjcl.mode.cbc = {
/** The name of the mode.
* @constant
*/
name: "cbc",
/** Encrypt in CBC mode with PKCS#5 padding.
* @param {Object} prp The block cipher. It must have a block size of 16 bytes.
* @param {bitArray} plaintext The plaintext data.
* @param {bitArray} iv The initialization value.
* @param {bitArray} [adata=[]] The authenticated data. Must be empty.
* @return The encrypted data, an array of bytes.
* @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits, or if any adata is specified.
*/
encrypt: function(prp, plaintext, iv, adata) {
if (adata && adata.length) {
throw new sjcl.exception.invalid("cbc can't authenticate data");
}
if (sjcl.bitArray.bitLength(iv) !== 128) {
throw new sjcl.exception.invalid("cbc iv must be 128 bits");
}
var i,
w = sjcl.bitArray,
xor = w._xor4,
bl = w.bitLength(plaintext),
bp = 0,
output = [];
if (bl&7) {
throw new sjcl.exception.invalid("pkcs#5 padding only works for multiples of a byte");
}
for (i=0; bp+128 <= bl; i+=4, bp+=128) {
/* Encrypt a non-final block */
iv = prp.encrypt(xor(iv, plaintext.slice(i,i+4)));
output.splice(i,0,iv[0],iv[1],iv[2],iv[3]);
}
/* Construct the pad. */
bl = (16 - ((bl >> 3) & 15)) * 0x1010101;
/* Pad and encrypt. */
iv = prp.encrypt(xor(iv,w.concat(plaintext,[bl,bl,bl,bl]).slice(i,i+4)));
output.splice(i,0,iv[0],iv[1],iv[2],iv[3]);
return output;
},
/** Decrypt in CBC mode.
* @param {Object} prp The block cipher. It must have a block size of 16 bytes.
* @param {bitArray} ciphertext The ciphertext data.
* @param {bitArray} iv The initialization value.
* @param {bitArray} [adata=[]] The authenticated data. It must be empty.
* @return The decrypted data, an array of bytes.
* @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits, or if any adata is specified.
* @throws {sjcl.exception.corrupt} if if the message is corrupt.
*/
decrypt: function(prp, ciphertext, iv, adata) {
if (adata && adata.length) {
throw new sjcl.exception.invalid("cbc can't authenticate data");
}
if (sjcl.bitArray.bitLength(iv) !== 128) {
throw new sjcl.exception.invalid("cbc iv must be 128 bits");
}
if ((sjcl.bitArray.bitLength(ciphertext) & 127) || !ciphertext.length) {
throw new sjcl.exception.corrupt("cbc ciphertext must be a positive multiple of the block size");
}
var i,
w = sjcl.bitArray,
xor = w._xor4,
bi, bo,
output = [];
adata = adata || [];
for (i=0; i<ciphertext.length; i+=4) {
bi = ciphertext.slice(i,i+4);
bo = xor(iv,prp.decrypt(bi));
output.splice(i,0,bo[0],bo[1],bo[2],bo[3]);
iv = bi;
}
/* check and remove the pad */
bi = output[i-1] & 255;
if (bi == 0 || bi > 16) {
throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");
}
bo = bi * 0x1010101;
if (!w.equal(w.bitSlice([bo,bo,bo,bo], 0, bi*8),
w.bitSlice(output, output.length*32 - bi*8, output.length*32))) {
throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");
}
return w.bitSlice(output, 0, output.length*32 - bi*8);
}
};

View file

@ -0,0 +1,28 @@
var UTF8 = {
decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while (i < utftext.length) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(
((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}

468
chromeKeePassXC/bootstrap-btn.css vendored Normal file
View file

@ -0,0 +1,468 @@
.b2c-btn {
display: inline-block;
*display: inline;
padding: 4px 14px;
margin-bottom: 0;
*margin-left: .3em;
font-size: 14px;
line-height: 20px;
*line-height: 20px;
color: #333333;
text-align: center;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
vertical-align: middle;
cursor: pointer;
background-color: #f5f5f5;
*background-color: #e6e6e6;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
background-repeat: repeat-x;
border: 1px solid #bbbbbb;
*border: 0;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
border-color: #e6e6e6 #e6e6e6 #bfbfbf;
border-bottom-color: #a2a2a2;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
filter: progid:dximagetransform.microsoft.gradient(enabled=false);
*zoom: 1;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.b2c-btn:hover,
.b2c-btn:active,
.b2c-btn.active,
.b2c-btn.disabled,
.b2c-btn[disabled] {
color: #333333;
background-color: #e6e6e6;
*background-color: #d9d9d9;
}
.b2c-btn:active,
.b2c-btn.active {
background-color: #cccccc \9;
}
.b2c-btn:first-child {
*margin-left: 0;
}
.b2c-btn:hover {
color: #333333;
text-decoration: none;
background-color: #e6e6e6;
*background-color: #d9d9d9;
/* Buttons in IE7 don't get borders, so darken on hover */
background-position: 0 -15px;
-webkit-transition: background-position 0.1s linear;
-moz-transition: background-position 0.1s linear;
-o-transition: background-position 0.1s linear;
transition: background-position 0.1s linear;
}
.b2c-btn:focus {
outline: thin dotted #333;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
.b2c-btn.active,
.b2c-btn:active {
background-color: #e6e6e6;
background-color: #d9d9d9 \9;
background-image: none;
outline: 0;
-webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.b2c-btn.disabled,
.b2c-btn[disabled] {
cursor: default;
background-color: #e6e6e6;
background-image: none;
opacity: 0.65;
filter: alpha(opacity=65);
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.b2c-btn-large {
padding: 9px 14px;
font-size: 16px;
line-height: normal;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.b2c-btn-large [class^="icon-"] {
margin-top: 2px;
}
.b2c-btn-small {
padding: 3px 9px;
font-size: 12px;
line-height: 18px;
}
.b2c-btn-small [class^="icon-"] {
margin-top: 0;
}
.b2c-btn-mini {
padding: 2px 6px;
font-size: 11px;
line-height: 17px;
}
.b2c-btn-block {
display: block;
width: 100%;
padding-right: 0;
padding-left: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.b2c-btn-block + .b2c-btn-block {
margin-top: 5px;
}
input[type="submit"].b2c-btn-block,
input[type="reset"].b2c-btn-block,
input[type="button"].b2c-btn-block {
width: 100%;
}
.b2c-btn-primary.active,
.b2c-btn-warning.active,
.b2c-btn-danger.active,
.b2c-btn-success.active,
.b2c-btn-info.active,
.b2c-btn-inverse.active {
color: rgba(255, 255, 255, 0.75);
}
.b2c-btn {
border-color: #c5c5c5;
border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);
}
.b2c-btn-primary {
color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
background-color: #006dcc;
*background-color: #0044cc;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
background-image: linear-gradient(to bottom, #0088cc, #0044cc);
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
background-repeat: repeat-x;
border-color: #0044cc #0044cc #002a80;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
filter: progid:dximagetransform.microsoft.gradient(enabled=false);
}
.b2c-btn-primary:hover,
.b2c-btn-primary:active,
.b2c-btn-primary.active,
.b2c-btn-primary.disabled,
.b2c-btn-primary[disabled] {
color: #ffffff;
background-color: #0044cc;
*background-color: #003bb3;
}
.b2c-btn-primary:active,
.b2c-btn-primary.active {
background-color: #003399 \9;
}
.b2c-btn-warning {
color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
background-color: #faa732;
*background-color: #f89406;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
background-image: -o-linear-gradient(top, #fbb450, #f89406);
background-image: linear-gradient(to bottom, #fbb450, #f89406);
background-image: -moz-linear-gradient(top, #fbb450, #f89406);
background-repeat: repeat-x;
border-color: #f89406 #f89406 #ad6704;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
filter: progid:dximagetransform.microsoft.gradient(enabled=false);
}
.b2c-btn-warning:hover,
.b2c-btn-warning:active,
.b2c-btn-warning.active,
.b2c-btn-warning.disabled,
.b2c-btn-warning[disabled] {
color: #ffffff;
background-color: #f89406;
*background-color: #df8505;
}
.b2c-btn-warning:active,
.b2c-btn-warning.active {
background-color: #c67605 \9;
}
.b2c-btn-danger {
color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
background-color: #da4f49;
*background-color: #bd362f;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
background-repeat: repeat-x;
border-color: #bd362f #bd362f #802420;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
filter: progid:dximagetransform.microsoft.gradient(enabled=false);
}
.b2c-btn-danger:hover,
.b2c-btn-danger:active,
.b2c-btn-danger.active,
.b2c-btn-danger.disabled,
.b2c-btn-danger[disabled] {
color: #ffffff;
background-color: #bd362f;
*background-color: #a9302a;
}
.b2c-btn-danger:active,
.b2c-btn-danger.active {
background-color: #942a25 \9;
}
.b2c-btn-success {
color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
background-color: #5bb75b;
*background-color: #51a351;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
background-image: -webkit-linear-gradient(top, #62c462, #51a351);
background-image: -o-linear-gradient(top, #62c462, #51a351);
background-image: linear-gradient(to bottom, #62c462, #51a351);
background-image: -moz-linear-gradient(top, #62c462, #51a351);
background-repeat: repeat-x;
border-color: #51a351 #51a351 #387038;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
filter: progid:dximagetransform.microsoft.gradient(enabled=false);
}
.b2c-btn-success:hover,
.b2c-btn-success:active,
.b2c-btn-success.active,
.b2c-btn-success.disabled,
.b2c-btn-success[disabled] {
color: #ffffff;
background-color: #51a351;
*background-color: #499249;
}
.b2c-btn-success:active,
.b2c-btn-success.active {
background-color: #408140 \9;
}
.b2c-btn-info {
color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
background-color: #49afcd;
*background-color: #2f96b4;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
background-repeat: repeat-x;
border-color: #2f96b4 #2f96b4 #1f6377;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
filter: progid:dximagetransform.microsoft.gradient(enabled=false);
}
.b2c-btn-info:hover,
.b2c-btn-info:active,
.b2c-btn-info.active,
.b2c-btn-info.disabled,
.b2c-btn-info[disabled] {
color: #ffffff;
background-color: #2f96b4;
*background-color: #2a85a0;
}
.b2c-btn-info:active,
.b2c-btn-info.active {
background-color: #24748c \9;
}
.b2c-btn-inverse {
color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
background-color: #363636;
*background-color: #222222;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
background-image: -webkit-linear-gradient(top, #444444, #222222);
background-image: -o-linear-gradient(top, #444444, #222222);
background-image: linear-gradient(to bottom, #444444, #222222);
background-image: -moz-linear-gradient(top, #444444, #222222);
background-repeat: repeat-x;
border-color: #222222 #222222 #000000;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
filter: progid:dximagetransform.microsoft.gradient(enabled=false);
}
.b2c-btn-inverse:hover,
.b2c-btn-inverse:active,
.b2c-btn-inverse.active,
.b2c-btn-inverse.disabled,
.b2c-btn-inverse[disabled] {
color: #ffffff;
background-color: #222222;
*background-color: #151515;
}
.b2c-btn-inverse:active,
.b2c-btn-inverse.active {
background-color: #080808 \9;
}
button.b2c-btn,
input[type="submit"].b2c-btn {
*padding-top: 3px;
*padding-bottom: 3px;
}
button.b2c-btn::-moz-focus-inner,
input[type="submit"].b2c-btn::-moz-focus-inner {
padding: 0;
border: 0;
}
button.b2c-btn.b2c-btn-large,
input[type="submit"].b2c-btn.b2c-btn-large {
*padding-top: 7px;
*padding-bottom: 7px;
}
button.b2c-btn.b2c-btn-small,
input[type="submit"].b2c-btn.b2c-btn-small {
*padding-top: 3px;
*padding-bottom: 3px;
}
button.b2c-btn.b2c-btn-mini,
input[type="submit"].b2c-btn.b2c-btn-mini {
*padding-top: 1px;
*padding-bottom: 1px;
}
.b2c-input-append {
display: inline-block;
margin-bottom: 10px;
white-space: nowrap;
vertical-align: middle;
}
.b2c-input-append input,
.b2c-input-append select,
.b2c-input-append .b2c-uneditable-input,
.b2c-input-append .b2c-dropdown-menu,
.b2c-input-append .b2c-popover {
font-size: 14px;
}
.b2c-input-append input,
.b2c-input-append select,
.b2c-input-append .b2c-uneditable-input {
position: relative;
margin-bottom: 0;
*margin-left: 0;
vertical-align: top;
-webkit-border-radius: 0 4px 4px 0;
-moz-border-radius: 0 4px 4px 0;
border-radius: 0 4px 4px 0;
}
.b2c-input-append input:focus,
.b2c-input-append select:focus,
.b2c-input-append .b2c-b2c-uneditable-input:focus {
z-index: 2;
}
.b2c-input-append .b2c-add-on {
display: inline-block;
width: auto;
height: 20px;
min-width: 16px;
padding: 4px 5px;
font-size: 14px;
font-weight: normal;
line-height: 20px;
text-align: center;
text-shadow: 0 1px 0 #ffffff;
background-color: #eeeeee;
border: 1px solid #ccc;
}
.b2c-input-append .b2c-add-on,
.b2c-input-append .b2c-btn,
.b2c-input-append .b2c-btn-group > .b2c-dropdown-toggle {
vertical-align: top;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
}
.b2c-input-append .b2c-active {
background-color: #a9dba9;
border-color: #46a546;
}
.b2c-input-append input,
.b2c-input-append select,
.b2c-input-append .b2c-uneditable-input {
-webkit-border-radius: 4px 0 0 4px;
-moz-border-radius: 4px 0 0 4px;
border-radius: 4px 0 0 4px;
}
.b2c-input-append .b2c-add-on,
.b2c-input-append .b2c-btn,
.b2c-input-append .b2c-btn-group {
margin-left: -1px;
}
.b2c-input-append .b2c-add-on:last-child,
.b2c-input-append .b2c-btn:last-child,
.b2c-input-append .b2c-btn-group:last-child > .b2c-dropdown-toggle {
-webkit-border-radius: 0 4px 4px 0;
-moz-border-radius: 0 4px 4px 0;
border-radius: 0 4px 4px 0;
}

View file

@ -0,0 +1,172 @@
.cip-ui-autocomplete li.cip-ui-menu-item {
text-align: left !important;
font-size: 12px !important;
font-weight: normal !important;
font-style: normal !important;
font-family: Verdana, Arial, sans-serif !important;
color: #222222 !important;
}
.cip-ui-dialog-titlebar-close {
visibility: hidden !important;
}
.cip-ui-widget-overlay {
background: none !important;
z-index: 2147483601 !important;
}
.cip-ui-dialog {
z-index: 2147483602 !important;
}
.cip-ui-dialog .cip-ui-dialog-title {
font-size:.8em !important;
}
.cip-ui-dialog .cip-ui-dialog-titlebar {
padding:.1em .5em !important;
}
.cip-ui-dialog-content {
font-size: .8em !important;
}
#cip-genpw-dialog {
text-align: left !important;
}
#cip-genpw-dialog button {
height: 26px !important;
}
.cip-genpw-clearfix:after {
clear: both;
line-height: 0;
content: "";
display: table;
}
.cip-genpw-icon {
position: absolute;
cursor: pointer;
}
.cip-genpw-icon.cip-icon-key-small {
width: 16px;
height: 16px;
background-image: url(chrome-extension://__MSG_@@extension_id__/icons/key_16x16.png);
}
.cip-genpw-icon.cip-icon-key-big {
width: 24px;
height: 24px;
background-image: url(chrome-extension://__MSG_@@extension_id__/icons/key_24x24.png);
}
.cip-genpw-password-frame {
margin-top: 5px !important;
margin-bottom: 5px !important;
}
.cip-genpw-password-frame > * {
height: 20px !important;
font-size: 11px !important;
}
.cip-genpw-textfield {
background: none !important;
font-size: 11px !important;
display: inline !important;
border: 1px solid rgb(170, 170, 170) !important;
padding: 1px 2px !important;
max-width: none !important;
min-width: 0 !important;
font-size: 1em !important;
width: 240px !important;
padding-left: 5px !important;
}
#cip-genpw-quality {
width: 50px !important;
padding-top: 1px !important;
padding-bottom: 1px !important;
}
.cip-genpw-label {
display: block !important;
margin: 5px 0 !important;
}
.cip-genpw-checkbox {
vertical-align: middle !important;
}
#cip-genpw-btn-fillin {
margin-right: 5px;
}
.b2c-modal-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2147483645;
}
.b2c-modal-backdrop:after {
content:'';
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #000000;
opacity: 0.8;
filter: alpha(opacity=80);
}
#b2c-cipDefine-fields {
z-index: 2147483646;
}
#b2c-cipDefine-description {
z-index: 2147483646;
color: #efefef;
border: 2px solid #555555;
padding: 7px 5px;
position: absolute;
top: 100px;
left: 150px;
text-align: left;
cursor: pointer;
background-color:rgba(255,255,255,0.3);
font-size: 15px;
}
#b2c-cipDefine-description div:first-of-type {
margin-top: 0;
padding-top: 0;
text-align: left;
color: #efefef;
padding-bottom: 8px;
font-weight: bold;
font-size: 160%;
}
#b2c-cipDefine-description p {
margin-top: 10px;
padding-top: 10px;
color: #efefef;
border-top: 2px solid #666666;
line-height: 110%;
}
#b2c-help {
margin-bottom: 3px;
}
.b2c-fixed-field {
position: absolute;
border: 2px solid #efefef;
cursor: pointer;
z-index: 2147483646;
text-align: left;
font-weight: bold;
background-color:rgba(239,239,239,0.4);
}
.b2c-fixed-hover-field {
border: 2px solid orange;
background-color:rgba(255,165,239,0.4);
}
.b2c-fixed-password-field {
border: 2px solid red;
color: #efefef;
background-color:rgba(255,0,0,0.4);
}
.b2c-fixed-username-field {
border: 2px solid limegreen;
color: #efefef;
background-color:rgba(50,205,50,0.4);
}
.b2c-fixed-string-field {
border: 2px solid deepskyblue;
color: #efefef;
background-color:rgba(30,144,255,0.4);
}

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

17
chromeKeePassXC/jquery-1.11.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

4
chromeKeePassXC/jquery-2.2.3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

4
chromeKeePassXC/jquery-3.2.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,85 @@
{
"name": "chromeKeePassXC",
"version": "0.1.0",
"manifest_version": 2,
"description": "KeePassXC integration for Chrome",
"icons": {
"16": "icons/keepassxc_16x16.png",
"48": "icons/keepassxc_48x48.png",
"128": "icons/keepassxc_128x128.png"
},
"browser_action": {
"default_icon": {
"19": "icons/keepassxc_19x19.png",
"38": "icons/keepassxc_38x38.png"
},
"default_title": "chromeKeePassXC",
"default_popup": "popups/popup.html"
},
"options_page": "options/options.html",
"background": {
"scripts": [
"background/aes.js",
"background/cryptoHelpers.js",
"background/nacl.min.js",
"background/nacl-util.js",
"background/utf8.js",
"background/keepass.js",
"background/httpauth.js",
"background/browserAction.js",
"background/page.js",
"background/event.js",
"background/init.js"
]
},
"content_scripts": [
{
"matches":
[
"http://*/*",
"https://*/*"
],
"js":
[
"jquery-1.11.1.min.js",
"jquery-ui-1.10.2.custom.min.js",
"chromekeepassxc.js"
],
"css":
[
"jquery-ui-1.10.2.custom.min.css",
"bootstrap-btn.css",
"chromekeepassxc.css"
],
"run_at": "document_idle",
"all_frames": true
}
],
"web_accessible_resources": [
"jquery.min.map",
"icons/key_16x16.png",
"icons/key_24x24.png",
"images/ui-bg_flat_0_aaaaaa_40x100.png",
"images/ui-bg_flat_0_aaaaaa_40x100.png",
"images/ui-bg_flat_75_ffffff_40x100.png",
"images/ui-bg_glass_55_fbf9ee_1x400.png",
"images/ui-bg_glass_65_ffffff_1x400.png",
"images/ui-bg_glass_75_dadada_1x400.png",
"images/ui-bg_glass_75_e6e6e6_1x400.png",
"images/ui-bg_glass_95_fef1ec_1x400.png",
"images/ui-bg_highlight-soft_75_cccccc_1x100.png"
],
"permissions": [
"contextMenus",
"clipboardWrite",
"nativeMessaging",
"tabs",
"webRequest",
"webRequestBlocking",
"https://*/*",
"http://*/*",
"https://raw.github.com/"
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -0,0 +1,368 @@
<!DOCTYPE html>
<html>
<head>
<title>Settings | chromeKeePassXC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="../bootstrap-btn.css" />
<link href="bootstrap-responsive.min.css" rel="stylesheet" />
<script type="text/javascript" src="../jquery-1.11.1.min.js"></script>
<!--<script type="text/javascript" src="../jquery-3.2.0.min.js"></script>-->
<script type="text/javascript" src="bootstrap.min.js"></script>
<script type="text/javascript" src="options.js"></script>
<style type="text/css">
body {
padding-top: 20px;
padding-bottom: 60px;
}
/* Custom container */
.container {
margin: 0 auto;
max-width: 1000px;
}
.container > hr {
margin: 30px 0;
}
/* Customize the navbar links to be fill the entire space of the .navbar */
.navbar .navbar-inner {
padding: 0;
margin-bottom: 40px;
}
.navbar .nav {
margin: 0;
display: table;
width: 100%;
}
.navbar .nav li {
display: table-cell;
width: 1%;
float: none;
}
.navbar .nav li a {
font-weight: bold;
text-align: center;
border-left: 1px solid rgba(255,255,255,.75);
border-right: 1px solid rgba(0,0,0,.1);
}
.navbar .nav li:first-child a {
border-left: 0;
border-radius: 3px 0 0 3px;
}
.navbar .nav li:last-child a {
border-right: 0;
border-radius: 0 3px 3px 0;
}
.tab {
display: none;
}
h2+hr {
margin-top: 0;
}
#tab-connected-databases .color.dropdown .dropdown-menu {
width: 180px;
padding: 7px 10px;
line-height: 175%;
}
#tab-connected-databases .color.dropdown .dropdown-menu a {
margin-right: 3px;
}
#tab-connected-databases .color.dropdown a.dropdown-toggle img {
margin-right: 5px;
}
tr.clone {
display: none;
}
td.last-used,
td.created {
white-space: nowrap;
}
.bold {
font-weight: bold;
}
.radio.inline,
.checkbox.inline {
display: inline-block;
white-space: nowrap;
}
.radio.inline + .radio.inline,
.checkbox.inline + .checkbox.inline {
margin-left: 40px;
}
.checkUpdateKeePassXC {
margin-left: 40px;
}
#dangerousSettings {
display: none;
}
</style>
</head>
<body>
<div class="container">
<div class="masthead">
<h3 class="muted"><img src="/icons/keepassxc_48x48.png" alt="logo" /> chromeKeePassXC</h3>
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<ul class="nav">
<li class="active"><a href="#general-settings">General</a></li>
<li><a href="#connected-databases">Connected Databases</a></li>
<li><a href="#specified-fields">Specified credential fields</a></li>
<li><a href="#about">About</a></li>
</ul>
</div>
</div>
</div><!-- /.navbar -->
</div>
<!-- General Settings -->
<div class="tab" id="tab-general-settings">
<h2>General Settings</h2>
<hr />
<p>
If you just want to insert username + password into the fields where your focus is, press Ctrl + Shift + U.
<br />
If you only want to insert the password, just press Ctrl + Shift + P.
</p>
<p>
<label for="blinkTimeout">Blink Time:</label>
<div class="control-group">
<div class="input-append">
<input type="number" id="blinkTimeout" placeholder="7500" value="7500" />
<button class="btn" id="blinkTimeoutButton" type="button">Save</button>
</div>
<span class="help-inline">
What is the maximum time (ms) the icon should blink after detecting new credentials
<br />
Default: 7500
</span>
</div>
</p>
<p>
<label for="blinkMinTimeout">Redirect Offset:</label>
<div class="control-group">
<div class="input-append">
<input type="number" id="blinkMinTimeout" placeholder="2000" value="2000" />
<button class="btn" id="blinkMinTimeoutButton" type="button">Save</button>
</div>
<span class="help-inline">
What is the minimum time (ms) the icon should blink before deactivating due to page redirects.
<br />
-1 to only use <i>Blink Time</i> ignoring Redirect Allowance (old behavior)
<br />
Default: -1, Recommended: 2000
</span>
</div>
</p>
<p>
<label for="allowedRedirect">Redirect Allowance:</label>
<div class="control-group">
<div class="input-append">
<input type="number" id="allowedRedirect" placeholder="1" value="1" />
<button class="btn" id="allowedRedirectButton" type="button">Save</button>
</div>
<span class="help-inline">
How many pages should the tab cycle through after the redirect offset before deactivating the icon
<br />
Default: 1
</span>
</div>
</p>
<hr />
<p>
<label class="checkbox">
<input type="checkbox" name="usePasswordGenerator" value="1" /> Activate password generator.
</label>
<span class="help-block">For all password-fields there will be an icon added to generate a new password.<br />
It is generated by KeePassXC with the profile for automatically generated passwords for new entries.</span>
</p>
<hr />
<p>
<label class="checkbox">
<input type="checkbox" name="autoRetrieveCredentials" value="1" /> Automatically retrieve credentials.
</label>
<span class="help-block">chromeKeePassXC will immediately retrieve the credentials when the tab is activated.</span>
</p>
<hr />
<p>
<label class="checkbox">
<input type="checkbox" name="autoFillSingleEntry" value="1" /> Automatically fill-in single credentials entry.
</label>
<span class="help-block">If chromeKeePassXC does only receive a single entry from KeePassXC it automatically fills this credentials into the found credential fields.</span>
</p>
<hr />
<p>
<label class="checkbox">
<input type="checkbox" name="autoCompleteUsernames" value="1" /> Activate autocomplete for username fields.
</label>
<span class="help-block">For all username fields on a page a dropdown list appears which contains all available credentials.</span>
</p>
<hr />
<p>
Check for updates of KeePassXC:
<br />
<label class="radio inline"><input type="radio" name="checkUpdateKeePassXC" value="3" /> every 3 days</label>
<label class="radio inline"><input type="radio" name="checkUpdateKeePassXC" value="7" /> every week</label>
<label class="radio inline"><input type="radio" name="checkUpdateKeePassXC" value="30" /> every month</label>
<label class="radio inline"><input type="radio" name="checkUpdateKeePassXC" value="0" /> never</label>
</p>
<div class="help-block kphVersion">
chromeKeePassXC needs KeePassXC to retrieve credentials.
<br />
You can download the latest stable version from here: <a target="_blank" href="https://keepassxc.org/">https://keepassxc.org/</a>
<br />
<br />
<div class="row">
<div class="span3">Your running version of KeePassXC:</div>
<div class="span6"><em class="yourVersion"></em></div>
</div>
<div class="row">
<div class="span3">Latest available version of KeePassXC:</div>
<div class="span6"><em class="latestVersion"></em><button class="btn btn-mini checkUpdateKeePassXC">Check for updates</button></div>
</div>
</div>
<hr />
<p>
<label class="checkbox">
<input type="checkbox" name="autoFillAndSend" value="1" /> Auto fill HTTP Auth dialogs and send them.
</label>
<span class="help-block">
If credentials are found for a page and the login-type is an HTTP Auth request, chromeKeePassXC tries to login with the first given credentials.
<br />
An HTTP Auth dialog looks like this:
</span>
<img src="/options/http-auth-dialog.png" alt="http-auth-dialog" />
</p>
<hr />
</div>
<!-- Connected Databases -->
<div class="tab" id="tab-connected-databases">
<h2>Connected Databases</h2>
<hr />
<p>
If you are using several KeePass databases you can define a specific icon-color to each of them.
<br />
This will help you to easily determine from which database the credentials are retrieved.
</p>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th class="span5">Identifier</th>
<th class="span2">Icon</th>
<th class="span2">Last used</th>
<th class="span2">Created</th>
<th class="span1">Delete</th>
</tr>
</thead>
<tbody>
<tr class="empty">
<td colspan="5">No connected databases found.</td>
</tr>
<tr class="clone">
<td></td>
<td></td>
<td class="last-used"></td>
<td class="created"></td>
<td><button class="btn delete btn-danger">Remove</button></td>
</tr>
</tbody>
</table>
<div style="text-align: right">
<button id="connect-button" class="b2c-btn b2c-btn-primary">Connect</button>
</div>
<div id="dialogDeleteConnectedDatabase" class="modal hide" tabindex="-1" role="dialog">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Remove identifier from Chrome?</h3>
</div>
<div class="modal-body">
<p>Do you really want to remove the identifier <span class="bold"></span> from Chrome?</p>
<p class="help-block">You can reconnect your database at any time.</p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button class="btn yes btn-primary">Yes, remove now</button>
</div>
</div>
</div>
<!-- Specified credential fields -->
<div class="tab" id="tab-specified-fields">
<h2>Specified credential fields</h2>
<hr />
<p>
If chromeKeePassXC detects the wrong credential fields, you are able to specify the correct fields by yourself.
<br />
Just go to the page and click on the chromeKeePassXC-Icon, now select <em>Choose own credential fields for this page</em>.
<br />
On this page you can manage theses specified credential fields.
</p>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th class="span10">Page URL</th>
<th class="span2">Delete</th>
</tr>
</thead>
<tbody>
<tr class="empty">
<td colspan="2">No specified credential fields found.</td>
</tr>
<tr class="clone">
<td></td>
<td><button class="btn delete btn-danger btn">Remove</button></td>
</tr>
</tbody>
</table>
<div id="dialogDeleteSpecifiedCredentialFields" class="modal hide" tabindex="-1" role="dialog">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Remove specified credential fields?</h3>
</div>
<div class="modal-body">
<p>Do you really want to remove the specified credential fields on the page <strong></strong>?</p>
<p class="help-block">chromeKeePassXC will automatically detect the credential fields the next time you visit this page.</p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button class="btn yes btn-primary">Yes, remove now</button>
</div>
</div>
</div>
<!-- About -->
<div class="tab" id="tab-about">
<h2>About</h2>
<hr />
<p>
Developed by <a target="_blank" href="https://github.com/pfn/">Perry Nguyen</a>, <a target="_blank" href="http://lukas-schulze.de">Lukas Schulze</a> and
<a target="_blank" href="https://github.com/varjolintu/">Sami Vänttinen</a>
</p>
<p>
<a target="_blank" href="https://chrome.google.com/webstore/detail/chromeipass/ompiailgknfdndiefoaoiligalphfdae">Visit extension's page in Chrome Web store</a>
</p>
<p>
<a target="_blank" href="https://github.com/varjolintu/chromeKeePassXC">Visit project's page in GitHub</a>.
</p>
<hr />
<div class="row">
<div class="span2">chromeKeePassXC Version:</div>
<div class="span6"><em class="versionCIP"></em></div>
</div>
<div class="row">
<div class="span2">KeePassXC Version:</div>
<div class="span6"><em class="versionKPH"></em></div>
</div>
</div>
<hr>
<div class="footer">
<p>2010-2017 - Perry Nguyen, Lukas Schulze, Sami Vänttinen</p>
</div>
</div> <!-- /container -->
</body>
</html>

View file

@ -0,0 +1,314 @@
if(cIPJQ) {
var $ = cIPJQ.noConflict(true);
}
$(function() {
options.initMenu();
options.initGeneralSettings();
options.initConnectedDatabases();
options.initSpecifiedCredentialFields();
options.initAbout();
});
var options = options || {};
options.settings = typeof(localStorage.settings)=='undefined' ? {} : JSON.parse(localStorage.settings);
options.keyRing = typeof(localStorage.keyRing)=='undefined' ? {} : JSON.parse(localStorage.keyRing);
options.initMenu = function() {
$(".navbar:first ul.nav:first li a").click(function(e) {
e.preventDefault();
$(".navbar:first ul.nav:first li").removeClass("active");
$(this).parent("li").addClass("active");
$("div.tab").hide();
$("div.tab#tab-" + $(this).attr("href").substring(1)).fadeIn();
});
$("div.tab:first").show();
}
options.initGeneralSettings = function() {
$("#tab-general-settings input[type=checkbox]").each(function() {
$(this).attr("checked", options.settings[$(this).attr("name")]);
});
$("#tab-general-settings input[type=checkbox]").change(function() {
options.settings[$(this).attr("name")] = $(this).is(':checked');
localStorage.settings = JSON.stringify(options.settings);
chrome.extension.sendMessage({
action: 'load_settings'
});
});
$("#tab-general-settings input[type=radio]").each(function() {
if($(this).val() == options.settings[$(this).attr("name")]) {
$(this).attr("checked", options.settings[$(this).attr("name")]);
}
});
$("#tab-general-settings input[type=radio]").change(function() {
options.settings[$(this).attr("name")] = $(this).val();
localStorage.settings = JSON.stringify(options.settings);
chrome.extension.sendMessage({
action: 'load_settings'
});
});
chrome.extension.sendMessage({
action: "get_keepassxc_versions"
}, options.showKeePassXCVersions);
$("#tab-general-settings button.checkUpdateKeePassXC:first").click(function(e) {
e.preventDefault();
$(this).attr("disabled", true);
chrome.extension.sendMessage({
action: "check_update_keepassxc"
}, options.showKeePassXCVersions);
});
$("#showDangerousSettings").click(function() {
$('#dangerousSettings').is(":visible") ? $(this).text("Show these settings anyway") : $(this).text("Hide");
$("#dangerousSettings").toggle();
});
$("#hostname").val(options.settings["hostname"]);
$("#port").val(options.settings["port"]);
$("#blinkTimeout").val(options.settings["blinkTimeout"]);
$("#blinkMinTimeout").val(options.settings["blinkMinTimeout"]);
$("#allowedRedirect").val(options.settings["allowedRedirect"]);
$("#portButton").click(function() {
var port = $.trim($("#port").val());
var portNumber = parseInt(port);
if(isNaN(port) || portNumber < 1025 || portNumber > 99999) {
$("#port").closest(".control-group").addClass("error");
alert("The port number has to be in range 1025 - 99999.\nNothing saved!");
return;
}
options.settings["port"] = portNumber.toString();
$("#port").closest(".control-group").removeClass("error").addClass("success");
setTimeout(function() {$("#port").closest(".control-group").removeClass("success")}, 2500);
localStorage.settings = JSON.stringify(options.settings);
chrome.extension.sendMessage({
action: 'load_settings'
});
});
$("#hostnameButton").click(function() {
var hostname = $("#hostname").val();
if($.trim(hostname) == "") {
$("#hostname").closest(".control-group").addClass("error");
alert("Hostname cannot be empty.\nNothing saved!");
return;
}
options.settings["hostname"] = hostname;
$("#hostname").closest(".control-group").removeClass("error").addClass("success");
setTimeout(function() {$("#hostname").closest(".control-group").removeClass("success")}, 2500);
localStorage.settings = JSON.stringify(options.settings);
chrome.extension.sendMessage({
action: 'load_settings'
});
});
$("#blinkTimeoutButton").click(function(){
var blinkTimeout = $.trim($("#blinkTimeout").val());
var blinkTimeoutval = parseInt(blinkTimeout);
options.settings["blinkTimeout"] = blinkTimeoutval.toString();
$("#blinkTimeout").closest(".control-group").removeClass("error").addClass("success");
setTimeout(function() {$("#blinkTimeout").closest(".control-group").removeClass("success")}, 2500);
localStorage.settings = JSON.stringify(options.settings);
chrome.extension.sendMessage({
action: 'load_settings'
});
});
$("#blinkMinTimeoutButton").click(function(){
var blinkMinTimeout = $.trim($("#blinkMinTimeout").val());
var blinkMinTimeoutval = parseInt(blinkMinTimeout);
options.settings["blinkMinTimeout"] = blinkMinTimeoutval.toString();
$("#blinkMinTimeout").closest(".control-group").removeClass("error").addClass("success");
setTimeout(function() {$("#blinkMinTimeout").closest(".control-group").removeClass("success")}, 2500);
localStorage.settings = JSON.stringify(options.settings);
chrome.extension.sendMessage({
action: 'load_settings'
});
});
$("#allowedRedirectButton").click(function(){
var allowedRedirect = $.trim($("#allowedRedirect").val());
var allowedRedirectval = parseInt(allowedRedirect);
options.settings["allowedRedirect"] = allowedRedirectval.toString();
$("#allowedRedirect").closest(".control-group").removeClass("error").addClass("success");
setTimeout(function() {$("#allowedRedirect").closest(".control-group").removeClass("success")}, 2500);
localStorage.settings = JSON.stringify(options.settings);
chrome.extension.sendMessage({
action: 'load_settings'
});
});
};
options.showKeePassXCVersions = function(response) {
if(response.current <= 0) {
response.current = "unknown";
}
if(response.latest <= 0) {
response.latest = "unknown";
}
$("#tab-general-settings .kphVersion:first em.yourVersion:first").text(response.current);
$("#tab-general-settings .kphVersion:first em.latestVersion:first").text(response.latest);
$("#tab-about em.versionKPH").text(response.current);
$("#tab-general-settings button.checkUpdateKeePassXC:first").attr("disabled", false);
}
options.initConnectedDatabases = function() {
$("#dialogDeleteConnectedDatabase").modal({keyboard: true, show: false, backdrop: true});
$("#tab-connected-databases tr.clone:first button.delete:first").click(function(e) {
e.preventDefault();
$("#dialogDeleteConnectedDatabase").data("hash", $(this).closest("tr").data("hash"));
$("#dialogDeleteConnectedDatabase .modal-body:first span:first").text($(this).closest("tr").children("td:first").text());
$("#dialogDeleteConnectedDatabase").modal("show");
});
$("#dialogDeleteConnectedDatabase .modal-footer:first button.yes:first").click(function(e) {
$("#dialogDeleteConnectedDatabase").modal("hide");
var $hash = $("#dialogDeleteConnectedDatabase").data("hash");
$("#tab-connected-databases #tr-cd-" + $hash).remove();
delete options.keyRing[$hash];
localStorage.keyRing = JSON.stringify(options.keyRing);
chrome.extension.sendMessage({
action: 'load_keyring'
});
if($("#tab-connected-databases table tbody:first tr").length > 2) {
$("#tab-connected-databases table tbody:first tr.empty:first").hide();
}
else {
$("#tab-connected-databases table tbody:first tr.empty:first").show();
}
});
$("#tab-connected-databases tr.clone:first .dropdown-menu:first").width("230px");
$("#tab-connected-databases tr.clone:first .color.dropdown .dropdown-menu a").click(function(e) {
e.preventDefault();
var $icon = $(this).attr("href").substring(1);
var $hash = $(this).closest("tr").data("hash");
$(this).parent().parent().find("a.dropdown-toggle:first").find("img:first").attr("src", "/icons/19x19/icon_normal_" + $icon + "_19x19.png");
options.keyRing[$hash].icon = $icon;
localStorage.keyRing = JSON.stringify(options.keyRing);
chrome.extension.sendMessage({
action: 'load_keyring'
});
});
var $trClone = $("#tab-connected-databases table tr.clone:first").clone(true);
$trClone.removeClass("clone");
for(var hash in options.keyRing) {
var $tr = $trClone.clone(true);
$tr.data("hash", hash);
$tr.attr("id", "tr-cd-" + hash);
var $icon = options.keyRing[hash].icon || "blue";
$("a.dropdown-toggle:first img:first", $tr).attr("src", "/icons/19x19/icon_normal_" + $icon + "_19x19.png");
$tr.children("td:first").text(options.keyRing[hash].id);
var lastUsed = (options.keyRing[hash].lastUsed) ? new Date(options.keyRing[hash].lastUsed).toLocaleString() : "unknown";
$tr.children("td:eq(2)").text(lastUsed);
var date = (options.keyRing[hash].created) ? new Date(options.keyRing[hash].created).toLocaleDateString() : "unknown";
$tr.children("td:eq(3)").text(date);
$("#tab-connected-databases table tbody:first").append($tr);
}
if($("#tab-connected-databases table tbody:first tr").length > 2) {
$("#tab-connected-databases table tbody:first tr.empty:first").hide();
}
else {
$("#tab-connected-databases table tbody:first tr.empty:first").show();
}
$("#connect-button").click(function() {
chrome.extension.sendMessage({
action: "associate"
});
});
}
options.initSpecifiedCredentialFields = function() {
$("#dialogDeleteSpecifiedCredentialFields").modal({keyboard: true, show: false, backdrop: true});
$("#tab-specified-fields tr.clone:first button.delete:first").click(function(e) {
e.preventDefault();
$("#dialogDeleteSpecifiedCredentialFields").data("url", $(this).closest("tr").data("url"));
$("#dialogDeleteSpecifiedCredentialFields").data("tr-id", $(this).closest("tr").attr("id"));
$("#dialogDeleteSpecifiedCredentialFields .modal-body:first strong:first").text($(this).closest("tr").children("td:first").text());
$("#dialogDeleteSpecifiedCredentialFields").modal("show");
});
$("#dialogDeleteSpecifiedCredentialFields .modal-footer:first button.yes:first").click(function(e) {
$("#dialogDeleteSpecifiedCredentialFields").modal("hide");
var $url = $("#dialogDeleteSpecifiedCredentialFields").data("url");
var $trId = $("#dialogDeleteSpecifiedCredentialFields").data("tr-id");
$("#tab-specified-fields #" + $trId).remove();
delete options.settings["defined-credential-fields"][$url];
localStorage.settings = JSON.stringify(options.settings);
chrome.extension.sendMessage({
action: 'load_settings'
});
if($("#tab-specified-fields table tbody:first tr").length > 2) {
$("#tab-specified-fields table tbody:first tr.empty:first").hide();
}
else {
$("#tab-specified-fields table tbody:first tr.empty:first").show();
}
});
var $trClone = $("#tab-specified-fields table tr.clone:first").clone(true);
$trClone.removeClass("clone");
var counter = 1;
for(var url in options.settings["defined-credential-fields"]) {
var $tr = $trClone.clone(true);
$tr.data("url", url);
$tr.attr("id", "tr-scf" + counter);
counter += 1;
$tr.children("td:first").text(url);
$("#tab-specified-fields table tbody:first").append($tr);
}
if($("#tab-specified-fields table tbody:first tr").length > 2) {
$("#tab-specified-fields table tbody:first tr.empty:first").hide();
}
else {
$("#tab-specified-fields table tbody:first tr.empty:first").show();
}
}
options.initAbout = function() {
$("#tab-about em.versionCIP").text(chrome.app.getDetails().version);
}

View file

@ -0,0 +1,74 @@
body {
font-family: sans-serif;
min-width:357px;
overflow-x:hidden;
background: #eee;
font-size: 15px;
}
.credentials ul {
margin-left: 0;
margin-right: 0;
padding-left: 0;
padding-right: 0;
list-style-position: inside;
}
.credentials li {
list-style: none;
padding-top: 1px;
padding-bottom: 1px;
padding-left: 10px;
padding-right: 5px;
margin-left: 10px;
margin-right: 5px;
}
.credentials a {
cursor: pointer;
display: block;
color: #336;
}
.credentials li:hover {
cursor: pointer;
background: #ccc;
}
.settings {
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #333;
font-size: 90%;
}
.settings label {
display: block;
}
.settings label input {
vertical-align: middle;
}
.settings .description {
margin-top: 3px;
font-size: 80%;
color: #787878;
}
.small {
margin-top: 3px;
margin-left: 12px;
font-size: 80%;
color: #787878;
}
#update-available {
display: none;
font-size: 90%;
color: #cc0000;
font-weight: bold;
border-top: 1px solid #333;
padding-top: 10px;
margin-top: 10px;
}
#update-available a:link,
#update-available a:visited {
text-decoration: underline;
color: #cc0000;
}
#update-available a:hover,
#update-available a:active {
text-decoration: none;
}

View file

@ -0,0 +1,81 @@
<html>
<head>
<title>KeePassXC - Popup</title>
<link rel="stylesheet" href="popup.css" />
<link rel="stylesheet" href="../bootstrap-btn.css" />
<script type="text/javascript" src="../jquery-1.11.1.min.js"></script>
<!--<script type="text/javascript" src="../jquery-3.2.0.min.js">-->
<script type="text/javascript" src="popup_functions.js"></script>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<div id="settings" class="settings">
<button id="btn-options" class="b2c-btn b2c-btn-small b2c-btn-warning">Settings</button>
<button id="btn-choose-credential-fields" class="b2c-btn b2c-btn-small">Choose own credential fields for this page</button>
<div id="update-available">
You use an old version of KeePassXC.
<br />
<a target="_blank" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>.
</div>
</div>
<div id="initial-state">
<p><img style="margin-right: 1em" src="throbber.gif"/> Checking status...</p>
</div>
<div id="not-configured" style="display: none">
<p>
chromeKeePassXC has not been configured.
Press the connect button to register and pair with KeePassXC.
</p>
<div style="text-align: right">
<button id="connect-button" class="b2c-btn b2c-btn-primary">Connect</button>
</div>
</div>
<div id="need-reconfigure" style="display: none">
<p>
chromeKeePassXC has been disconnected from KeePassXC.
</p>
<code id="need-reconfigure-message"></code>
<p>
Press the reconnect button to establish a new connection.
</p>
<div style="text-align: right">
<button id="reconnect-button" class="b2c-btn b2c-btn-primary">Reconnect</button>
</div>
</div>
<div id="configured-not-associated" style="display: none">
<p>
chromeKeePassXC has been configured using the identifier
<em id="unassociated-identifier"></em> and has not yet
connected to KeePassXC.
</p>
</div>
<div id="configured-and-associated" style="display: none">
<p>
chromeKeePassXC has been configured using the identifier
"<em id="associated-identifier"></em>" and is successfully
connected to KeePassXC.
</p>
<div style="text-align: right">
<button id="redetect-fields-button" class="b2c-btn">Redetect credential fields</button>
</div>
</div>
<div id="error-encountered" style="display: none">
<p>
chromeKeePassXC has encountered an error:
</p>
<p style="margin-left: 1em">
<code id="error-message"></code>
</p>
<div style="text-align: right">
<button id="reload-status-button" class="b2c-btn">Reload</button>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,73 @@
function status_response(r) {
$('#initial-state').hide();
$('#error-encountered').hide();
$('#need-reconfigure').hide();
$('#not-configured').hide();
$('#configured-and-associated').hide();
$('#configured-not-associated').hide();
if(!r.keePassXCAvailable || r.databaseClosed) {
$('#error-message').html(r.error);
$('#error-encountered').show();
}
else if(!r.configured) {
$('#not-configured').show();
}
else if(r.encryptionKeyUnrecognized) {
$('#need-reconfigure').show();
$('#need-reconfigure-message').html(r.error);
}
else if(!r.associated) {
//$('#configured-not-associated').show();
//$('#unassociated-identifier').html(r.identifier);
$('#need-reconfigure').show();
$('#need-reconfigure-message').html(r.error);
}
else if(typeof(r.error) != "undefined") {
$('#error-encountered').show();
$('#error-message').html(r.error);
}
else {
$('#configured-and-associated').show();
$('#associated-identifier').html(r.identifier);
}
}
$(function() {
$("#connect-button").click(function() {
chrome.extension.sendMessage({
action: "associate"
});
close();
});
$("#reconnect-button").click(function() {
chrome.extension.sendMessage({
action: "associate"
});
close();
});
$("#reload-status-button").click(function() {
chrome.extension.sendMessage({
action: "get_status"
}, status_response);
});
$("#redetect-fields-button").click(function() {
chrome.tabs.query({"active": true, "windowId": chrome.windows.WINDOW_ID_CURRENT}, function(tabs) {
if (tabs.length === 0)
return; // For example: only the background devtools or a popup are opened
var tab = tabs[0];
chrome.tabs.sendMessage(tab.id, {
action: "redetect_fields"
});
});
});
chrome.extension.sendMessage({
action: "get_status"
}, status_response);
});

View file

@ -0,0 +1,38 @@
var $ = cIPJQ.noConflict(true);
var _settings = typeof(localStorage.settings)=='undefined' ? {} : JSON.parse(localStorage.settings);
//var global = chrome.extension.getBackgroundPage();
function updateAvailableResponse(available) {
if(available) {
$("#update-available").show();
}
else {
$("#update-available").hide();
}
}
function initSettings() {
$("#settings #btn-options").click(function() {
close();
chrome.tabs.create({
url: "../options/options.html"
})
});
$("#settings #btn-choose-credential-fields").click(function() {
var global = chrome.extension.getBackgroundPage();
chrome.tabs.sendMessage(global.page.currentTabId, {
action: "choose_credential_fields"
});
close();
});
}
$(function() {
initSettings();
chrome.extension.sendMessage({
action: "update_available_keepassxc"
}, updateAvailableResponse);
});

View file

@ -0,0 +1,29 @@
<html>
<head>
<title>KeePassXC - Popup</title>
<link rel="stylesheet" href="popup.css" />
<link rel="stylesheet" href="../bootstrap-btn.css" />
<script type="text/javascript" src="../jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="popup_functions.js"></script>
<script type="text/javascript" src="popup_httpauth.js"></script>
</head>
<body>
<div id="settings" class="settings">
<button id="btn-options" class="b2c-btn b2c-btn-small b2c-btn-warning">Settings</button>
<button id="btn-choose-credential-fields" class="b2c-btn b2c-btn-small">Choose own credential fields for this page</button>
<div id="update-available">
You use an old version of KeePassXC.
<br />
<a target="_blank" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>.
</div>
</div>
<div class="credentials">
<p>
Select the login information you would like to get logged in with:
</p>
<ul id="login-list"></ul>
</div>
</body>
</html>

View file

@ -0,0 +1,21 @@
$(function() {
var global = chrome.extension.getBackgroundPage();
chrome.tabs.getSelected(null, function(tab) {
//var data = global.tab_httpauth_list["tab" + tab.id];
var data = global.page.tabs[tab.id].loginList;
var ul = document.getElementById("login-list");
for (var i = 0; i < data.logins.length; i++) {
var li = document.createElement("li");
var a = document.createElement("a");
a.textContent = data.logins[i].Login + " (" + data.logins[i].Name + ")";
li.appendChild(a);
$(a).data("url", data.url.replace(/:\/\//g, "://" + data.logins[i].Login + ":" + data.logins[i].Password + "@"));
$(a).click(function() {
chrome.tabs.update(tab.id, {"url": $(this).data("url")});
close();
});
ul.appendChild(li);
}
});
});

View file

@ -0,0 +1,29 @@
<html>
<head>
<title>KeePassXC - Popup</title>
<link rel="stylesheet" href="popup.css" />
<link rel="stylesheet" href="../bootstrap-btn.css" />
<script type="text/javascript" src="../jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="popup_functions.js"></script>
<script type="text/javascript" src="popup_login.js"></script>
</head>
<body>
<div id="settings" class="settings">
<button id="btn-options" class="b2c-btn b2c-btn-small b2c-btn-warning">Settings</button>
<button id="btn-choose-credential-fields" class="b2c-btn b2c-btn-small">Choose own credential fields for this page</button>
<div id="update-available">
You use an old version of KeePassXC.
<br />
<a target="_blank" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>.
</div>
</div>
<div class="credentials">
<p>
Select the login information you would like to get entered into the page:
</p>
<ul id="login-list"></ul>
</div>
</body>
</html>

View file

@ -0,0 +1,28 @@
$(function() {
var global = chrome.extension.getBackgroundPage();
chrome.tabs.query({"active": true, "windowId": chrome.windows.WINDOW_ID_CURRENT}, function(tabs) {
if (tabs.length === 0)
return; // For example: only the background devtools or a popup are opened
var tab = tabs[0];
var logins = global.page.tabs[tab.id].loginList;
var ul = document.getElementById("login-list");
for (var i = 0; i < logins.length; i++) {
var li = document.createElement("li");
var a = document.createElement("a");
a.textContent = logins[i];
li.appendChild(a);
a.setAttribute("id", "" + i);
a.addEventListener('click', function(e) {
var id = e.target.id;
chrome.tabs.sendMessage(tab.id, {
action: 'fill_user_pass_with_specific_login',
id: id
});
close();
});
ul.appendChild(li);
}
});
});

View file

@ -0,0 +1,29 @@
<html>
<head>
<title>KeePassXC - Popup</title>
<link rel="stylesheet" href="popup.css" />
<link rel="stylesheet" href="../bootstrap-btn.css" />
<script type="text/javascript" src="../jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="popup_functions.js"></script>
</head>
<body>
<div id="settings" class="settings">
<button id="btn-options" class="b2c-btn b2c-btn-small b2c-btn-warning">Settings</button>
<button id="btn-choose-credential-fields" class="b2c-btn b2c-btn-small">Choose own credential fields for this page</button>
<div id="update-available">
You use an old version of KeePassXC.
<br />
<a target="_blank" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>.
</div>
</div>
<div>
<p>
chromeKeePassXC found more than one password field on this page. To enter your
logins, right-click on one of the password fields, and choose either the
"<code>Fill User + Pass</code>" or "<code>Fill Pass Only</code>" command.
</p>
</div>
</body>
</html>

View file

@ -0,0 +1,47 @@
<html>
<head>
<title>KeePassXC - Popup</title>
<link rel="stylesheet" href="popup.css" />
<link rel="stylesheet" href="../bootstrap-btn.css" />
<script type="text/javascript" src="../jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="popup_functions.js"></script>
<script type="text/javascript" src="popup_remember.js"></script>
<style type="text/css">
.credentials {display: none; border-top: 1px solid #333;}
.connected-database {display: none; font-size: 85%; color: #787878;}
.credentials .username-new {display: none;}
.credentials .username-exists {display: none;}
.small { font-weight: bold; }
.small .normal { font-weight: normal; }
</style>
</head>
<body>
<div class="buttons">
<p>
Username or password changed! Save it?
<br />
<span class="small information-url">Url: <span class="normal"></span></span>
<br />
<span class="small information-username">Username: <span class="normal"></span></span>
</p>
<p>
<button id="btn-new" class="b2c-btn b2c-btn-success">New</button>
<button id="btn-update" class="b2c-btn b2c-btn-warning">Update</button>
<button id="btn-dismiss" class="b2c-btn b2c-btn-danger">Dismiss</button>
</p>
</div>
<div class="connected-database">
<p>Credentials will be saved in connected database with identifier <em></em>.</p>
</div>
<div class="credentials">
<p class="username-new">The used username <strong></strong> is currently not saved!</p>
<p class="username-exists">The credentials with the used username <strong></strong> are marked bold.</p>
<p>
Please choose the credentials you want to update:
</p>
<ul id="list"></ul>
</div>
</body>
</html>

View file

@ -0,0 +1,124 @@
var _tab;
function _initialize(tab) {
_tab = tab;
// no credentials set or credentials already cleared
if(!_tab.credentials.username) {
_close();
return;
}
// no existing credentials to update --> disable update-button
if(_tab.credentials.list.length == 0) {
$("#btn-update").attr("disabled", true).removeClass("b2c-btn-warning");
}
var url = _tab.credentials.url;
url = (url.length > 50) ? url.substring(0, 50) + "..." : url;
$(".information-url:first span:first").text(url);
$(".information-username:first span:first").text(_tab.credentials.username);
$("#btn-new").click(function(e) {
chrome.extension.sendMessage({
action: 'add_credentials',
args: [_tab.credentials.username, _tab.credentials.password, _tab.credentials.url]
}, _verifyResult);
});
$("#btn-update").click(function(e) {
e.preventDefault();
// only one entry which could be updated
if(_tab.credentials.list.length == 1) {
chrome.extension.sendMessage({
action: 'update_credentials',
args: [_tab.credentials.list[0].Uuid, _tab.credentials.username, _tab.credentials.password, _tab.credentials.url]
}, _verifyResult);
}
else {
$(".credentials:first .username-new:first strong:first").text(_tab.credentials.username);
$(".credentials:first .username-exists:first strong:first").text(_tab.credentials.username);
if(_tab.credentials.usernameExists) {
$(".credentials:first .username-new:first").hide();
$(".credentials:first .username-exists:first").show();
}
else {
$(".credentials:first .username-new:first").show();
$(".credentials:first .username-exists:first").hide();
}
for(var i = 0; i < _tab.credentials.list.length; i++) {
var $a = $("<a>")
.attr("href", "#")
.text(_tab.credentials.list[i].Login + " (" + _tab.credentials.list[i].Name + ")")
.data("entryId", i)
.click(function(e) {
e.preventDefault();
chrome.extension.sendMessage({
action: 'update_credentials',
args: [_tab.credentials.list[$(this).data("entryId")].Uuid, _tab.credentials.username, _tab.credentials.password, _tab.credentials.url]
}, _verifyResult);
});
if(_tab.credentials.usernameExists && _tab.credentials.username == _tab.credentials.list[i].Login) {
$a.css("font-weight", "bold");
}
var $li = $("<li>").append($a);
$("ul#list").append($li);
}
$(".credentials").show();
}
});
$("#btn-dismiss").click(function(e) {
e.preventDefault();
_close();
});
}
function _connected_database(db) {
if(db.count > 1 && db.identifier) {
$(".connected-database:first em:first").text(db.identifier);
$(".connected-database:first").show();
}
else {
$(".connected-database:first").hide();
}
}
function _verifyResult(code) {
if(code == "success") {
_close();
}
}
function _close() {
chrome.extension.sendMessage({
action: 'remove_credentials_from_tab_information'
});
chrome.extension.sendMessage({
action: 'pop_stack'
});
close();
}
$(function() {
chrome.extension.sendMessage({
action: 'stack_add',
args: ["icon_remember_red_background_19x19.png", "popup_remember.html", 10, true, 0]
});
chrome.extension.sendMessage({
action: 'get_tab_information'
}, _initialize);
chrome.extension.sendMessage({
action: 'get_connected_database'
}, _connected_database);
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

View file

@ -0,0 +1,9 @@
{
"name": "com.varjolintu.chromekeepassxc",
"description": "KeepassXC integration with Chrome with Native Messaging support",
"path": "<KeePassXC path here>",
"type": "stdio",
"allowed_origins": [
"chrome-extension://ffojhfbafadajlgddbgadkbbchliloel/"
]
}