I am writing some code that encrypts a communication channel between two users. The steps are as follows
mongoDb
cipher
and encrypt the incoming datamongoDb
and encrypt the incoming dataThe code uses crypto
module which is one of the few synchronous libs in core nodejs
Create a cipher and return it as a promise
cipher.createCipher = Promise.method((pw) => {
if (!pw) {
throw new Error('Passphrase must be provided');
}
return crypto.createCipher('aes192', pw);
});
Encrypt data using Promise.method()
cipher.encryptTextAsPromise = Promise.method((cipher, plainText) => {
if (!( typeof plainText === 'string')) {
throw new Error("2nd param must be plain text");
let cipherText = '';
cipher.on('readable', () => {
var data = cipher.read();
if (data)
cipherText += data.toString('hex');
});
cipher.on('end', () => {
return cipherText;
});
cipher.write(plainText);
cipher.end();
}
});
Encrypt data via callback functions.
cipher.encryptText = (cipher, plainText, callback) => {
if (!( typeof plainText === 'string')) {
throw new Error("2nd param must be plain text");
}
try {
let cipherText = '';
cipher.on('readable', () => {
var data = cipher.read();
if (data)
cipherText += data.toString('hex');
});
cipher.on('end', () => {
callback(null, cipherText);
});
cipher.write(plainText);
cipher.end();
} catch (e) {
callback(e, null);
}
}
I am unable to chain these two together. What I have is a horrible anti-pattern that is worse than getting stuck in callback hell
cipher.createCipher('secretWord')
.then((data) => {
cipher.encryptTextasPromise(data, 'hello world')
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err);
})
})
.catch((err) => {
console.log(err);
})
mongoDbSearch(username)
.then((data) => {
if (data) {
// Cipher exists, retrieve and encrypt
}else {
// Create new cipher and save
someMongoSave()
.then((data) => {
// Cipher exists now, retrieve and encrypt
})
}
})
.catch((mongoErr) => {
console.log(mongoErr);
})
The code is a bit incomplete as I am still trying to grasp this concept. Furthermore the my attempt to chain createCipher
and encryptTextAsPromise
is returning undefined
in the data. I have tried writing these as normal callback and then using Promise.promisfyAll()
as well, which just feels like another anti-pattern.
Promise.method
would appear to make sense for createCipher
, but probably not for encryptTextAsPromise
.
Here's a version that should point you the right direction, distilling various of T.J. Crowder's, Jaromanda X's, and undefined's comments on the question; see code comments for more:
// For this one, `Promise.method` still makes sense (although doing it with
// your own promise is also perfectly reasonable)
cipher.createCipher = Promise.method(pw => {
if (!pw) {
throw new Error('Passphrase must be provided');
}
return crypto.createCipher('aes192', pw);
});
// For this one, your own promise makes sense
cipher.encryptTextAsPromise = (cipher, plainText) => {
return new Promise(resolve => {
if (!( typeof plainText === 'string')) {
// It's fine to throw here (it will get converted into a rejection),
// or add `reject` to the arguments list above and call
// that and return instead:
// reject(new Error("2nd param must be plain text"));
// return;
throw new Error("2nd param must be plain text");
}
let cipherText = '';
cipher.on('readable', () => {
var data = cipher.read();
if (data)
cipherText += data.toString('hex');
});
cipher.on('end', () => {
resolve(cipherText);
});
cipher.write(plainText);
cipher.end();
});
};
// Usage:
cipher.createCipher('secretWord')
.then(data => cipher.encryptTextAsPromise(data, 'hello world'))
.then(data => console.log(data)) // See 1 below
.catch(err => console.log(err));
mongoDbSearch(username)
.then(data => data || someMongoSave(data)) // You pass `data` to `someMongoSave`, presumably?
.then(data => {
// Cipher exists, retrieve and encrypt
})
.catch(mongoErr => {
console.log(mongoErr);
});
Separately, re
if (!( typeof plainText === 'string')) {
there's a !==
operator in JavaScript. Jus' sayin'. ;-D