Search code examples
node.jsnestjscryptojs

How to use Node crypto in NestJS to digest binary


I am trying to port a pre-existing NodeJS project to NestJS.

Rather than using require I am importing the library like so:

import * as crypto from 'crypto';

Most of the code works. However I am having issues with the following line:

const hash_digest   = hash.update(nonce + message).digest('binary');

The issue is "binary" does not appear to be a valid type. And indeed when I click through into the source located at node_modules/@types/node/crypto.d.ts, I see BinaryToTextEncoding = 'base64' | 'hex'; are the only valid types for the digest method.

However, when I read the documentation it states:

hash.digest([encoding])
Calculates the digest of all of the passed data to be hashed. The encoding can be 'hex', 'binary' or 'base64'.

So is this a difference between the "node" and "nestJS" versions of this library or what am I missing?

And if this is not a valid approach, how else to solve this problem? As it stands now, my nonce gets rejected as invalid if I try any of the following:

const hash_digest   = hash.update(nonce + message, 'binary').digest();
const hash_digest   = hash.update(nonce + message).digest();
const hash_digest   = hash.update(nonce + message, 'binary');
hash_digest   = hash.update(nonce + message).digest(<BinaryToTextEncoding>'binary');

Solution

  • This isn't anything to do with NestJS, a framework on top of NodeJS, and all to do with Typescript, a superset of JavaScript which adds type safety to the development environment. The typescript types for the crypto package for the BinaryToTextEncoding says that you have the ability to pass in a union of strings, meaning one of the following

    type BinaryToTextEncoding = 'base64' | 'hex';
    type CharacterEncoding = 'utf8' | 'utf-8' | 'utf16le' | 'latin1';
    type LegacyCharacterEncoding = 'ascii' | 'binary' | 'ucs2' | 'ucs-2';
    
    type Encoding = BinaryToTextEncoding | CharacterEncoding | LegacyCharacterEncoding;
    
    // Or in simple terms
    type Encoding = 'base64' | 'hex' | 'utf8' | 'utf-8' | 'utf16le' | 'latin1' | 'ascii' | 'binary' | 'ucs2' | 'ucs-2';
    

    This is all for Node14, so make sure the version matches that, but it should accept binary as a valid encoding type. What you should probably be doing is using the update(message, encoding) format instead of update(message).digest(encoding) method

    Docs for the NodeJS crypto package's update method

    Docs for the update method's encoding type

    Overall, it looks like a typescript discrepancy. You could probably make an issue and a PR to the DefinitelyTyped repository