node-archiver
node-archiver copied to clipboard
Creating a crypto hash from the buffer gives new hash everytime
I am trying to create a sample buffer that contains a zip using the archiver. Here is my code that creates uses the archive
public async createBuffer(...filesToAdd: TestFile[]): Promise<Buffer> {
let buffers: any[] = [];
let finalBuffer = await new Promise<Buffer>((resolve, reject) => {
let archive = archiver('zip');
archive.on('warning', function (err: any) {
if (err.code === 'ENOENT') {
console.log(err);
} else {
// throw error
reject(err);
}
});
archive.on('data', data => buffers.push(data));
archive.on('error', reject);
archive.on('end', () => resolve(Buffer.concat(buffers)));
filesToAdd.forEach(elem => archive.append(elem.content, { name: elem.path }));
archive.finalize();
});
return finalBuffer;
}
I was trying to write a test for a function that takes in a buffer and checks the "sha256" checksum against a known integrity value. Here is the function:
export function isValidDownload(buffer: Buffer, integrity: string): boolean {
let hash = crypto.createHash('sha256');
if (integrity && integrity.length > 0) {
hash.update(buffer);
let value = hash.digest('hex');
if (value.toUpperCase() == integrity.toUpperCase()) {
return true;
}
else {
return false;
}
}
// no integrity has been specified
return true;
}
And my test goes like this
test('Returns false for non-matching integrity', async () => {
let testZip = await createBuffer(createTestFile("Foo", "foo.txt"));
let result = await isValidDownload(testZip, "a75801f49d0e7bf2178a4c6fe69663ee374812447a8a0f080fa22647d780279b", new EventStream());
expect(result).to.be.true;
});
I am unable to write this test with a constant hash value as I observed that the hash value keeps changing whenever I run the test. Is there something I am doing wrong while creating the buffer that leads to this behavior. Any guidance would be greatly appreciated.
By default append
will use current time while creating zip entries. So, the created zip file will not be 'bit exact'. You can pass in a desired time to make the zip, and hence the checksum, unique/repeatable.
export async function zip(basePath: string, ...filter: string[]) {
const buffer: Buffer[] = []
const files = await fg(filter.length > 0 ? filter : '**', { cwd: basePath, onlyFiles: true, unique: true, absolute: true })
await files
.sort() // The order that the files are added to the archive may be different
.reduce(
(stream, file) =>
stream.append(fs.createReadStream(file), {
name: path.relative(basePath, file),
date: new Date(0), // The timestamp that the files are added to the archive may be different
}),
archiver('zip').on('data', (data) => buffer.push(data))
)
.finalize()
return Buffer.concat(buffer)
}