Sécurisez le jeton aléatoire dans le noeud.js

Dans cette question Erik doit générer une sécurité aléatoire jeton dans le Nœud.js. Il y a la méthode crypto.randomBytes qui génère un tampon aléatoire. Cependant, l'encodage base64 dans le noeud n'est pas sûr pour les URLs, il inclut / et + au lieu de - et _ . Par conséquent, la façon la plus facile de générer un tel token que j'ai trouvé est

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

Est-il un moyen plus élégant?

202
demandé sur Community 2012-01-13 22:55:14

11 réponses

Essayer crypto.randomBytes() :

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

Le 'hex' encodage travaille dans le nœud v0.6.x ou plus récent.

269
répondu thejh 2016-03-18 18:34:37

option synchrone au cas où vous ne seriez pas un expert JS comme moi. A dû passer un certain temps sur la façon d'accéder à la variable de fonction en ligne

var token = crypto.randomBytes(64).toString('hex');
174
répondu phoenix2010 2014-08-13 16:59:27

0. Utilisation de nanoid third party library [nouveau!]

un petit, sécurisé, URL-friendly, générateur d'ID de chaîne unique pour JavaScript

https://github.com/ai/nanoid

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



1. Codage en Base 64 avec l'URL et le nom de fichier en Sécurité de l'Alphabet

page 7 de RCF 4648 décrit comment encoder en base 64 avec la sécurité des URL. Vous pouvez utiliser une bibliothèque existante comme base64url pour faire le travail.

la fonction sera:

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

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

exemple d'utilisation:

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

notez que la longueur de la chaîne retournée ne correspondra pas à l'argument Taille (size != longueur finale).



2. Valeurs aléatoires Crypto à partir d'un jeu limité de caractères

méfiez-vous qu'avec cette solution la chaîne aléatoire générée n'est pas distribuée uniformément.

vous pouvez aussi construire une chaîne aléatoire forte à partir d'un ensemble limité de caractères comme celui-ci:

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

exemple d'utilisation:

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

randomString(20, 'ABCDEFG');
// Returns 'CCBAAGDGBBEGBDBECDCE' which is 20 characters length.
55
répondu Yves M. 2018-05-09 15:09:19

L'up-to-date droit chemin", 151930920" pour ce faire de manière asynchrone à l'aide de ES 2016 normes de async et await (Nœud 7) serait la suivante:

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

cela fonctionne hors de la boîte dans le noeud 7 sans aucune transformation Babel

9
répondu real_ate 2017-06-08 11:05:49

Aléatoire URL et le nom de la chaîne de sécurité (1 conduit)

Crypto.randomBytes(48).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
6
répondu Kedem 2016-03-15 10:34:22

regardez real_ates es2016 way, c'est plus 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'));
};

Générateur/Rendement Moyen

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'));
});
5
répondu Karl Morrison 2017-05-09 21:19:18

Check out:

var crypto = require('crypto');
crypto.randomBytes(Math.ceil(length/2)).toString('hex').slice(0,length);
3
répondu sudam 2017-01-21 20:31:45

With async / wait and promisification .

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

génère quelque chose de similaire à VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM

3
répondu Znarkus 2017-07-31 12:49:26

Voici une version asynchrone tirée mot à mot de la réponse de @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);
});
1
répondu Scott Stensland 2015-11-13 00:36:40

le module npm anyid fournit une API flexible pour générer divers types d'ID / code de chaîne.

pour générer une chaîne aléatoire dans A-Za-z0-9 en utilisant 48 octets aléatoires:

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

pour générer une chaîne d'alphabet de longueur fixe uniquement remplie par des octets aléatoires:

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

interne il utilise crypto.randomBytes() pour générer aléatoire.

1
répondu aleung 2016-08-05 05:45:09

https://www.npmjs.com/package/crypto-extra a une méthode pour cela :)

var value = crypto.random(/* desired length */)
0
répondu jsonmaur 2016-02-19 23:54:45