266 votes

Cryptage et décryptage de chaînes JavaScript ?

J'aimerais créer une petite application à usage personnel qui cryptera et décryptera des informations du côté client en utilisant JavaScript. Les informations cryptées seront stockées dans une base de données sur un serveur, mais jamais la version décryptée.

Il n'est pas nécessaire qu'il soit super sécurisé, mais j'aimerais utiliser un algorithme actuellement intact.

L'idéal serait de pouvoir faire quelque chose comme

var gibberish = encrypt(string, salt, key);

pour générer la chaîne codée, et quelque chose comme

var sensical = decrypt(gibberish, key);

pour le décoder plus tard.

Jusqu'à présent, j'ai vu ça : http://bitwiseshiftleft.github.io/sjcl/

Y a-t-il d'autres bibliothèques que je devrais consulter ?

244voto

Tomas Kirda Points 3548
 var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
//U2FsdGVkX18ZUVvShFSES21qHsQEqZXMxQ9zgHy+bu0=

var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");
//4d657373616765

document.getElementById("demo1").innerHTML = encrypted;
document.getElementById("demo2").innerHTML = decrypted;
document.getElementById("demo3").innerHTML = decrypted.toString(CryptoJS.enc.Utf8);

Full working sample actually is:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js" integrity="sha256-/H4YS+7aYb9kJ5OKhFYPUjSJdrtV6AeyJOtTkw6X72o=" crossorigin="anonymous"></script>

<br><br>
<label>encrypted</label>
<div id="demo1"></div>
<br>

<label>decrypted</label>
<div id="demo2"></div>

<br>
<label>Actual Message</label>
<div id="demo3"></div>

98voto

ovidb Points 705

Et si CryptoJS ?

C'est une bibliothèque cryptographique solide, avec de nombreuses fonctionnalités. Elle implémente les hashers, HMAC, PBKDF2 et les ciphers. Dans ce cas, c'est de chiffrement dont vous avez besoin. Consultez le guide de démarrage rapide sur la page d'accueil du projet.

Vous pourriez faire quelque chose comme avec l'AES :

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>

<script>
    var encryptedAES = CryptoJS.AES.encrypt("Message", "My Secret Passphrase");
    var decryptedBytes = CryptoJS.AES.decrypt(encryptedAES, "My Secret Passphrase");
    var plaintext = decryptedBytes.toString(CryptoJS.enc.Utf8);
</script>

En ce qui concerne la sécurité, à l'heure où j'écris ces lignes, l'algorithme AES est considéré comme inviolable.

Edit :

Il semble que l'URL en ligne soit en panne & vous pouvez utiliser les fichiers téléchargés pour le cryptage à partir du lien ci-dessous et placer les fichiers respectifs dans votre dossier racine de l'application.

https://code.google.com/archive/p/crypto-js/downloads

ou utilisé un autre CDN comme https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/aes-min.js

96voto

Bommox Points 718

J'ai créé un utilitaire de chiffrement/déchiffrement de texte simple mais non sécurisé. Aucune dépendance avec une bibliothèque externe.

Ce sont les fonctions :

const cipher = salt => {
    const textToChars = text => text.split('').map(c => c.charCodeAt(0));
    const byteHex = n => ("0" + Number(n).toString(16)).substr(-2);
    const applySaltToChar = code => textToChars(salt).reduce((a,b) => a ^ b, code);

    return text => text.split('')
      .map(textToChars)
      .map(applySaltToChar)
      .map(byteHex)
      .join('');
}

const decipher = salt => {
    const textToChars = text => text.split('').map(c => c.charCodeAt(0));
    const applySaltToChar = code => textToChars(salt).reduce((a,b) => a ^ b, code);
    return encoded => encoded.match(/.{1,2}/g)
      .map(hex => parseInt(hex, 16))
      .map(applySaltToChar)
      .map(charCode => String.fromCharCode(charCode))
      .join('');
}

// To create a cipher
const myCipher = cipher('mySecretSalt')

//Then cipher any text:
console.log(myCipher('the secret string'))

//To decipher, you need to create a decipher and use it:
const myDecipher = decipher('mySecretSalt')
console.log(myDecipher("7c606d287b6d6b7a6d7c287b7c7a61666f"))

53voto

q212 Points 15

Ce code est basé sur la réponse de @Jorgeblom ci-dessus.


@Jorgeblom mon gars, c'est une fantastique petite librairie cryptographique :D J'y touche un peu car je n'aimais pas devoir assigner le sel et le rappeler mais en général, pour mes besoins, c'est absolument parfait.

const crypt = (salt, text) => {
  const textToChars = (text) => text.split("").map((c) => c.charCodeAt(0));
  const byteHex = (n) => ("0" + Number(n).toString(16)).substr(-2);
  const applySaltToChar = (code) => textToChars(salt).reduce((a, b) => a ^ b, code);

  return text
    .split("")
    .map(textToChars)
    .map(applySaltToChar)
    .map(byteHex)
    .join("");
};

const decrypt = (salt, encoded) => {
  const textToChars = (text) => text.split("").map((c) => c.charCodeAt(0));
  const applySaltToChar = (code) => textToChars(salt).reduce((a, b) => a ^ b, code);
  return encoded
    .match(/.{1,2}/g)
    .map((hex) => parseInt(hex, 16))
    .map(applySaltToChar)
    .map((charCode) => String.fromCharCode(charCode))
    .join("");
};

Et vous l'utilisez

// encrypting
const encrypted_text = crypt("salt", "Hello"); // -> 426f666665

// decrypting
const decrypted_string = decrypt("salt", "426f666665"); // -> Hello

30voto

Scott Points 389

Les réponses existantes qui s'appuient sur SJCL, CryptoJS, et/ou WebCrypto ne sont pas nécessairement faux mais ils ne sont pas aussi sûrs que vous pourriez le penser. En général, vous voulez utiliser libsodium . Je vais d'abord expliquer pourquoi, puis comment.

Pourquoi pas SJCL, CryptoJS, WebCrypto, etc.

Réponse courte : Pour que votre chiffrement soit réellement sûr, ces bibliothèques vous demandent de faire trop de choix, par exemple le mode de chiffrement par blocs (CBC, CTR, GCM) ; si vous ne pouvez pas dire lequel des trois que je viens de citer est sûr à utiliser et sous quelles contraintes, vous ne devriez pas avoir à faire ce genre de choix. du tout ).

A moins que votre titre de poste soit ingénieur en cryptographie les chances sont minces pour que vous l'implémentiez en toute sécurité.

Pourquoi éviter CryptoJS ?

CryptoJS offre une poignée de blocs de construction et attend de vous que vous sachiez comment les utiliser en toute sécurité. Il passe même par défaut en mode CBC ( archivé ).

Pourquoi le mode CBC est-il mauvais ?

Lire cet article sur les vulnérabilités de l'AES-CBC .

Pourquoi éviter WebCrypto ?

WebCrypto est une norme de type potluck, conçue par un comité, à des fins qui sont orthogonales à l'ingénierie de la cryptographie. Plus précisément, WebCrypto était destiné à remplacer Flash, pas à assurer la sécurité. .

Pourquoi éviter SJCL ?

L'API publique et la documentation de SJCL supplient les utilisateurs de chiffrer les données avec un mot de passe mémorisé par l'homme. C'est rarement, voire jamais, ce que vous voulez faire dans le monde réel.

En outre : Son nombre de tours PBKDF2 par défaut est d'environ 86 fois plus petit que vous ne le souhaitez . AES-128-CCM est probablement parfait.

Parmi les trois options ci-dessus, SJCL est la moins susceptible de se terminer en larmes. Mais il y a de meilleures options disponibles.

Pourquoi le Libsodium est-il meilleur ?

Vous n'avez pas besoin de choisir entre un menu de modes de chiffrement, de fonctions de hachage et d'autres options inutiles. Vous n'aurez jamais à risque de bousiller vos paramètres et d'enlever toute sécurité à votre protocole .

Au lieu de cela, libsodium ne vous propose que des options simples, conçues pour une sécurité maximale et des API minimalistes.

  • crypto_box() / crypto_box_open() offrent un cryptage à clé publique authentifié.
    • L'algorithme en question combine X25519 (ECDH sur Curve25519) et XSalsa20-Poly1305, mais il n'est pas nécessaire de le savoir (ni même de s'en soucier) pour l'utiliser de manière sécurisée.
  • crypto_secretbox() / crypto_secretbox_open() offrent un cryptage authentifié à clé partagée.
    • L'algorithme en question est XSalsa20-Poly1305, mais vous n'avez pas besoin de le savoir ou de vous en soucier.

De plus, libsodium a des liaisons dans des dizaines de langages de programmation populaires donc il est très probable que libsodium juste travailler lorsqu'on essaie d'interopérer avec une autre pile de programmation. De plus, libsodium a tendance à être très rapide sans sacrifier la sécurité.

Comment utiliser Libsodium en JavaScript ?

D'abord, vous devez décider d'une chose :

  1. Voulez-vous simplement crypter/décrypter des données (et peut-être encore utiliser le texte en clair dans des requêtes de base de données en toute sécurité) et ne pas vous soucier des détails ? Ou bien...
  2. Avez-vous besoin de mettre en œuvre un protocole spécifique ?

Si vous avez choisi la première option , obtenir CipherSweet.js .

La documentation est disponible en ligne . EncryptedField est suffisante pour la plupart des cas d'utilisation, mais la EncryptedRow y EncryptedMultiRows Les API peuvent être plus faciles si vous avez beaucoup de champs distincts à crypter.

Avec CipherSweet, vous n'avez pas besoin de même savoir ce qu'est un nonce/IV pour l'utiliser en toute sécurité.

En outre, cela permet de traiter int / float le cryptage sans fuite de données sur le contenu par la taille du texte chiffré.

Sinon, vous voudrez sodium-plus , qui est un frontal convivial pour divers wrappers libsodium. Sodium-Plus vous permet d'écrire du code performant, asynchrone, multiplateforme, facile à auditer et à raisonner.

Pour installer sodium-plus, il suffit d'exécuter...

npm install sodium-plus

Il n'y a actuellement aucun CDN public pour le support du navigateur. Cela changera bientôt. Cependant, vous pouvez récupérer sodium-plus.min.js de la dernière version de Github si vous en avez besoin.

const { SodiumPlus } = require('sodium-plus');
let sodium;

(async function () {
    if (!sodium) sodium = await SodiumPlus.auto();
    let plaintext = 'Your message goes here';
    let key = await sodium.crypto_secretbox_keygen();
    let nonce = await sodium.randombytes_buf(24);
    let ciphertext = await sodium.crypto_secretbox(
        plaintext,
        nonce,
        key    
    );
    console.log(ciphertext.toString('hex'));

    let decrypted = await sodium.crypto_secretbox_open(
        ciphertext,
        nonce,
        key
    );

    console.log(decrypted.toString());
})();

La documentation pour sodium-plus est disponible sur Github.

Si vous voulez un tutoriel étape par étape, cet article de dev.to a ce que vous cherchez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X