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 ?

28voto

richardtallent Points 17534

Les navigateurs modernes prennent désormais en charge la fonction crypto.subtle qui fournit des fonctions de cryptage et de décryptage natives (asynchrones, pas moins !) utilisant l'une de ces méthodes : AES-CBC, AES-CTR, AES-GCM, ou RSA-OAEP.

https://www.w3.org/TR/WebCryptoAPI/#dfn-Crypto

10voto

Liang Ng Points 115

Crypt.subtil AES-GCM, autonome, testé :

async function aesGcmEncrypt(plaintext, password)

async function aesGcmDecrypt(ciphertext, password) 

https://gist.github.com/chrisveness/43bcda93af9f646d083fad678071b90a

8voto

Jose A Points 978

Avant de mettre en œuvre tout ceci, veuillez consulter La réponse de Scott Arciszewski .

Je veux que tu sois très prudent avec ce que je suis sur le point de partager, car je n'ai que peu ou pas de connaissances en matière de sécurité (il y a de fortes chances que j'utilise mal l'API ci-dessous). mettre à jour cette réponse avec l'aide de la communauté .

Comme @richardtallent l'a mentionné dans son respuesta Dans le cadre de l'utilisation de l'API Web Crypto, il existe un support pour l'API Web Crypto, cet exemple utilise donc la norme. Au moment où nous écrivons ces lignes, il existe une 95,88% des navigateurs mondiaux sont supportés .

Je vais vous présenter un exemple utilisant l'API Crypto Web.

Avant de poursuivre, veuillez noter ( Citation de MDN ):

Cette API fournit un certain nombre de primitives cryptographiques de bas niveau. Elle est il est très facile de les utiliser à mauvais escient et le pièges impliqués peuvent être très subtile .

Même en supposant que vous utilisiez correctement les fonctions cryptographiques de base, la gestion sécurisée des clés et la conception globale du système de sécurité sont des éléments essentiels. extrêmement difficile à obtenir et sont généralement le domaine des experts en sécurité.

Des erreurs dans la conception et la mise en œuvre du système de sécurité peuvent rendre la sécurité du système totalement inefficace.

Si vous n'êtes pas sûr de savoir ce que vous faites, vous ne devriez probablement pas utiliser cette API. .

Je respecte beaucoup la sécurité, et j'ai même mis en gras des parties supplémentaires de MDN... Vous avez été prévenu

Maintenant, l'exemple concret...


JSFiddle :

Trouvé ici : https://jsfiddle.net/superjose/rm4e0gqa/5/

Note :

Notez l'utilisation de await mots-clés. Utilisez-le à l'intérieur d'un async ou utiliser .then() y .catch() .

Générer la clé :

// https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey
// https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams
// https://github.com/diafygi/webcrypto-examples#rsa-oaep---generatekey
    const stringToEncrypt = 'https://localhost:3001';
    // https://github.com/diafygi/webcrypto-examples#rsa-oaep---generatekey
    // The resultant publicKey will be used to encrypt
    // and the privateKey will be used to decrypt. 
    // Note: This will generate new keys each time, you must store both of them in order for 
    // you to keep encrypting and decrypting.
    //
    // I warn you that storing them in the localStorage may be a bad idea, and it gets out of the scope
    // of this post. 
    const key = await crypto.subtle.generateKey({
      name: 'RSA-OAEP',
      modulusLength: 4096,
      publicExponent:  new Uint8Array([0x01, 0x00, 0x01]),
      hash: {name: 'SHA-512'},

    }, true,
    // This depends a lot on the algorithm used
    // Go to https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto
    // and scroll down to see the table. Since we're using RSA-OAEP we have encrypt and decrypt available
    ['encrypt', 'decrypt']);

    // key will yield a key.publicKey and key.privateKey property.

Cryptage :

    const encryptedUri = await crypto.subtle.encrypt({
      name: 'RSA-OAEP'
    }, key.publicKey, stringToArrayBuffer(stringToEncrypt))

    console.log('The encrypted string is', encryptedUri);

Décryptage

   const msg = await  crypto.subtle.decrypt({
      name: 'RSA-OAEP',
    }, key.privateKey, encryptedUri);
    console.log(`Derypted Uri is ${arrayBufferToString(msg)}`)

Convertir ArrayBuffer en String (fait en TypeScript) :

  private arrayBufferToString(buff: ArrayBuffer) {
    return String.fromCharCode.apply(null, new Uint16Array(buff) as unknown as number[]);
  }

  private stringToArrayBuffer(str: string) {
    const buff = new ArrayBuffer(str.length*2) // Because there are 2 bytes for each char.
    const buffView = new Uint16Array(buff);
    for(let i = 0, strLen = str.length; i < strLen; i++) {
      buffView[i] = str.charCodeAt(i);
    }
    return buff;
  }

Vous pouvez trouver d'autres exemples ici (je ne suis pas le propriétaire) : // https://github.com/diafygi/webcrypto-examples

7voto

Yazan Najjar Points 531

Vous pouvez utiliser ces fonctions, c'est très facile, la première pour le cryptage, il suffit d'appeler la fonction et d'envoyer le texte que vous voulez crypter et prendre le résultat de la fonction encryptWithAES et l'envoyer à la fonction de décryptage comme ceci :

const CryptoJS = require("crypto-js");

   //The Function Below To Encrypt Text
   const encryptWithAES = (text) => {
      const passphrase = "My Secret Passphrase";
      return CryptoJS.AES.encrypt(text, passphrase).toString();
    };
    //The Function Below To Decrypt Text
    const decryptWithAES = (ciphertext) => {
      const passphrase = "My Secret Passphrase";
      const bytes = CryptoJS.AES.decrypt(ciphertext, passphrase);
      const originalText = bytes.toString(CryptoJS.enc.Utf8);
      return originalText;
    };

  let encryptText = encryptWithAES("YAZAN"); 
  //EncryptedText==>  //U2FsdGVkX19GgWeS66m0xxRUVxfpI60uVkWRedyU15I= 

  let decryptText = decryptWithAES(encryptText);
  //decryptText==>  //YAZAN

4voto

CryptoJS n'est plus supporté. Si vous voulez continuer à l'utiliser, vous pouvez passer à cette url :

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>

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