admin管理员组文章数量:1127072
In this question Erik needs to generate a secure random token in Node.js. There's the method crypto.randomBytes
that generates a random Buffer. However, the base64 encoding in node is not url-safe, it includes /
and +
instead of -
and _
. Therefore, the easiest way to generate such token I've found is
require('crypto').randomBytes(48, function(ex, buf) {
token = buf.toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
});
Is there a more elegant way?
In this question Erik needs to generate a secure random token in Node.js. There's the method crypto.randomBytes
that generates a random Buffer. However, the base64 encoding in node is not url-safe, it includes /
and +
instead of -
and _
. Therefore, the easiest way to generate such token I've found is
require('crypto').randomBytes(48, function(ex, buf) {
token = buf.toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
});
Is there a more elegant way?
Share Improve this question edited May 23, 2017 at 12:10 CommunityBot 11 silver badge asked Jan 13, 2012 at 18:55 Hubert OGHubert OG 19.5k7 gold badges47 silver badges73 bronze badges 9 | Show 4 more comments16 Answers
Reset to default 475Try crypto.randomBytes():
require('crypto').randomBytes(48, function(err, buffer) {
var token = buffer.toString('hex');
});
The 'hex' encoding works in node v0.6.x or newer.
Synchronous option in-case if you are not a JS expert like me. Had to spend some time on how to access the inline function variable
var token = crypto.randomBytes(64).toString('hex');
1. Using nanoid third party library [NEW!]
A tiny, secure, URL-friendly, unique string ID generator for JavaScript
https://github.com/ai/nanoid
import { nanoid } from "nanoid";
const id = nanoid(48);
2. Base 64 Encoding with URL and Filename Safe Alphabet
Page 7 of RCF 4648 describes how to encode in base 64 with URL safety.
This is natively supported by Node.js >=v14.18.0:
const crypto = require("crypto");
/** Sync */
function randomStringAsBase64Url(size) {
return crypto.randomBytes(size).toString("base64url");
}
Usage example:
randomStringAsBase64Url(20);
// Returns "AXSGpLVjne_f7w5Xg-fWdoBwbfs" which is 27 characters length.
Note that the returned string length will not match with the size argument (size != final length).
If you are using Node.js <v14.18.0 you can use an existing library like base64url to do the job. The function will be:
const crypto = require("crypto");
const base64url = require("base64url");
/** Sync */
function randomStringAsBase64Url(size) {
return base64url(crypto.randomBytes(size));
}
3. Crypto random values from limited set of characters
Beware that with this solution the generated random string is not uniformly distributed.
You can also build a strong random string from a limited set of characters like that:
const crypto = require("crypto");
/** Sync */
function randomString(length, chars) {
if (!chars) {
throw new Error("Argument 'chars' is undefined");
}
const charsLength = chars.length;
if (charsLength > 256) {
throw new Error("Argument 'chars' should not have more than 256 characters"
+ ", otherwise unpredictability will be broken");
}
const randomBytes = crypto.randomBytes(length);
let result = new Array(length);
let cursor = 0;
for (let i = 0; i < length; i++) {
cursor += randomBytes[i];
result[i] = chars[cursor % charsLength];
}
return result.join("");
}
/** Sync */
function randomAsciiString(length) {
return randomString(length,
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
}
Usage example:
randomAsciiString(20);
// Returns "rmRptK5niTSey7NlDk5y" which is 20 characters length.
randomString(20, "ABCDEFG");
// Returns "CCBAAGDGBBEGBDBECDCE" which is 20 characters length.
As of Node.js 14.18 and 15.7, url-safe base64 encoding support is built-in:
const token = crypto.randomBytes(48).toString('base64url');
If you want to use the async version (because the function may have to wait for entropy), it can be promisified to align better with modern patterns:
const randomBytesAsync = util.promisify(crypto.randomBytes);
const token = (await randomBytesAsync(48)).toString('base64url');
The up-to-date right way to do this asynchronously using ES 2016 standards of async and await (as of Node 7) would be the following:
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);
}
This works out of the box in Node 7 without any Babel transformations
Random URL and filename string safe (1 liner)
Crypto.randomBytes(48).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
With async/await and promisification.
const crypto = require('crypto')
const randomBytes = Util.promisify(crypto.randomBytes)
const plain = (await randomBytes(24)).toString('base64').replace(/\W/g, '')
Generates something similar to VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM
Check out:
var crypto = require('crypto');
crypto.randomBytes(Math.ceil(length/2)).toString('hex').slice(0,length);
crypto-random-string is a nice module for this.
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)
add .async
if you want to get a promise
.
in your terminal just write
node -e "console.log(crypto.randomBytes(48).toString('hex'))"
Or in your code use:
const randomToken = () => {
crypto.randomBytes(48).toString('hex');
}
Look at real_ates
ES2016 way, it's more correct.
ECMAScript 2016 (ES7) way
import crypto from 'crypto';
function spawnTokenBuf() {
return function(callback) {
crypto.randomBytes(48, callback);
};
}
async function() {
console.log((await spawnTokenBuf()).toString('base64'));
};
Generator/Yield Way
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'));
});
https://www.npmjs.com/package/crypto-extra has a method for it :)
var value = crypto.random(/* desired length */)
The npm module anyid provides flexible API to generate various kinds of string ID / code.
To generate random string in A-Za-z0-9 using 48 random bytes:
const id = anyid().encode('Aa0').bits(48 * 8).random().id();
// G4NtiI9OYbSgVl3EAkkoxHKyxBAWzcTI7aH13yIUNggIaNqPQoSS7SpcalIqX0qGZ
To generate fixed length alphabet only string filled by random bytes:
const id = anyid().encode('Aa').length(20).random().id();
// qgQBBtDwGMuFHXeoVLpt
Internally it uses crypto.randomBytes()
to generate random.
0 dependency free solution... Works in browsers, deno & nodejs (with new global web crypto)
const random = size => btoa(
String.fromCharCode(
...crypto.getRandomValues(
new Uint8Array(size)
)
)
).replaceAll('+', 'x').replaceAll('/', 'I').slice(0, size)
for (let i = 5; i--;) console.log(random(16))
All doe I would just have used one single uint8array \w predefined length and called crypto.getRandomValues
whenever I need something uniq (and slice it if i have to) and never deal with strings or base64, base64 is just unnecessary overhead.
(allocating lots of buffer to fast can be costly)
const buf256 = new Uint8Array(256)
const random = crypto.getRandomValues.bind(crypto, buf256)
for (let i = 5; i--;) random()//.slice()
Simple function that gets you a token that is URL safe and has base64 encoding! It's a combination of 2 answers from above.
const randomToken = () => {
crypto.randomBytes(64).toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
}
You can use the random-token
lib. it's very easy to use . :)
var randomToken = require('random-token').create('abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
var token = randomToken(16);
And also you can not use different salt
var randomToken = require('random-token');
var token = randomToken(16); // output -> d8d4kd29c40f021 ```
本文标签: javascriptSecure random token in NodejsStack Overflow
版权声明:本文标题:javascript - Secure random token in Node.js - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736690064a1947875.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
'a-zA-Z0-9_-'
). – Max Truxa Commented Aug 9, 2016 at 19:18