Skip to content

Commit 0f0b40c

Browse files
committed
Finalize implementation
1 parent 76e10ff commit 0f0b40c

4 files changed

Lines changed: 76 additions & 72 deletions

File tree

nodejs/decrypt.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,25 @@ var base64 = require('urlsafe-base64');
44
var crypto = require('crypto');
55
var ece = require('./ece.js');
66

7-
if (process.argv.length < 5) {
7+
if (process.argv.length < 4) {
88
console.warn('Usage: ' + process.argv.slice(0, 2).join(' ') +
9-
' <key> <salt> <message> [JSON args]');
9+
' <key> <message> [JSON args]');
1010
process.exit(2);
1111
}
1212

1313
var params = {
14-
key: process.argv[2],
15-
salt: process.argv[3]
14+
key: process.argv[2]
1615
};
1716

18-
if (process.argv.length > 5) {
19-
var extra = JSON.parse(process.argv[5]);
17+
if (process.argv.length > 4) {
18+
var extra = JSON.parse(process.argv[4]);
2019
Object.keys(extra).forEach(function(k) {
2120
params[k] = extra[k];
2221
});
2322
}
2423

2524
console.log("Params: " + JSON.stringify(params, null, 2));
26-
var result = ece.decrypt(base64.decode(process.argv[4]), params);
25+
var result = ece.decrypt(base64.decode(process.argv[3]), params);
2726

2827
console.log(base64.encode(result));
2928
console.log(result.toString('utf-8'));

nodejs/ece.js

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ var keylog;
1818
if (process.env.ECE_KEYLOG === '1') {
1919
keylog = function(m, k) {
2020
console.warn(m + ' [' + k.length + ']: ' + base64.encode(k));
21+
return k;
2122
};
2223
} else {
23-
keylog = function() {};
24+
keylog = function(m, k) { return k; };
2425
}
2526

2627
function HMAC_hash(key, input) {
@@ -110,7 +111,6 @@ function extractSecretAndContext(header, mode) {
110111
result.secret = savedKeys[header.keyid];
111112
}
112113
if (!result.secret) {
113-
console.warn(header);
114114
throw new Error('Unable to determine key');
115115
}
116116
keylog('secret', result.secret);
@@ -176,22 +176,23 @@ function extractSalt(salt) {
176176
}
177177

178178
/* Used when decrypting aes128gcm to populate the header values. */
179-
function readHeader(params, buffer) {
179+
function readHeader(buffer, params) {
180180
var idsz = buffer.readUIntBE(20, 1);
181+
keylog('header', buffer.slice(0, 21 + idsz));
181182
return {
182183
type: 'aes128gcm',
183184
salt: buffer.slice(0, KEY_LENGTH),
184185
rs: buffer.readUIntBE(KEY_LENGTH, 4),
185186
keyid: buffer.slice(21, 21 + idsz).toString('utf-8'),
186187
key: params.key ? base64.decode(params.key) : undefined,
187188
dh: params.dh ? base64.decode(params.dh) : undefined,
188-
authSecret: params.authSecret ? base64.decode(params.authSecret) : undefined
189+
authSecret: params.authSecret ? base64.decode(params.authSecret) : undefined,
190+
headerLength: 21 + idsz
189191
};
190192
}
191193

192194
/* Used when decrypting to populate the header values for aesgcm[128]. */
193195
function parseParams(params) {
194-
console.warn(params);
195196
var type = (params.padSize === 1) ? 'aesgcm128' : 'aesgcm';
196197
return {
197198
type: type,
@@ -225,10 +226,6 @@ function decryptRecord(key, counter, buffer, header) {
225226
var padSize = PAD_SIZE[header.type];
226227
var pad = data.readUIntBE(0, padSize);
227228
if (pad + padSize > data.length) {
228-
console.warn(header);
229-
console.warn(pad);
230-
console.warn(padSize);
231-
console.warn(data.length);
232229
throw new Error('padding exceeds block size');
233230
}
234231
var padCheck = new Buffer(pad);
@@ -258,7 +255,7 @@ function decrypt(buffer, params) {
258255
header = readHeader(buffer, params);
259256
}
260257
var key = deriveKeyAndNonce(header, MODE_DECRYPT);
261-
buffer = buffer.slice(header.len);
258+
buffer = buffer.slice(header.headerLength || 0);
262259
var start = 0;
263260
var result = new Buffer(0);
264261

@@ -294,9 +291,7 @@ function encryptRecord(key, counter, buffer, pad, padSize) {
294291
if (tag.length !== TAG_LENGTH) {
295292
throw new Error('invalid tag generated');
296293
}
297-
var encrypted = Buffer.concat([epadding, ebuffer, tag]);
298-
keylog('encrypted', encrypted);
299-
return encrypted;
294+
return keylog('encrypted', Buffer.concat([epadding, ebuffer, tag]));
300295
}
301296

302297
function encodeHeader(header) {
@@ -307,7 +302,7 @@ function encodeHeader(header) {
307302
}
308303
ints.writeUIntBE(header.rs, 0, 4);
309304
ints.writeUIntBE(keyid.length, 4, 1);
310-
return Buffer.concat([header.salt, ints, keyid]);
305+
return keylog('header', Buffer.concat([header.salt, ints, keyid]));
311306
}
312307

313308
/**

nodejs/encrypt.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,24 @@ var base64 = require('urlsafe-base64');
44
var crypto = require('crypto');
55
var ece = require('./ece.js');
66

7-
if (process.argv.length < 5) {
7+
if (process.argv.length < 4) {
88
console.warn('Usage: ' + process.argv.slice(0, 2).join(' ') +
9-
' <key> <salt> <message> [JSON args]');
9+
' <key> <message> [JSON args]');
1010
process.exit(2);
1111
}
1212

1313
var params = {
14-
key: process.argv[2],
15-
salt: process.argv[3]
14+
key: process.argv[2]
1615
};
1716

18-
if (process.argv.length > 5) {
19-
var extra = JSON.parse(process.argv[5]);
17+
if (process.argv.length > 4) {
18+
var extra = JSON.parse(process.argv[4]);
2019
Object.keys(extra).forEach(function(k) {
2120
params[k] = extra[k];
2221
});
2322
}
2423

2524
console.log("Params: " + JSON.stringify(params, null, 2));
26-
var result = ece.encrypt(base64.decode(process.argv[4]), params);
25+
var result = ece.encrypt(base64.decode(process.argv[3]), params);
2726

2827
console.log("Encrypted Message: " + base64.encode(result));

nodejs/test.js

Lines changed: 55 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ var ece = require('./ece.js');
55
var base64 = require('urlsafe-base64');
66
var assert = require('assert');
77

8-
// Usage: node <this> <iterations> <maxsize>
8+
// Usage: node <this> <iterations> <maxsize|plaintext>
99
var count = parseInt(process.argv[2], 10) || 20;
1010
var maxLen = 100;
11+
var minLen = 3;
1112
var plaintext = null;
1213
if (process.argv.length >= 4) {
1314
if (!isNaN(parseInt(process.argv[3], 10))) {
@@ -41,10 +42,14 @@ function validate() {
4142
});
4243
}
4344

44-
function encryptDecrypt(length, encryptParams, decryptParams) {
45-
decryptParams = decryptParams || encryptParams;
46-
logbuf('Salt', encryptParams.salt);
47-
var input = plaintext || crypto.randomBytes(Math.min(length, maxLen));
45+
function encryptDecrypt(length, encryptParams, decryptParams, oldVersion) {
46+
if (oldVersion) {
47+
decryptParams.salt = base64.encode(crypto.randomBytes(16));
48+
encryptParams.salt = decryptParams.salt;
49+
logbuf('Salt', encryptParams.salt);
50+
}
51+
var input = plaintext ||
52+
crypto.randomBytes(Math.max(minLen, Math.min(length, maxLen)));
4853
// var input = new Buffer('I am the walrus');
4954
logbuf('Input', input);
5055
var encrypted = ece.encrypt(input, encryptParams);
@@ -55,52 +60,57 @@ function encryptDecrypt(length, encryptParams, decryptParams) {
5560
log('----- OK');
5661
}
5762

58-
function useExplicitKey() {
59-
var length = crypto.randomBytes(4);
63+
function useExplicitKey(oldVersion) {
64+
var length = crypto.randomBytes(4).readUInt16BE(0);
6065
var params = {
6166
key: base64.encode(crypto.randomBytes(16)),
62-
salt: base64.encode(crypto.randomBytes(16)),
63-
rs: length.readUInt16BE(0) + 1
67+
rs: length + minLen
6468
};
6569
logbuf('Key', params.key);
66-
encryptDecrypt(length.readUInt16BE(2), params);
70+
encryptDecrypt(length, params, params, oldVersion);
6771
}
6872

69-
function authenticationSecret() {
70-
var length = crypto.randomBytes(4);
73+
function authenticationSecret(oldVersion) {
74+
var length = crypto.randomBytes(4).readUInt16BE(0);
7175
var params = {
7276
key: base64.encode(crypto.randomBytes(16)),
73-
salt: base64.encode(crypto.randomBytes(16)),
74-
rs: length.readUInt16BE(0) + 1,
77+
rs: length + minLen,
7578
authSecret: base64.encode(crypto.randomBytes(16))
7679
};
7780
logbuf('Key', params.key);
7881
logbuf('Context', params.authSecret);
79-
encryptDecrypt(length.readUInt16BE(2), params);
82+
encryptDecrypt(length, params, params, oldVersion);
8083
}
8184

82-
function exactlyOneRecord() {
83-
var length = Math.min(crypto.randomBytes(2).readUInt16BE(0), maxLen);
85+
function exactlyOneRecord(oldVersion) {
86+
var length = Math.min(crypto.randomBytes(2).readUInt16BE(0) + 1, maxLen);
8487
var params = {
8588
key: base64.encode(crypto.randomBytes(16)),
86-
salt: base64.encode(crypto.randomBytes(16)),
87-
rs: length + 1
89+
rs: length + 2 // add exactly the padding
8890
};
89-
encryptDecrypt(length, params);
91+
encryptDecrypt(length, params, params, oldVersion);
9092
}
9193

92-
function detectTruncation() {
93-
var length = Math.min(crypto.randomBytes(2).readUInt16BE(0), maxLen);
94+
function detectTruncation(oldVersion) {
95+
var length = Math.min(crypto.randomBytes(2).readUInt16BE(0) + minLen, maxLen);
9496
var params = {
9597
key: base64.encode(crypto.randomBytes(16)),
96-
salt: base64.encode(crypto.randomBytes(16)),
97-
rs: length + 1
98+
rs: length // so we get two records
9899
};
99-
logbuf('Salt', params.salt);
100+
var headerLen;
101+
if (oldVersion) {
102+
params.salt = base64.encode(crypto.randomBytes(16));
103+
logbuf('Salt', params.salt);
104+
headerLen = 0;
105+
} else {
106+
headerLen = 21; // no keyid
107+
}
100108
var input = crypto.randomBytes(Math.min(length, maxLen));
101109
logbuf('Input', input);
102110
var encrypted = ece.encrypt(input, params);
103-
encrypted = encrypted.slice(0, length + 1 + 16);
111+
var chunkLen = headerLen + params.rs + 16;
112+
assert.ok(chunkLen < encrypted.length);
113+
encrypted = encrypted.slice(0, chunkLen);
104114
logbuf('Encrypted', encrypted);
105115
var ok = false;
106116
try {
@@ -114,20 +124,19 @@ function detectTruncation() {
114124
}
115125
}
116126

117-
function useKeyId() {
118-
var length = crypto.randomBytes(4);
127+
function useKeyId(oldVersion) {
128+
var length = crypto.randomBytes(4).readUInt16BE(0);
119129
var keyid = base64.encode(crypto.randomBytes(16));
120130
var key = crypto.randomBytes(16);
121131
ece.saveKey(keyid, key);
122132
var params = {
123133
keyid: keyid,
124-
salt: base64.encode(crypto.randomBytes(16)),
125-
rs: length.readUInt16BE(0) + 1
134+
rs: length + minLen
126135
};
127-
encryptDecrypt(length.readUInt16BE(2), params);
136+
encryptDecrypt(length, params, params, oldVersion);
128137
}
129138

130-
function useDH() {
139+
function useDH(oldVersion) {
131140
// the static key is used by the receiver
132141
var staticKey = crypto.createECDH('prime256v1');
133142
staticKey.generateKeys();
@@ -148,34 +157,36 @@ function useDH() {
148157
logbuf('Sender private', ephemeralKey.getPrivateKey());
149158
logbuf('Sender public', ephemeralKey.getPublicKey());
150159

151-
var length = crypto.randomBytes(4);
160+
var length = crypto.randomBytes(4).readUInt16BE(0);
152161
var encryptParams = {
153162
keyid: ephemeralKeyId,
154163
dh: base64.encode(staticKey.getPublicKey()),
155164
salt: base64.encode(crypto.randomBytes(16)),
156-
rs: length.readUInt16BE(0) + 1
165+
rs: length + minLen
157166
};
158167
var decryptParams = {
159168
keyid: staticKeyId,
160169
dh: base64.encode(ephemeralKey.getPublicKey()),
161170
salt: encryptParams.salt,
162171
rs: encryptParams.rs
163172
};
164-
encryptDecrypt(length.readUInt16BE(2), encryptParams, decryptParams);
173+
encryptDecrypt(length, encryptParams, decryptParams, oldVersion);
165174
}
166175

167176
validate();
168177
var i;
169178
for (i = 0; i < count; ++i) {
170-
[ useExplicitKey,
171-
authenticationSecret,
172-
exactlyOneRecord,
173-
detectTruncation,
174-
useKeyId,
175-
useDH,
176-
].forEach(function(f) {
177-
log('Test: ' + f.name);
178-
f();
179+
[ true, false ].forEach(function(oldVersion) {
180+
[ useExplicitKey,
181+
authenticationSecret,
182+
exactlyOneRecord,
183+
detectTruncation,
184+
useKeyId,
185+
useDH,
186+
].forEach(function(f) {
187+
log((oldVersion ? 'aesgcm' : 'aes128gcm') + ' Test: ' + f.name);
188+
f(oldVersion);
189+
});
179190
});
180191
}
181192

0 commit comments

Comments
 (0)