Reputation: 1735
When trying to encrypt and decrypt a file through a Cipher/Decipher stream I always encounter the following error: Unsupported state or unable to authenticate data
.
This is the code (comparison between the stream and the not-stream versions):
const key = Buffer.alloc(256 / 8);
const text = 'my secret message';
const encrypter = crypto.createCipheriv('aes-256-gcm', key, Buffer.alloc(16));
let encrypted = encrypter.update(text, 'utf8', 'hex');
encrypted += encrypter.final('hex');
const tag = encrypter.getAuthTag();
console.log('Encrypted!', encrypted);
const decrypter = crypto.createDecipheriv('aes-256-gcm', key, Buffer.alloc(16));
decrypter.setAuthTag(tag);
let decrypted = decrypter.update(encrypted, 'hex', 'utf8');
decrypted += decrypter.final('utf8');
console.log('Decrypted', decrypted);
Which perfectly prints out Decrypted my secret message
On the other hand...
const key = Buffer.alloc(256 / 8);
const text = 'my secret message';
const cipher = crypto.createCipheriv('aes-256-gcm', key, Buffer.alloc(16));
let encrypted = '';
cipher.on('data', (data: Buffer) =>
{
encrypted += data.toString('hex');
});
cipher.on('end', () =>
{
const tag = cipher.getAuthTag();
const decipher = crypto.createDecipheriv('aes-256-gcm', key, Buffer.alloc(16));
decipher.setAuthTag(tag);
let decrypted = '';
decipher.on('readable', () =>
{
const data = decipher.read() as Buffer;
if(data)
decrypted += data.toString('utf8');
});
decipher.on('end', () =>
{
console.log(decrypted);
});
fromString(encrypted).pipe(decipher);
});
I'm assuming the utility function fromString
picked from the examples of the from2 package
import * as from from 'from2';
function fromString(text: string)
{
return from((size, next) =>
{
if (text.length <= 0)
return next(null, null);
const chunk = text.slice(0, size);
text = text.slice(size);
next(null, chunk);
});
}
Any hint on why this is not working correctly? Thank you very much. I'm quite stuck on this.
Upvotes: 2
Views: 3099
Reputation: 1735
Actually the following code is working fine on files. I don't know the differences between this and the one I posted about...
const algorithm = 'aes-256-gcm';
const iv = Buffer.alloc(16);
const key = Buffer.alloc(256/8);
const cipher = crypto.createCipheriv(algorithm, key, iv);
const read_stream = fs.createReadStream(path.resolve(os.homedir(), 'Desktop', 'abstract.pdf'));
const encrypted_write_stream = fs.createWriteStream(path.resolve(os.homedir(), 'Desktop', 'abstract.enc.pdf'));
cipher.on('finish', () =>
{
const tag = cipher.getAuthTag();
console.log('File encrypted. Tag is', tag.toString('hex'));
const decipher = crypto.createDecipheriv(algorithm, key, iv);
decipher.setAuthTag(tag);
const encrypted_read_stream = fs.createReadStream(path.resolve(os.homedir(), 'Desktop', 'abstract.enc.pdf'));
const write_stream = fs.createWriteStream(path.resolve(os.homedir(), 'Desktop', 'abstract.decrypted.pdf'));
decipher.on('error', console.error);
decipher.on('finish', () =>
{
console.log('Decrypted successfully');
});
encrypted_read_stream.pipe(decipher).pipe(write_stream);
});
read_stream.pipe(cipher).pipe(encrypted_write_stream);
Upvotes: 3