224

I love cupcakes(キーで署名されたabcdeg)のハッシュを作成したい

Node.js Cryptoを使用してそのハッシュを作成するにはどうすればよいですか?

4

4 に答える 4

399

暗号のドキュメント:http://nodejs.org/api/crypto.html

const crypto = require('crypto')

const text = 'I love cupcakes'
const key = 'abcdeg'

crypto.createHmac('sha1', key)
  .update(text)
  .digest('hex')
于 2011-09-20T04:38:21.757 に答える
101

update()数年前、とはレガシーメソッドであると言われdigest()、新しいストリーミングAPIアプローチが導入されました。現在、ドキュメントには、どちらの方法も使用できると記載されています。例えば:

var crypto    = require('crypto');
var text      = 'I love cupcakes';
var secret    = 'abcdeg'; //make this your secret!!
var algorithm = 'sha1';   //consider using sha256
var hash, hmac;

// Method 1 - Writing to a stream
hmac = crypto.createHmac(algorithm, secret);    
hmac.write(text); // write in to the stream
hmac.end();       // can't read from the stream until you call end()
hash = hmac.read().toString('hex');    // read out hmac digest
console.log("Method 1: ", hash);

// Method 2 - Using update and digest:
hmac = crypto.createHmac(algorithm, secret);
hmac.update(text);
hash = hmac.digest('hex');
console.log("Method 2: ", hash);

ノードv6.2.2およびv7.7.2でテスト済み

https://nodejs.org/api/crypto.html#crypto_class_hmacを参照してください。ストリーミングアプローチを使用するためのより多くの例を示します。

于 2013-09-15T14:59:44.697 に答える
22

hash = hmac.read();ストリームがファイナライズされる前に発生するため、Gwerderのソリューションは機能しません。したがって、AngraXの問題。また、hmac.writeこの例ではステートメントは不要です。

代わりにこれを行います:

var crypto    = require('crypto');
var hmac;
var algorithm = 'sha1';
var key       = 'abcdeg';
var text      = 'I love cupcakes';
var hash;

hmac = crypto.createHmac(algorithm, key);

// readout format:
hmac.setEncoding('hex');
//or also commonly: hmac.setEncoding('base64');

// callback is attached as listener to stream's finish event:
hmac.end(text, function () {
    hash = hmac.read();
    //...do something with the hash...
});

より正式には、必要に応じて、行

hmac.end(text, function () {

書くことができます

hmac.end(text, 'utf8', function () {

この例では、テキストはutf文字列であるため

于 2014-10-09T15:04:39.033 に答える
0

ハッシュアルゴリズムに署名して検証するためのすべてのサンプルコードにもかかわらず、私はまだ実験を行い、それを機能させるためにかなりの調整を行いました。これが私の作業サンプルで、すべてのエッジケースがカバーされていると思います。

これはURLセーフであり(つまり、エンコードする必要はありません)、有効期限がかかり、予期せず例外をスローすることはありません。Day.jsには依存関係がありますが、それを別の日付ライブラリに置き換えるか、独自の日付比較を行うことができます。

TypeScriptで書かれた:

// signature.ts
import * as crypto from 'crypto';
import * as dayjs from 'dayjs';

const key = 'some-random-key-1234567890';

const replaceAll = (
  str: string,
  searchValue: string,
  replaceValue: string,
) => str.split(searchValue).join(replaceValue);

const swap = (str: string, input: string, output: string) => {
  for (let i = 0; i < input.length; i++)
    str = replaceAll(str, input[i], output[i]);

  return str;
};

const createBase64Hmac = (message: string, expiresAt: Date) =>
  swap(
    crypto
      .createHmac('sha1', key)
      .update(`${expiresAt.getTime()}${message}`)
      .digest('hex'),
    '+=/', // Used to avoid characters that aren't safe in URLs
    '-_,',
  );

export const sign = (message: string, expiresAt: Date) =>
  `${expiresAt.getTime()}-${createBase64Hmac(message, expiresAt)}`;

export const verify = (message: string, hash: string) => {
  const matches = hash.match(/(.+?)-(.+)/);
  if (!matches) return false;

  const expires = matches[1];
  const hmac = matches[2];

  if (!/^\d+$/.test(expires)) return false;

  const expiresAt = dayjs(parseInt(expires, 10));
  if (expiresAt.isBefore(dayjs())) return false;

  const expectedHmac = createBase64Hmac(message, expiresAt.toDate());
  // Byte lengths must equal, otherwise crypto.timingSafeEqual will throw an exception
  if (hmac.length !== expectedHmac.length) return false;

  return crypto.timingSafeEqual(
    Buffer.from(hmac),
    Buffer.from(expectedHmac),
  );
};

次のように使用できます。

import { sign, verify } from './signature';

const message = 'foo-bar';
const expiresAt = dayjs().add(1, 'day').toDate();
const hash = sign(message, expiresAt);

const result = verify(message, hash);

expect(result).toBe(true);
于 2022-01-04T01:32:34.727 に答える