php 有没有办法在node.js中使用GMP库来验证SRP6

a0zr77ik  于 2023-03-28  发布在  PHP
关注(0)|答案(2)|浏览(164)

我在Node.js中搜索了一种使用以下PHP函数的方法,在搜索了一段时间后,我发现在我的情况下没有任何工作:
x一个月一次x一个月一次x一个月二次x一个月三次
我们的想法是用js重写这个php代码:

function CalculateSRP6Verifier($username, $password, $salt)
    {
        // algorithm constants
        $g = gmp_init(7);
        $N = gmp_init('894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7', 16);
        
        // calculate first hash
        $h1 = sha1(strtoupper($username . ':' . $password), TRUE);
        
        // calculate second hash
        $h2 = sha1($salt.$h1, TRUE);
        
        // convert to integer (little-endian)
        $h2 = gmp_import($h2, 1, GMP_LSW_FIRST);
        
        // g^h2 mod N
        $verifier = gmp_powm($g, $h2, $N);
        
        // convert back to a byte array (little-endian)
        $verifier = gmp_export($verifier, 1, GMP_LSW_FIRST);
        
        // pad to 32 bytes, remember that zeros go on the end in little-endian!
        $verifier = str_pad($verifier, 32, chr(0), STR_PAD_RIGHT);
        
        // done!
        return $verifier;
    }
ctehm74n

ctehm74n1#

我在不久前找到了我的问题的答案。这可以在Node.js中使用Buffer和下面的库bigint-bufferbig-integer来完成,就像我在下面做的那样。

const bigintBuffer = require(`bigint-buffer`)
const BigInteger = require(`big-integer`)
const crypto = require(`crypto`)

/**
 *
 * @param {Buffer} salt
 * @param {string} identity
 * @param {string} password
 * @return {Buffer}
 */
function computeVerifier (salt, identity, password) {
    const hashIP = crypto.createHash(`sha1`)
        .update(identity + `:` + password)
        .digest()
    const hashX = crypto.createHash(`sha1`)
        .update(salt)
        .update(hashIP)
        .digest()
    const x = bigintBuffer.toBigIntLE(hashX)
    const g = BigInt(`0x7`)
    const N = BigInt(`0x894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7`)
    const verifier = BigInteger(g).modPow(x, N)
    const lEVerifier = verifier.value.toString(16).match(/.{2}/g).reverse().join(``)
    return Buffer.from(lEVerifier, `hex`)
}

// Test
crypto.randomBytes(32, (err, buf) => {
    if (err) throw err;
    computeVerifier(buf, `foo`, `bar`);
});

如果你想直接使用我创建的一个适用于TrinityCore和AzerothCore的库:https://www.npmjs.com/package/trinitycore-srp6

af7jpaap

af7jpaap2#

import crypto from "crypto";
import { toBigIntLE, toBufferLE } from "bigint-buffer";
import sha1 from "sha1";
import { modPow } from 'bigint-crypto-utils';
// 常量
const _g: bigint = BigInt(7);
const _N: bigint = BigInt('0x894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7');
/**
 * 计算SRP6验证器
 * @param username string 用户名
 * @param password string 密码
 * @param salt Buffer 盐
 * @returns Buffer 验证器
 */
function calculateSRP6Verifier(username: string, password: string, salt: Buffer): Buffer {

  const h1: Buffer = Buffer.from(sha1((username + ':' + password).toUpperCase()), 'hex') ;

  const h2: bigint = toBigIntLE(Buffer.from(sha1(Buffer.concat([salt, h1])), 'hex'))

  let verifier: Buffer = toBufferLE(modPow(_g, h2, _N), 32)

  verifier = Buffer.concat([verifier, Buffer.alloc(32 - verifier.length, '\0')]);

  return verifier;
}

/**
 * 获取注册数据
 * @param username string 用户名
 * @param password string 密码
 * @returns [Buffer, Buffer] 注册数据
 */
function getRegistrationData(username:string, password:string): [Buffer, Buffer] {

  const salt: Buffer = crypto.randomBytes(32);

  const verifier: Buffer = calculateSRP6Verifier(username, password, salt);

  return [salt, verifier];
}

/**
 * 验证SRP6
 * @param user string 用户名
 * @param pass string 密码
 * @param salt Buffer 盐
 * @param verifier Buffer 验证器
 * @returns boolean 是否验证成功
 */
function verifySRP6(user: string, pass: string, salt: Buffer, verifier: Buffer): boolean {

  const paddedVerifier: Buffer = calculateSRP6Verifier(user, pass, salt)

  return verifier.equals(paddedVerifier);
}

相关问题