Token casuale sicuro in Node.js

In questa domanda Erik deve generare un token casuale sicuro in Node.js. C’è il metodo crypto.randomBytes che genera un Buffer casuale. Tuttavia, la codifica base64 nel nodo non è url-safe, include / e + invece di - e _ . Pertanto, il modo più semplice per generare tale token che ho trovato è

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

C’è un modo più elegante?

Prova crypto.randomBytes () :

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

La codifica “hex” funziona nel nodo v0.6.xo più recente.

Opzione sincrona in-case se non sei un esperto di JS come me. Dovevo dedicare del tempo a come accedere alla variabile funzione inline

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

0. Uso della libreria nanoid di terze parti [NUOVO!]

Un minuscolo generatore di ID stringa minuscolo, sicuro, URL-friendly per JavaScript

https://github.com/ai/nanoid

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

1. Codifica 64 Base con URL e Alfabeto sicuro per nome file

Pagina 7 di RCF 4648 descrive come codificare in base 64 con sicurezza URL. Puoi usare una libreria esistente come base64url per fare il lavoro.

La funzione sarà:

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

Esempio di utilizzo:

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

Si noti che la lunghezza della stringa restituita non corrisponderà all’argomento dimensione (dimensione! = Lunghezza finale).

2. Crypto valori casuali dal set limitato di caratteri

Fai attenzione che con questa soluzione la stringa casuale generata non è distribuita uniformsmente.

Puoi anche creare una stringa casuale forte da un set limitato di caratteri del genere:

 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'); } 

Esempio di utilizzo:

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

Il modo giusto e aggiornato per fare ciò in modo asincrono usando gli standard ES 2016 di async e attendere (come dal Nodo 7) sarebbe il seguente:

 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); } 

Funziona fuori dal box nel Nodo 7 senza alcuna trasformazione di Babele

URL casuale e stringa del nome file sicura (1 riga)

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

Guarda in real_ates modo ES2016, è più corretto.

ECMAScript 2016 (ES7) modo

 import crypto from 'crypto'; function spawnTokenBuf() { return function(callback) { crypto.randomBytes(48, callback); }; } async function() { console.log((await spawnTokenBuf()).toString('base64')); }; 

Generatore / Modo di rendimento

 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')); }); 

Check-out:

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

Con async / attendi e promesse .

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

Genera qualcosa di simile a VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM

Ecco una versione asincrona presa verbatim dall’alto la risposta di @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); }); 

Il modulo npm anyid fornisce API flessibili per generare vari tipi di string ID / codice.

Per generare una stringa casuale in A-Za-z0-9 utilizzando 48 byte casuali:

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

Per generare alfabeto con lunghezza fissa solo stringa riempita da byte casuali:

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

Internamente utilizza crypto.randomBytes() per generare random.

https://www.npmjs.com/package/crypto-extra ha un metodo per questo 🙂

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