node-archiver icon indicating copy to clipboard operation
node-archiver copied to clipboard

Creating a crypto hash from the buffer gives new hash everytime

Open akshita31 opened this issue 6 years ago • 2 comments

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.

akshita31 avatar Dec 19 '18 02:12 akshita31

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.

rk-yen avatar Apr 23 '19 04:04 rk-yen

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)
}

Hoofoo-WHU avatar Nov 27 '20 04:11 Hoofoo-WHU