Безопасный случайный токен в узле.js
на этот вопрос Эрик должен создать безопасный случайный маркер в узле.js. Вот это метод crypto.randomBytes это создает случайный буфер. Однако кодировка base64 в узле не является безопасной для url, она включает / и + вместо - и _. Поэтому самый простой способ создать такой токен, который я нашел, - это
require('crypto').randomBytes(48, function(ex, buf) {
token = buf.toString('base64').replace(///g,'_').replace(/+/g,'-');
});
есть ли более элегантный способ?
11 ответов:
попробовать крипто.randomBytes ():
require('crypto').randomBytes(48, function(err, buffer) { var token = buffer.toString('hex'); });кодировка ' hex ' работает в узле v0.6.X или новее.
синхронный вариант в случае, если вы не являетесь экспертом JS, как я. Пришлось потратить некоторое время на то, как получить доступ к встроенной переменной функции
var token = crypto.randomBytes(64).toString('hex');
0. Использование nanoid сторонней библиотеки [NEW!]
крошечный, безопасный, удобный для URL, уникальный генератор идентификаторов строк для JavaScript
const nanoid = require("nanoid"); const id = nanoid(48);
1. Кодировка Base 64 с URL и именем файла Safe Alphabet
Страница 7 из RCF 4648 описывает, как кодировать в базе 64 с безопасностью URL. Вы можете использовать существующую библиотеку, как 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 != конечная длина).
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.
вверх-к-дата правильно чтобы сделать это асинхронно, используя стандарты ES 2016 async и await (начиная с узла 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); }это работает из коробки в узле 7 без каких-либо преобразований Бабеля
случайный URL и строка имени файла safe (1 liner)
Crypto.randomBytes(48).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
посмотреть
real_atesES2016 путь, это более правильно.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')); };Генератор / Выход Путь
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')); });
проверить:
var crypto = require('crypto'); crypto.randomBytes(Math.ceil(length/2)).toString('hex').slice(0,length);
С async/await и promisification.
const crypto = require('crypto') const randomBytes = Util.promisify(crypto.randomBytes) const plain = (await randomBytes(24)).toString('base64').replace(/\W/g, '')создает что-то похожее на
VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM
вот асинхронная версия, взятая дословно сверху @Yves M.'s answer
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); });
модуль npm anyid обеспечивает гибкий API для генерации различных видов строки ID / кода.
для генерации случайной строки В A-Za-z0-9 с использованием 48 случайных байтов:
const id = anyid().encode('Aa0').bits(48 * 8).random().id(); // G4NtiI9OYbSgVl3EAkkoxHKyxBAWzcTI7aH13yIUNggIaNqPQoSS7SpcalIqX0qGZдля генерации алфавита фиксированной длины только строка, заполненная случайными байтами:
const id = anyid().encode('Aa').length(20).random().id(); // qgQBBtDwGMuFHXeoVLptвнутренне он использует
crypto.randomBytes()для генерации случайных.
https://www.npmjs.com/package/crypto-extra имеет метод для этого :)
var value = crypto.random(/* desired length */)
Comments