web-dev-qa-db-ja.com

TypeScriptファイルのNodejs暗号

私は暗号を必要とする独自のhash.jsファイルを作成し、暗号を使用する2つの関数をエクスポートします。パスワードをハッシュすると、api.jsファイルで正常に機能します。しかし今、このファイルをuser.service.tsファイルにインポートして、パスワード自体ではなく、ハッシュされたバージョンのパスワードをクエリパラメータとして送信できるようにしています。そうしようとすると、cryptが使用する関数は関数ではないというTypeScriptエラーが常に表示されます。ただし、インポートしたオブジェクトをコンソールログに記録することはできます。 node_modulesフォルダー内の他のJavaスクリプトファイルを確認しましたが、ファイルに問題があるはずの部分が何も表示されません。

作成する必要のある定義ファイルがあるようですが、そのようなファイルを作成する試みも何度も行っていますが、何も機能しないようです。

数時間のグーグルとこのプロジェクトの時間不足の中での知識の欠如が私をこの投稿に導きました、それは私の最初のスタックオーバーフローの投稿であり、不明確ではないことを願っています。この問題を解決するために必要な情報を提供できることをうれしく思います。

コンソールからのエラーコード

LoginComponent.html:18 ERROR TypeError: crypto.randomBytes is not a function
at Object.genRandomString (hash.js:12)
at UserService.loginUser (user.service.ts:82)
at LoginComponent.getUser (login.component.ts:54)
at LoginComponent.onSubmit (login.component.ts:44)
at Object.eval [as handleEvent] (LoginComponent.html:18)
at handleEvent (core.es5.js:12014)
at callWithDebugContext (core.es5.js:13475)
at Object.debugHandleEvent [as handleEvent] (core.es5.js:13063)
at dispatchEvent (core.es5.js:8607)
at core.es5.js:10775

LoginComponent.html:18 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 31, nodeDef: {…}, elDef: {…}, elView: {…}}

hash.jsファイル

   'use strict';
    var crypto = require('crypto');

    /**
     * generates random string of characters i.e salt
     * @function
     * @param {number} length - Length of the random string.
     */
    function genRandomString (length){
        return crypto.randomBytes(Math.ceil(length/2))
                .toString('hex') /** convert to hexadecimal format */
                .slice(0,length);   /** return required number of characters */
    };

    /**
     * hash password with sha512.
     * @function
     * @param {string} password - List of required fields.
     * @param {string} salt - Data to be validated.
     */
    function sha512(password, salt){
        var hash = crypto.createHmac('sha512', salt); /** Hashing algorithm sha512 */
        hash.update(password);
        var value = hash.digest('hex');
        return {
            salt:salt,
            passwordHash:value
        };
    };

    module.exports = {
        genRandomString: genRandomString,
        sha512: sha512
    };

JavaScriptとTypeScriptが混同されているようですが、この問題を自分で見つけたので、次の方法で解決しました。

最初に、hash.jsファイルはhash.tsである必要があります。その後、暗号をインポートして通常どおり使用できます。以下の関連コード:

import * as crypto from "crypto";

  public setEncryptionKeyDES(sKey: string) {
    const desIV = Buffer.alloc(8);
    this.encLobby.cipher = crypto.createCipheriv(
      "des-cbc",
      Buffer.from(sKey, "hex"),
      desIV,
    );
    this.encLobby.cipher.setAutoPadding(false);
    this.encLobby.decipher = crypto.createDecipheriv(
      "des-cbc",
      Buffer.from(sKey, "hex"),
      desIV,
    );
    this.encLobby.decipher.setAutoPadding(false);

    this.isSetupComplete = true;
  }
7
Drazisil

そうしようとすると、cryptが使用する関数は関数ではないというTypeScriptエラーが常に表示されます。

これは、TypeScriptがファイルを静的に分析し、操作しているデータの種類を支援するために発生します。この関数が引数として何を使用していて、戻り値の型が何であるかについてTypeScriptへのヒントなしにJavaScriptで記述された関数を使用している場合、単純にその関数を実行できないため、エラーが発生します。

デカルレーションファイルを作成することもできますが、迅速な修正が必要な場合や、これらの生のJS関数を他のファイルで使用しない場合は必要ありません。ファイル内の任意の場所で宣言する必要があります。 TypeScriptでのdeclareキーワードの使用の詳細 を実行できます。

ただし、インポートしたオブジェクトをコンソールログに記録することはできます。

スクリーンショットから判断すると、関数randomBytesが正しく呼び出されます(エラーの下に出力されたスタックトレースからわかるように)。問題は、cryptoオブジェクトにrandomBytesという名前のメソッドが含まれていないことです。これは、cryptoが新しいブラウザのグローバルオブジェクトであるためです。

The <code>crypto</code> object exists in the browser

君の crypto.jsファイルは、ブラウザが持っているものとは異なるcryptoグローバルオブジェクトの存在を想定していると考えられます。このオブジェクトを適切なスコープで提供して、関数が認識できるようにするか、Rollupなどのバンドラーを使用してこれらの関数をインライン化します。

1

この問題が発生しました(ノードv13.12.0、tsc v3.8.3)。私の場合、インポート:

import * as crypto from "crypto";

エラーを与える:

error TS2307: Cannot find module 'crypto'

ノードに types definition をインストールする必要があるため、暗号環境宣言が含まれています。

npm install @types/node

注:@types/nodeのグローバルインストールがある場合は、@typesが配置されているパスを--typesRootオプションで明示的に宣言する必要があります。詳細は here を参照してください。

0
attdona

さて、これは下に行くにはかなり恐ろしいウサギの穴であることがわかりました。私はたくさんの推奨された提案に従いましたが、最終的に私のために働いた解決策は(いつものように...)非常にシンプルでした。

答えは、ブラウザに組み込まれた暗号化機能を使用することでした。私は、非常に軽量なアプリには十分であるとして、パスワードの一方向ダイジェストを確認したかっただけです。ただし、ほとんどのガイドは提案の一部であるか、Angular 7とbabelを使用するアプリの設定では機能しませんでした。そのため、最終的なコードを以下に示します。

  • ダイジェストを実行するには、配列バッファーにエンコードする必要があります
  • ダイジェスト関数はpromiseを返すため、.thenを使用してその値をアンラップする必要がありました
  • anyNPMモジュールまたはインポートを追加する必要はありませんでした

とにかく、ここにコードがあります。それが他のスタックオーバーフラワーに役立つことを願っています。

また、 Daniel Roesler's Githubページが さまざまなWeb暗号化の例の実装 に非常に役立つこともわかりました。

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-user-create',
  templateUrl: './user-create.component.html',
  styleUrls: ['./user-create.component.css']
})
export class UserCreateComponent implements OnInit {

  constructor() { }

  ngOnInit() {

    sha256("hello").then(digestValue => {
      console.log(digestValue);
    });
  }
}

async function sha256(str) {
  const encoder = new TextEncoder();
  const encdata = encoder.encode(str);
  const buf = await crypto.subtle.digest("SHA-256", encdata);
  return Array.prototype.map.call(new Uint8Array(buf), x=>(('00'+x.toString(16)).slice(-2))).join('');
}
0
Rory