web-dev-qa-db-fra.com

Jeton aléatoire sécurisé dans Node.js

Dans cette question Erik doit générer un jeton aléatoire sécurisé dans Node.js. Il y a la méthode crypto.randomBytes qui génère un tampon aléatoire. Cependant, le codage base64 dans le noeud n'est pas sécurisé par l'url, il inclut / et + au lieu de - et _. Par conséquent, le moyen le plus simple de générer le jeton que j'ai trouvé est

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

Y a-t-il un moyen plus élégant?

238
Hubert OG

Essayez crypto.randomBytes () :

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

Le codage 'hex' fonctionne dans le noeud v0.6.x ou plus récent.

324
thejh

Option synchrone au cas où vous n'êtes pas un expert JS comme moi. J'ai dû passer du temps à accéder à la variable de fonction inline

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

0. Utilisation de la bibliothèque tierce nanoïde [NEW!]

Un petit générateur d'identifiant de chaîne unique et sécurisé, convivial pour les URL et l'URL, pour JavaScript

https://github.com/ai/nanoid

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


1. Encodage de base 64 avec URL et alphabet sécurisé de nom de fichier

Page 7 of RCF 4648 explique comment coder en base 64 avec la sécurité des URL. Vous pouvez utiliser une bibliothèque existante telle que base64url pour effectuer 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 chaîne renvoyée ne correspondra pas à l'argument de taille (taille! = Longueur finale).


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

Attention, avec cette solution, la chaîne aléatoire générée n'est pas uniformément distribuée.

Vous pouvez également créer 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.
71
Yves M.

La mise à jour bonne façon de le faire de manière asynchrone en utilisant les normes ES 2016 d'async et d'attendre (à partir de Node 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 Node 7 sans aucune transformation Babel

10
real_ate

URL aléatoire et chaîne de nom de fichier sécurisée (1 doublure)

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

Avec async/wait et 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

6
Znarkus

Check-out:

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

Regardez real_ates ES2016 façon, c'est plus correct.

Méthode ECMAScript 2016 (ES7)

import crypto from 'crypto';

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

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

Générateur/voie de rendement

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
Karl Morrison

Le module npm anyid fournit une API flexible permettant de générer différents 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 un alphabet de longueur fixe uniquement une chaîne remplie par des octets aléatoires:

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

En interne, il utilise crypto.randomBytes() pour générer de manière aléatoire.

2
aleung

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

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

Voici une version asynchrone prise mot par 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
Scott Stensland