Simplify MDC verification

This commit is contained in:
Daniel Huigens 2018-12-21 11:08:10 -05:00
parent 3f1734ae7a
commit 31931c9b0d
2 changed files with 5 additions and 48 deletions

View File

@ -36,45 +36,6 @@ const nodeCrypto = util.getNodeCrypto();
const Buffer = util.getNodeBuffer();
export default {
/**
* Decrypts the prefixed data for the Modification Detection Code (MDC) computation
* @param {String} cipherfn.encrypt Cipher function to use,
* @see module:crypto/cipher.
* @param {Uint8Array} key Uint8Array representation of key to be used to check the mdc
* This will be passed to the cipherfn
* @param {Uint8Array} ciphertext The encrypted data
* @returns {Uint8Array} plaintext Data of D(ciphertext) with blocksize length +2
*/
mdc: function(cipherfn, key, ciphertext) {
cipherfn = new cipher[cipherfn](key);
const block_size = cipherfn.blockSize;
let iblock = new Uint8Array(block_size);
let ablock = new Uint8Array(block_size);
let i;
// initialisation vector
for (i = 0; i < block_size; i++) {
iblock[i] = 0;
}
iblock = cipherfn.encrypt(iblock);
for (i = 0; i < block_size; i++) {
ablock[i] = ciphertext[i];
iblock[i] ^= ablock[i];
}
ablock = cipherfn.encrypt(ablock);
const result = new Uint8Array(iblock.length + 2);
result.set(iblock);
result[iblock.length] = ablock[0] ^ ciphertext[block_size];
result[iblock.length + 1] = ablock[1] ^ ciphertext[block_size + 1];
return result;
},
encrypt: function(algo, key, plaintext, iv) {
if (algo.substr(0, 3) === 'aes') {
return aesEncrypt(algo, key, plaintext, iv);

View File

@ -111,19 +111,14 @@ SymEncryptedIntegrityProtected.prototype.encrypt = async function (sessionKeyAlg
SymEncryptedIntegrityProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key, streaming) {
if (!streaming) this.encrypted = await stream.readToEnd(this.encrypted);
const encrypted = stream.clone(this.encrypted);
const encryptedClone = stream.passiveClone(encrypted);
let decrypted = await crypto.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(crypto.cipher[sessionKeyAlgorithm].blockSize));
decrypted = stream.slice(decrypted, crypto.cipher[sessionKeyAlgorithm].blockSize + 2); // Remove random prefix
const decrypted = await crypto.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(crypto.cipher[sessionKeyAlgorithm].blockSize));
// there must be a modification detection code packet as the
// last packet and everything gets hashed except the hash itself
const encryptedPrefix = await stream.readToEnd(stream.slice(encryptedClone, 0, crypto.cipher[sessionKeyAlgorithm].blockSize + 2));
const prefix = crypto.cfb.mdc(sessionKeyAlgorithm, key, encryptedPrefix);
const realHash = stream.slice(stream.passiveClone(decrypted), -20);
const bytes = stream.slice(decrypted, 0, -20);
const tohash = util.concat([prefix, stream.passiveClone(bytes)]);
const tohash = stream.slice(decrypted, 0, -20);
const verifyHash = Promise.all([
stream.readToEnd(await crypto.hash.sha1(tohash)),
stream.readToEnd(await crypto.hash.sha1(stream.passiveClone(tohash))),
stream.readToEnd(realHash)
]).then(([hash, mdc]) => {
if (!util.equalsUint8Array(hash, mdc)) {
@ -131,7 +126,8 @@ SymEncryptedIntegrityProtected.prototype.decrypt = async function (sessionKeyAlg
}
return new Uint8Array();
});
let packetbytes = stream.slice(bytes, 0, -2);
const bytes = stream.slice(tohash, crypto.cipher[sessionKeyAlgorithm].blockSize + 2); // Remove random prefix
let packetbytes = stream.slice(bytes, 0, -2); // Remove MDC packet
packetbytes = stream.concat([packetbytes, stream.fromAsync(() => verifyHash)]);
if (!util.isStream(encrypted) || !config.allow_unauthenticated_stream) {
packetbytes = await stream.readToEnd(packetbytes);