Nodejs crypto in typescript file

时间:2018-01-04 11:49:30

标签: javascript node.js angular typescript

我创建了自己的hash.js文件,该文件需要加密并导出两个使用加密的函数。当我散列密码时,它在我的api.js文件中工作正常。但是现在我尝试在我的user.service.ts文件中导入此文件,以便我可以将密码的散列版本作为查询参数而不是密码本身发送。当我尝试这样做时,我总是得到一个TypeScript错误,告诉我crypto使用的函数不是函数。但是,我仍然可以控制登录我导入的对象,它看起来合法。我查看了node_modules文件夹中的其他java脚本文件,我看不到任何应该对我的文件有误的内容。

我还发现似乎有一些我需要创建的定义文件,但我也有很多尝试创建这样的文件,但似乎没有任何工作

几个小时的谷歌搜索以及缺乏时间在这个项目上缺乏知识导致我这篇文章,这是我的第一个stackoverflow帖子,我希望它不是不清楚,我很高兴提供帮助我解决此问题所需的任何信息。

Error code from console

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

4 个答案:

答案 0 :(得分:3)

混合使用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;
  }

答案 1 :(得分:1)

  

当我尝试这样做时,我总是会收到TypeScript错误,告诉我加密使用的函数不是函数。

这种情况正在发生,因为TypeScript会静态分析您的文件并尝试帮助您处理您正在使用的数据类型。如果你正在使用一个用JavaScript编写的函数,而没有任何关于这个函数作为参数使用的提示,以及它的返回值的类型是什么,它根本无法完成它的工作,这就是为什么你要这样做的原因。得到一个错误。

您可以创建一个decalration文件,但如果您想要快速修复并且您不想在其他文件中使用这些原始JS函数,则不需要。您只需要在文件中的任何位置声明它。你可以read more about using declare keyword in TypeScript

  

但是我仍然可以控制登录我导入的对象,它看起来很合法。

根据您的屏幕截图判断,函数randomBytes被正确调用(从错误下方打印的堆栈跟踪中可以看到)。问题是crypto对象不包含名为randomBytes的方法。这是因为crypto是较新浏览器中的全局对象。

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

您的crypto.js文件可能假设存在与浏览器不同的crypto全局对象。在适当的范围内提供此对象,以便您的函数可以看到它,或使用诸如Rollup之类的捆绑器内联这些函数。

答案 2 :(得分: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

答案 3 :(得分:0)

这真是一个可怕的兔子洞。我遵循了一些建议,但最终对我有用的解决方案是(一如既往...)超级简单,一旦您知道怎么做。

答案是使用浏览器内置的加密功能。我只想检查单向密码摘要是否足以构成一个非常轻便的应用程序。但是,大多数指南只是部分建议,或者与我的应用程序使用Angular 7和babel的设置不兼容。因此,这是我最后得到的最终代码,带有以下注释:

  • 需要编码到数组缓冲区中以执行摘要
  • digest函数正在返回一个承诺,因此必须使用.then来取消其值。
  • 不需要添加任何 NPM模块或导入

无论如何,这里是代码,希望它能帮助其他Stack Overflowers。

我还发现Daniel Roesler's的Github页面对于implementations of various web cryptography examples非常有用。

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('');
}