Skip to content

Commit 3ac76b6

Browse files
committed
Fixing padding
1 parent 012a203 commit 3ac76b6

3 files changed

Lines changed: 53 additions & 27 deletions

File tree

nodejs/decrypt.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ var ece = require('./ece.js');
66

77
if (process.argv.length < 7) {
88
console.warn('Usage: ' + process.argv.slice(0, 2).join(' ') +
9-
' <receiver-private> <receiver-public> <sender-public> <salt> <message> [auth-secret]');
9+
' <receiver-private> <receiver-public> <sender-public> <salt> <message> [JSON args]');
1010
process.exit(2);
1111
}
1212

@@ -20,12 +20,21 @@ receiver.setPublicKey(base64.decode(process.argv[3]));
2020
receiver.setPrivateKey(base64.decode(process.argv[2]));
2121
ece.saveKey('keyid', receiver, "P-256");
2222

23-
var result = ece.decrypt(base64.decode(process.argv[6]), {
23+
var params = {
2424
keyid: 'keyid',
2525
dh: process.argv[4],
26-
salt: process.argv[5],
27-
authSecret: process.argv[7]
28-
});
26+
salt: process.argv[5]
27+
};
28+
29+
if (process.argv.length > 7) {
30+
var extra = JSON.parse(process.argv[7]);
31+
Object.keys(extra).forEach(function(k) {
32+
params[k] = extra[k];
33+
});
34+
}
35+
36+
console.log("Params: " + JSON.stringify(params, null, 2));
37+
var result = ece.decrypt(base64.decode(process.argv[6]), params);
2938

3039
console.log(base64.encode(result));
3140
console.log(result.toString('utf-8'));

nodejs/ece.js

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ function HKDF_expand(prk, info, l) {
3939
return output.slice(0, l);
4040
}
4141

42-
function HKDF(salt, ikm, info, l) {
43-
return HKDF_expand(HKDF_extract(salt, ikm), info, l);
42+
function HKDF(salt, ikm, info, len) {
43+
return HKDF_expand(HKDF_extract(salt, ikm), info, len);
4444
}
4545

4646
function info(base, context) {
@@ -98,38 +98,36 @@ function extractDH(keyid, dh, mode) {
9898
}
9999

100100
function extractSecretAndContext(params, mode) {
101-
var secret;
102-
var context = new Buffer(0);
101+
var result = { secret: null, context: new Buffer(0) };
103102
if (params.key) {
104-
secret = base64.decode(params.key);
105-
if (secret.length !== KEY_LENGTH) {
103+
result.secret = base64.decode(params.key);
104+
if (result.secret.length !== KEY_LENGTH) {
106105
throw new Error('An explicit key must be ' + KEY_LENGTH + ' bytes');
107106
}
108107
} else if (params.dh) { // receiver/decrypt
109-
var r = extractDH(params.keyid, params.dh, mode);
110-
secret = r.secret;
111-
context = r.context;
108+
result = extractDH(params.keyid, params.dh, mode);
112109
} else if (params.keyid) {
113-
secret = savedKeys[params.keyid];
110+
result.secret = savedKeys[params.keyid];
114111
}
115-
if (!secret) {
112+
if (!result.secret) {
116113
throw new Error('Unable to determine key');
117114
}
118115
if (params.authSecret) {
119-
secret = HKDF(base64.decode(params.authSecret), secret,
116+
result.secret = HKDF(base64.decode(params.authSecret), result.secret,
120117
info('auth', new Buffer(0)), SHA_256_LENGTH);
121118
}
122-
return { secret: secret, context: context };
119+
return result;
123120
}
124121

125122
function deriveKeyAndNonce(params, mode) {
126123
var salt = extractSalt(params.salt);
127124
var s = extractSecretAndContext(params, mode);
128125
var prk = HKDF_extract(salt, s.secret);
129-
return {
126+
var result = {
130127
key: HKDF_expand(prk, info('aesgcm128', s.context), KEY_LENGTH),
131128
nonce: HKDF_expand(prk, info('nonce', s.context), NONCE_LENGTH)
132129
};
130+
return result;
133131
}
134132

135133
function determineRecordSize(params) {
@@ -232,12 +230,22 @@ function encrypt(buffer, params) {
232230
var rs = determineRecordSize(params);
233231
var start = 0;
234232
var result = new Buffer(0);
233+
var pad = isNaN(parseInt(params.pad, 10)) ? 0 : parseInt(params.pad, 10);
235234

235+
// Note the <= here ensures that we write out a padding-only block at the end
236+
// of a buffer.
236237
for (var i = 0; start <= buffer.length; ++i) {
237-
var end = Math.min(start + rs - 1, buffer.length);
238-
var block = encryptRecord(key, i, buffer.slice(start, end));
238+
// Pad so that at least one data byte is in a block.
239+
var recordPad = Math.min(255, Math.min(rs - 2, pad));
240+
pad -= recordPad;
241+
242+
var end = Math.min(start + rs - 1 - recordPad, buffer.length);
243+
var block = encryptRecord(key, i, buffer.slice(start, end), recordPad);
239244
result = Buffer.concat([result, block]);
240-
start += rs - 1;
245+
start += rs - 1 - recordPad;
246+
}
247+
if (pad) {
248+
throw new Error('Unable to pad by requested amount, ' + pad + ' remaining');
241249
}
242250
return result;
243251
}

nodejs/encrypt.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ var ece = require('./ece.js');
66

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

@@ -16,12 +16,21 @@ ece.saveKey('keyid', sender, "P-256");
1616

1717
var salt = base64.encode(crypto.randomBytes(16));
1818

19-
var result = ece.encrypt(base64.decode(process.argv[3]), {
19+
var params = {
2020
keyid: 'keyid',
2121
dh: process.argv[2],
22-
salt: salt,
23-
authSecret: process.argv[4]
24-
});
22+
salt: salt
23+
};
24+
25+
if (process.argv.length > 4) {
26+
var extra = JSON.parse(process.argv[4]);
27+
Object.keys(extra).forEach(function(k) {
28+
params[k] = extra[k];
29+
});
30+
}
31+
32+
console.log("Params: " + JSON.stringify(params, null, 2));
33+
var result = ece.encrypt(base64.decode(process.argv[3]), params);
2534

2635
console.log("Salt: " + salt);
2736
console.log("Public Key: " + base64.encode(sender.getPublicKey()));

0 commit comments

Comments
 (0)