在Node.js中保护随机令牌

时间:2012-01-13 18:55:15

标签: javascript node.js base64 securestring

this question中,Erik需要在Node.js中生成安全随机令牌。方法crypto.randomBytes生成随机缓冲区。但是,节点中的base64编码不是url-safe,它包括/+,而不是-_。因此,我发现生成此类令牌的最简单方法是

require('crypto').randomBytes(48, function(ex, buf) {
    token = buf.toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
});

有更优雅的方式吗?

13 个答案:

答案 0 :(得分:311)

尝试crypto.randomBytes()

require('crypto').randomBytes(48, function(err, buffer) {
  var token = buffer.toString('hex');
});

' hex'编码在节点v0.6.x或更新版本中工作。

答案 1 :(得分:196)

如果您不是像我这样的JS专家,

同步选项。不得不花一些时间来访问内联函数变量

var token = crypto.randomBytes(64).toString('hex');

答案 2 :(得分:66)

0。使用nanoid第三方库[新!]

  

用于JavaScript的小巧,安全,对URL友好,唯一的字符串ID生成器

https://github.com/ai/nanoid

const nanoid = require("nanoid");
const id = nanoid(48);


1。 Base 64使用URL和文件名安全字母编码

Page 7 of RCF 4648描述了如何使用URL安全性在base 64中进行编码。 您可以使用base64url之类的现有库来完成这项工作。

该功能将是:

var crypto = require('crypto');
var base64url = require('base64url');

/** Sync */
function randomStringAsBase64Url(size) {
  return base64url(crypto.randomBytes(size));
}

用法示例:

randomStringAsBase64Url(20);
// Returns 'AXSGpLVjne_f7w5Xg-fWdoBwbfs' which is 27 characters length.

请注意,返回的字符串长度与size参数(size!= final length)不匹配。


2。从有限的字符集中加密随机值

  

请注意,使用此解决方案,生成的随机字符串不是均匀分布的。

您还可以使用以下有限字符集构建强大的随机字符串:

var crypto = require('crypto');

/** Sync */
function randomString(length, chars) {
  if (!chars) {
    throw new Error('Argument \'chars\' is undefined');
  }

  var charsLength = chars.length;
  if (charsLength > 256) {
    throw new Error('Argument \'chars\' should not have more than 256 characters'
      + ', otherwise unpredictability will be broken');
  }

  var randomBytes = crypto.randomBytes(length);
  var result = new Array(length);

  var cursor = 0;
  for (var i = 0; i < length; i++) {
    cursor += randomBytes[i];
    result[i] = chars[cursor % charsLength];
  }

  return result.join('');
}

/** Sync */
function randomAsciiString(length) {
  return randomString(length,
    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
}

用法示例:

randomAsciiString(20);
// Returns 'rmRptK5niTSey7NlDk5y' which is 20 characters length.

randomString(20, 'ABCDEFG');
// Returns 'CCBAAGDGBBEGBDBECDCE' which is 20 characters length.

答案 3 :(得分:10)

使用ES 2016异步和等待(从节点7开始)标准异步执行正确方式的方法如下:

const crypto = require('crypto');

function generateToken({ stringBase = 'base64', byteLength = 48 } = {}) {
  return new Promise((resolve, reject) => {
    crypto.randomBytes(byteLength, (err, buffer) => {
      if (err) {
        reject(err);
      } else {
        resolve(buffer.toString(stringBase));
      }
    });
  });
}

async function handler(req, res) {
   // default token length
   const newToken = await generateToken();
   console.log('newToken', newToken);

   // pass in parameters - adjust byte length
   const shortToken = await generateToken({byteLength: 20});
   console.log('newToken', shortToken);
}

这在Node 7中开箱即用,没有任何Babel转换

答案 4 :(得分:7)

随机URL和文件名字符串安全(1个班轮)

Crypto.randomBytes(48).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');

答案 5 :(得分:6)

使用async / await和promisification

E

生成与const crypto = require('crypto') const randomBytes = Util.promisify(crypto.randomBytes) const plain = (await randomBytes(24)).toString('base64').replace(/\W/g, '')

类似的内容

答案 6 :(得分:5)

看看real_ates ES2016的方式,它更正确。

ECMAScript 2016(ES7)方式

import crypto from 'crypto';

function spawnTokenBuf() {
    return function(callback) {
        crypto.randomBytes(48, callback);
    };
}

async function() {
    console.log((await spawnTokenBuf()).toString('base64'));
};

发电机/收益方式

var crypto = require('crypto');
var co = require('co');

function spawnTokenBuf() {
    return function(callback) {
        crypto.randomBytes(48, callback);
    };
}

co(function* () {
    console.log((yield spawnTokenBuf()).toString('base64'));
});

答案 7 :(得分:4)

退房:

var crypto = require('crypto');
crypto.randomBytes(Math.ceil(length/2)).toString('hex').slice(0,length);

答案 8 :(得分:2)

npm模块anyid提供灵活的API来生成各种字符串ID /代码。

使用48个随机字节在A-Za-z0-9中生成随机字符串:

const id = anyid().encode('Aa0').bits(48 * 8).random().id();
// G4NtiI9OYbSgVl3EAkkoxHKyxBAWzcTI7aH13yIUNggIaNqPQoSS7SpcalIqX0qGZ

生成由随机字节填充的固定长度字母表字符串:

const id = anyid().encode('Aa').length(20).random().id();
// qgQBBtDwGMuFHXeoVLpt

在内部,它使用crypto.randomBytes()生成随机。

答案 9 :(得分:1)

这是从@Yves M上面逐字逐句采取的异步版本。回答

var crypto = require('crypto');

function createCryptoString(length, chars) { // returns a promise which renders a crypto string

    if (!chars) { // provide default dictionary of chars if not supplied

        chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    }

    return new Promise(function(resolve, reject) {

        var charsLength = chars.length;
        if (charsLength > 256) {
            reject('parm chars length greater than 256 characters' +
                        ' masks desired key unpredictability');
        }

        var randomBytes = crypto.randomBytes(length);

        var result = new Array(length);

        var cursor = 0;
        for (var i = 0; i < length; i++) {
            cursor += randomBytes[i];
            result[i] = chars[cursor % charsLength];
        }

        resolve(result.join(''));
    });
}

// --- now generate crypto string async using promise --- /

var wantStringThisLength = 64; // will generate 64 chars of crypto secure string

createCryptoString(wantStringThisLength)
.then(function(newCryptoString) {

    console.log(newCryptoString); // answer here

}).catch(function(err) {

    console.error(err);
});

答案 10 :(得分:1)

https://www.npmjs.com/package/crypto-extra有一个方法:)

var value = crypto.random(/* desired length */)

答案 11 :(得分:1)

一个简单的函数,可为您提供URL安全且具有base64编码的令牌!它是上面两个答案的组合。

const randomToken = () => {
    crypto.randomBytes(64).toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
}

答案 12 :(得分:0)

crypto-random-string 是一个很好的模块。

const cryptoRandomString = require('crypto-random-string');
 
cryptoRandomString({length: 10});
// => '2cf05d94db'
 
cryptoRandomString({length: 10, type: 'base64'});
// => 'YMiMbaQl6I'
 
cryptoRandomString({length: 10, type: 'url-safe'});
// => 'YN-tqc8pOw'
 
cryptoRandomString({length: 10, type: 'numeric'});
// => '8314659141'
 
cryptoRandomString({length: 6, type: 'distinguishable'});
// => 'CDEHKM'
 
cryptoRandomString({length: 10, type: 'ascii-printable'});
// => '`#Rt8$IK>B'
 
cryptoRandomString({length: 10, type: 'alphanumeric'});
// => 'DMuKL8YtE7'
 
cryptoRandomString({length: 10, characters: 'abc'});
// => 'abaaccabac'

cryptoRandomString.async(options)如果想获得.async,请添加promise