• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3if (!common.hasCrypto)
4  common.skip('missing crypto');
5
6const assert = require('assert');
7const crypto = require('crypto');
8const fs = require('fs');
9
10const fixtures = require('../common/fixtures');
11
12let cryptoType;
13let digest;
14
15// Test hashing
16const a1 = crypto.createHash('sha1').update('Test123').digest('hex');
17const a2 = crypto.createHash('sha256').update('Test123').digest('base64');
18const a3 = crypto.createHash('sha512').update('Test123').digest(); // buffer
19const a4 = crypto.createHash('sha1').update('Test123').digest('buffer');
20
21// stream interface
22let a5 = crypto.createHash('sha512');
23a5.end('Test123');
24a5 = a5.read();
25
26let a6 = crypto.createHash('sha512');
27a6.write('Te');
28a6.write('st');
29a6.write('123');
30a6.end();
31a6 = a6.read();
32
33let a7 = crypto.createHash('sha512');
34a7.end();
35a7 = a7.read();
36
37let a8 = crypto.createHash('sha512');
38a8.write('');
39a8.end();
40a8 = a8.read();
41
42if (!common.hasFipsCrypto) {
43  cryptoType = 'md5';
44  digest = 'latin1';
45  const a0 = crypto.createHash(cryptoType).update('Test123').digest(digest);
46  assert.strictEqual(
47    a0,
48    'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca\u00bd\u008c',
49    `${cryptoType} with ${digest} digest failed to evaluate to expected hash`
50  );
51}
52cryptoType = 'md5';
53digest = 'hex';
54assert.strictEqual(
55  a1,
56  '8308651804facb7b9af8ffc53a33a22d6a1c8ac2',
57  `${cryptoType} with ${digest} digest failed to evaluate to expected hash`);
58cryptoType = 'sha256';
59digest = 'base64';
60assert.strictEqual(
61  a2,
62  '2bX1jws4GYKTlxhloUB09Z66PoJZW+y+hq5R8dnx9l4=',
63  `${cryptoType} with ${digest} digest failed to evaluate to expected hash`);
64cryptoType = 'sha512';
65digest = 'latin1';
66assert.deepStrictEqual(
67  a3,
68  Buffer.from(
69    '\u00c1(4\u00f1\u0003\u001fd\u0097!O\'\u00d4C/&Qz\u00d4' +
70    '\u0094\u0015l\u00b8\u008dQ+\u00db\u001d\u00c4\u00b5}\u00b2' +
71    '\u00d6\u0092\u00a3\u00df\u00a2i\u00a1\u009b\n\n*\u000f' +
72    '\u00d7\u00d6\u00a2\u00a8\u0085\u00e3<\u0083\u009c\u0093' +
73    '\u00c2\u0006\u00da0\u00a1\u00879(G\u00ed\'',
74    'latin1'),
75  `${cryptoType} with ${digest} digest failed to evaluate to expected hash`);
76cryptoType = 'sha1';
77digest = 'hex';
78assert.deepStrictEqual(
79  a4,
80  Buffer.from('8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'hex'),
81  `${cryptoType} with ${digest} digest failed to evaluate to expected hash`
82);
83
84// Stream interface should produce the same result.
85assert.deepStrictEqual(a5, a3);
86assert.deepStrictEqual(a6, a3);
87assert.notStrictEqual(a7, undefined);
88assert.notStrictEqual(a8, undefined);
89
90// Test multiple updates to same hash
91const h1 = crypto.createHash('sha1').update('Test123').digest('hex');
92const h2 = crypto.createHash('sha1').update('Test').update('123').digest('hex');
93assert.strictEqual(h1, h2);
94
95// Test hashing for binary files
96const fn = fixtures.path('sample.png');
97const sha1Hash = crypto.createHash('sha1');
98const fileStream = fs.createReadStream(fn);
99fileStream.on('data', function(data) {
100  sha1Hash.update(data);
101});
102fileStream.on('close', common.mustCall(function() {
103  // Test SHA1 of sample.png
104  assert.strictEqual(sha1Hash.digest('hex'),
105                     '22723e553129a336ad96e10f6aecdf0f45e4149e');
106}));
107
108// Issue https://github.com/nodejs/node-v0.x-archive/issues/2227: unknown digest
109// method should throw an error.
110assert.throws(function() {
111  crypto.createHash('xyzzy');
112}, /Digest method not supported/);
113
114// Issue https://github.com/nodejs/node/issues/9819: throwing encoding used to
115// segfault.
116assert.throws(
117  () => crypto.createHash('sha256').digest({
118    toString: () => { throw new Error('boom'); },
119  }),
120  {
121    name: 'Error',
122    message: 'boom'
123  });
124
125// Issue https://github.com/nodejs/node/issues/25487: error message for invalid
126// arg type to update method should include all possible types
127assert.throws(
128  () => crypto.createHash('sha256').update(),
129  {
130    code: 'ERR_INVALID_ARG_TYPE',
131    name: 'TypeError',
132    message: 'The "data" argument must be of type string or an instance of ' +
133      'Buffer, TypedArray, or DataView. Received undefined'
134  });
135
136// Default UTF-8 encoding
137const hutf8 = crypto.createHash('sha512').update('УТФ-8 text').digest('hex');
138assert.strictEqual(
139  hutf8,
140  '4b21bbd1a68e690a730ddcb5a8bc94ead9879ffe82580767ad7ec6fa8ba2dea6' +
141        '43a821af66afa9a45b6a78c712fecf0e56dc7f43aef4bcfc8eb5b4d8dca6ea5b');
142
143assert.notStrictEqual(
144  hutf8,
145  crypto.createHash('sha512').update('УТФ-8 text', 'latin1').digest('hex'));
146
147const h3 = crypto.createHash('sha256');
148h3.digest();
149
150assert.throws(
151  () => h3.digest(),
152  {
153    code: 'ERR_CRYPTO_HASH_FINALIZED',
154    name: 'Error'
155  });
156
157assert.throws(
158  () => h3.update('foo'),
159  {
160    code: 'ERR_CRYPTO_HASH_FINALIZED',
161    name: 'Error'
162  });
163
164assert.strictEqual(
165  crypto.createHash('sha256').update('test').digest('ucs2'),
166  crypto.createHash('sha256').update('test').digest().toString('ucs2'));
167
168assert.throws(
169  () => crypto.createHash(),
170  {
171    code: 'ERR_INVALID_ARG_TYPE',
172    name: 'TypeError',
173    message: 'The "algorithm" argument must be of type string. ' +
174             'Received undefined'
175  }
176);
177
178{
179  const Hash = crypto.Hash;
180  const instance = crypto.Hash('sha256');
181  assert(instance instanceof Hash, 'Hash is expected to return a new instance' +
182                                   ' when called without `new`');
183}
184
185// Test XOF hash functions and the outputLength option.
186{
187  // Default outputLengths.
188  assert.strictEqual(crypto.createHash('shake128').digest('hex'),
189                     '7f9c2ba4e88f827d616045507605853e');
190  assert.strictEqual(crypto.createHash('shake128', null).digest('hex'),
191                     '7f9c2ba4e88f827d616045507605853e');
192  assert.strictEqual(crypto.createHash('shake256').digest('hex'),
193                     '46b9dd2b0ba88d13233b3feb743eeb24' +
194                     '3fcd52ea62b81b82b50c27646ed5762f');
195  assert.strictEqual(crypto.createHash('shake256', { outputLength: 0 })
196                           .copy()  // Default outputLength.
197                           .digest('hex'),
198                     '46b9dd2b0ba88d13233b3feb743eeb24' +
199                     '3fcd52ea62b81b82b50c27646ed5762f');
200
201  // Short outputLengths.
202  assert.strictEqual(crypto.createHash('shake128', { outputLength: 0 })
203                           .digest('hex'),
204                     '');
205  assert.strictEqual(crypto.createHash('shake128', { outputLength: 5 })
206                           .copy({ outputLength: 0 })
207                           .digest('hex'),
208                     '');
209  assert.strictEqual(crypto.createHash('shake128', { outputLength: 5 })
210                           .digest('hex'),
211                     '7f9c2ba4e8');
212  assert.strictEqual(crypto.createHash('shake128', { outputLength: 0 })
213                           .copy({ outputLength: 5 })
214                           .digest('hex'),
215                     '7f9c2ba4e8');
216  assert.strictEqual(crypto.createHash('shake128', { outputLength: 15 })
217                           .digest('hex'),
218                     '7f9c2ba4e88f827d61604550760585');
219  assert.strictEqual(crypto.createHash('shake256', { outputLength: 16 })
220                           .digest('hex'),
221                     '46b9dd2b0ba88d13233b3feb743eeb24');
222
223  // Large outputLengths.
224  assert.strictEqual(crypto.createHash('shake128', { outputLength: 128 })
225                           .digest('hex'),
226                     '7f9c2ba4e88f827d616045507605853e' +
227                     'd73b8093f6efbc88eb1a6eacfa66ef26' +
228                     '3cb1eea988004b93103cfb0aeefd2a68' +
229                     '6e01fa4a58e8a3639ca8a1e3f9ae57e2' +
230                     '35b8cc873c23dc62b8d260169afa2f75' +
231                     'ab916a58d974918835d25e6a435085b2' +
232                     'badfd6dfaac359a5efbb7bcc4b59d538' +
233                     'df9a04302e10c8bc1cbf1a0b3a5120ea');
234  const superLongHash = crypto.createHash('shake256', {
235    outputLength: 1024 * 1024
236  }).update('The message is shorter than the hash!')
237    .digest('hex');
238  assert.strictEqual(superLongHash.length, 2 * 1024 * 1024);
239  assert.ok(superLongHash.endsWith('193414035ddba77bf7bba97981e656ec'));
240  assert.ok(superLongHash.startsWith('a2a28dbc49cfd6e5d6ceea3d03e77748'));
241
242  // Non-XOF hash functions should accept valid outputLength options as well.
243  assert.strictEqual(crypto.createHash('sha224', { outputLength: 28 })
244                           .digest('hex'),
245                     'd14a028c2a3a2bc9476102bb288234c4' +
246                     '15a2b01f828ea62ac5b3e42f');
247
248  // Passing invalid sizes should throw during creation.
249  assert.throws(() => {
250    crypto.createHash('sha256', { outputLength: 28 });
251  }, {
252    code: 'ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH'
253  });
254
255  for (const outputLength of [null, {}, 'foo', false]) {
256    assert.throws(() => crypto.createHash('sha256', { outputLength }),
257                  { code: 'ERR_INVALID_ARG_TYPE' });
258  }
259
260  for (const outputLength of [-1, .5, Infinity, 2 ** 90]) {
261    assert.throws(() => crypto.createHash('sha256', { outputLength }),
262                  { code: 'ERR_OUT_OF_RANGE' });
263  }
264}
265
266{
267  const h = crypto.createHash('sha512');
268  h.digest();
269  assert.throws(() => h.copy(), { code: 'ERR_CRYPTO_HASH_FINALIZED' });
270  assert.throws(() => h.digest(), { code: 'ERR_CRYPTO_HASH_FINALIZED' });
271}
272
273{
274  const a = crypto.createHash('sha512').update('abc');
275  const b = a.copy();
276  const c = b.copy().update('def');
277  const d = crypto.createHash('sha512').update('abcdef');
278  assert.strictEqual(a.digest('hex'), b.digest('hex'));
279  assert.strictEqual(c.digest('hex'), d.digest('hex'));
280}
281