打字稿文件中的Nodejs加密

Posted

技术标签:

【中文标题】打字稿文件中的Nodejs加密【英文标题】:Nodejs crypto in typescript file 【发布时间】:2018-06-14 03:31:48 【问题描述】:

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

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

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

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 ;

【问题讨论】:

可以粘贴错误代码吗? 【参考方案1】:

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

这是因为 TypeScript 静态分析您的文件并尝试帮助您处理您正在使用的数据类型。如果您使用的是用 javascript 编写的函数,而没有向 TypeScript 提示该函数使用什么作为参数以及它的返回值的类型是什么,那么它根本无法完成它的工作,这就是您收到错误的原因。

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

但是我仍然可以控制台记录我导入的对象,并且它在我看来是合法的。

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

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

【讨论】:

“你只需要在文件中的任何地方声明它”,我忘了提到我之前确实尝试在我的打字稿文件中声明导出的函数,我在其中进行导入。像这样:声明 var genRandomString: any;声明 var sha512: any;【参考方案2】:

混合使用 JavaScript 和 TypeScript 似乎有些混乱,但由于我自己遇到了这个问题,所以我是这样解决的。

首先,您的 hash.js 文件应该是 hash.ts。然后你就可以导入crypto并正常使用了。相关代码如下:

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;
  

Edit1:从下面添加@attdona 的答案,确保您也将@types/node 安装到您的项目中,否则您将收到许多与找不到节点模块相关的错误。

【讨论】:

【参考方案3】:

结果证明这是一个相当可怕的兔子洞。我遵循了一堆推荐的建议,但最终对我有用的解决方案(一如既往......)超级简单,一旦你知道怎么做。

答案是使用浏览器内置的加密功能。我只想检查密码的单向摘要是否足以用于非常轻量级的应用程序。然而,大多数指南只是部分建议,或者不适用于我的应用程序使用 Angular 7 和 babel 的设置。所以这是我最终得到的代码,带有以下注释:

需要编码到数组缓冲区来执行摘要 digest 函数返回一个 promise,因此必须使用 .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('');

【讨论】:

Edge 似乎仍然不支持加密。【参考方案4】:

刚刚遇到这个问题(节点 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。

【讨论】:

以上是关于打字稿文件中的Nodejs加密的主要内容,如果未能解决你的问题,请参考以下文章

打字稿中的Nodejs需要('this')(that)

使用打字稿时nodemon不刷新

nodejs和打字稿中的Prisma事务不起作用

NodeJs 打字稿和模块问题

使用打字稿表达无法查找视图目录

为外部 js nodejs 包编写 typescript 声明文件,没有类型信息