【问题标题】:How can I mimick OpenLDAP's slappasswd using NodeJS?如何使用 Node JS 模仿 OpenLDAP slappasswd?
【发布时间】:2022-07-26 15:04:30
【问题描述】:

我的目标是使用 NodeJS 创建类似于 slappasswd 命令行工具的 LDAP 密码哈希。

以下是使用命令行生成 LDAP 密码的方法:

slappasswd -h '{SSHA}' -s 'P@ssw0rd'
{SSHA}1RHPt8m4AWLjK8Px1MT6FEBJOBJpdzqT

结果是一个 base64 编码的加盐 SHA1 密码。

这是我最初尝试重新创建的内容:

#!/usr/bin/env node

import sha1 from 'crypto-js/sha1.js';

let password = 'P@ssW0rd';
let salt = btoa(0xA5);  // Not random, just a proof of concept temporary value.
let hash = sha1(password + salt);
console.log('{SSHA}' + btoa(hash));

但是,我得到的字符串比 slappasswd 命令生成的要长得多,我不知道为什么。

{SSHA}NDVkN2JjODQ2ZDk3Yjc2YmViNTU3MzUzYjBiNzExN2ZmYzMxYWY5ZA==

我在网上进行了一些挖掘,并在 LDAP 密码生成器网页上找到了这个:

<script src="lib/cryptojs/core.js"></script>
<script src="lib/cryptojs/sha1.js"></script>
<script src="lib/cryptojs/enc-base64.js"></script>

<script>
    function slappasswd(password) {
      var salt = CryptoJS.lib.WordArray.random(128/8).toString().substr(0,4);
      var hash = CryptoJS.SHA1(password + salt);
      var base = CryptoJS.enc.Latin1.parse(hash.toString(CryptoJS.enc.Latin1) + salt).toString(CryptoJS.enc.Base64);
      return '{SSHA}' + base;
    }
...

网页生成的字符串长度与 slappasswd 的长度相同,因此我认为这是对 slappasswd 逻辑的准确再现。

使用这些信息,我的下一次尝试如下所示:

#!/usr/bin/env node

import * as CryptoJS from 'crypto-js';

let password = 'P@ssW0rd';
let salt = CryptoJS.lib.WordArray.random(128/8).toString().substr(0,4);
let hash = sha1(password + salt);
let base = CryptoJS.enc.Latin1.parse(hash.toString(CryptoJS.enc.Latin1) + salt).toString(CryptoJS.enc.Base64);
console.log('{SSHA}' + base);

但是,我得到了错误。

首先是TypeError: Cannot read properties of undefined (reading 'WordArray')

如果我在第一次尝试代码中将 let salt = 替换为 let salt = btoa(0xA5),则会收到错误消息:ReferenceError: sha1 is not defined

我的感觉是我的导入错误。

我正在尝试做相当于var CryptoJS = require("crypto-js"); 的 ES6 模块,但在某处失败了。

所以我的问题有两个:

  1. 我的第一次尝试是否可以生成一个类似于 slappassword 输出的字符串长度?
  2. 如果没有,我该如何解决我在第二次尝试中遇到的错误?

理想情况下,我想了解我在第一次尝试时出错的地方,而不是在没有完全掌握的情况下简单地复制和粘贴其他人的代码(第二次尝试)。

【问题讨论】:

    标签: javascript node.js cryptojs


    【解决方案1】:

    这里是 NodeJS 的 python/php 实现的替代方案。

    导入加密模块

    const crypto = require('crypto');
    

    生成的哈希函数

    function generate_hash(passwd, salt) {
      if (!salt) {
         const buf = crypto.randomBytes(32);
         salt = buf.toString('base64');
      }
      let ctx = crypto.createHash('sha1');
      ctx.update(passwd, 'utf-8');
      ctx.update(salt, 'binary');
      let digest = ctx.digest('binary');
      let ssha = '{SSHA}' + Buffer.from(digest + salt, 
           'binary').toString('base64');
      return ssha;
    } 
    

    验证生成的哈希函数

    function verify_hash(passwd, hash) {
      let bhash = Buffer.from(hash.substr(6), 'base64');
      let salt = bhash.toString('binary', 20);
      let newssha = generate_hash(passwd, salt);
      return hash === newssha;
    }
    

    一起测试

     const hash = generate_hash("qwe1234");
     let test = verify_hash("qwe1234", hash);
     console.log(test);  //Output: true
     let test = verify_hash("XXXX", hash);
     console.log(test);  //Output: false
    

    希望对您有所帮助。请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-06
      • 1970-01-01
      • 2016-07-01
      相关资源
      最近更新 更多