web-dev-qa-db-fra.com

Comment puis-je hacher une chaîne avec SHA256 en JS?

La description

Je cherche à hacher une chaîne localement avec SHA256 en JavaScript. Je regarde autour de toi en pensant qu'il y aurait une sorte de bibliothèque ou de fonction officielle, mais tout ce que j'ai trouvé étaient des charges de projets différents, chacun avec des scripts différents, et je ne suis pas si sûr des scripts de confiance (comme je ne suis pas un expert et certainement non qualifié pour les évaluer) ou comment les mettre en œuvre. EDIT : J'ai besoin de la sortie dans le texte, pas d'hexes, désolé si je n'ai pas expliqué cela lors de la postion de la question initiale.

Code

Voici ce que j'ai essayé jusqu'à présent:

async function sha256(message) {
  // encode as UTF-8
  const msgBuffer = new TextEncoder('utf-8').encode(message);

  // hash the message
  const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

  // convert ArrayBuffer to Array
  const hashArray = Array.from(new Uint8Array(hashBuffer));

  // convert bytes to hex string
  const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
  console.log(hashHex);
  return hashHex;
}
sha256(passwordInput); 

Sortie de la console:

Non capturé (en promesse) TypeError: impossible de lire la propriété 'Digest' de non définie

Je suis nouveau à JavaScript et je suis ouvert à toutes les suggestions, alors oui.

2
Federico Fusco

Le code est bien. La dernière ligne devrait ressembler à ceci:

var vDigest = await sha256(passwordInput);
1

Cannot read property 'digest' of undefined lorsque vous appelez crypto.subtle.digest implique que subtle n'est pas disponible dans crypto; Par conséquent, digest ne peut pas exister, car son module contenant n'existe pas.
Logiquement alors, crypto.subtle ne doit pas être disponible dans cette portée et, en fait, qui contient de vrai dans le navigateur n'importe où en dehors d'un contexte sécurisé .

Quand un contexte est-il considéré comme sécurisé? - développeur.mozilla.org

Un contexte sera considéré comme sécurisé lorsqu'il est livré de manière sécurisée (ou localement), et lorsqu'il ne peut pas être utilisé pour donner accès aux API sécurisées à un contexte qui n'est pas sécurisé. Dans la pratique, cela signifie que pour une page pour avoir un contexte sécurisé, elle et toutes les pages le long de sa chaîne parent et de sa chaîne d'ouverture doivent avoir été livrées de manière sécurisée.

Par exemple, une page livrée de manière sécurisée sur TLS n'est pas considérée comme un contexte sécurisé s'il possède un document parent ou ancêtre qui n'a pas été livré de manière sécurisée; Sinon, la page serait alors capable d'exposer des API sensibles à l'ancêtre livré de manière sécurisée via PostMessage messages. De même, si un document livré TLS est ouvert dans une nouvelle fenêtre par un contexte non sécurisé sans noopener étant spécifié, la fenêtre ouverte n'est pas considérée comme un contexte sécurisé (puisque l'ouvre-fenêtre et la fenêtre ouverte pourrait communiquer via PostMessage).

Des fichiers livrés localement tels que http: // localhost * et File: // Les chemins sont considérés comme ayant été livrés de manière sécurisée.

|||||Les contextes qui ne sont pas locaux doivent être servis sur https: // ou WSS: // et où les protocoles utilisés ne doivent pas être considérés comme obsolètes .

Dans un contexte sécurisé, votre code fonctionne parfaitement ????


1: Contextes sécurisés - Sécurité Web | MDN
[.____] 2: quand est un contexte considéré comme sécurisé? - contextes sécurisés - Sécurité Web | MDN
[.____] : fenêtre.postMessage () - API Web | MDN
[.____] 4: Fonctionnalités de fonctionnalité de la fenêtre window.open () - API Web | MDN

1
fire

La réponse ci-dessus de Ofundefina a un tas de semi-joints manquants et d'erreurs. J'ai nettoyé le code afin que vous puissiez l'appeler comme une fonction. Je ne sais pas si cela fonctionnera avec des personnages Unicode. Peut-être avoir à convertir Unicode en ASCII normal au travail. Mais, comme l'indique l'article lié ... Cela ne devrait pas être utilisé dans un environnement de production. En outre, il semble que la version originale de ce code prend en charge Unicode alors peut-être qu'il est préférable d'utiliser cela que cette fonction.

L'article d'en haut (qui semble supporter unicode) montre cette fonction différente de la fonction postée ci-dessous ...

https://www.movable-type.co.uk/scripts/sha256.html

Comment utiliser

console.log(sha256('Perry Computer Services'));

[~ # ~] sortie [~ # ~ ~]

89bae4aeb761e42cb71ba6b62305e0980154cf21992c9ab2ab6fc40966ab5bf3

Testé avec PHP HASH - sortie

89bae4aeb761e42cb71ba6b62305e0980154cf21992c9ab2ab6fc40966ab5bf3

Ce n'est pas la fonction complète comme indiqué sur l'autre page liée ci-dessus. Il fonctionne "tel quel" avec des caractères non unicode que vous pouvez voir de mon exemple ci-dessus.

function sha256(ascii) {
    function rightRotate(value, amount) {
        return (value >>> amount) | (value << (32 - amount));
    }
    ;

    var mathPow = Math.pow;
    var maxWord = mathPow(2, 32);
    var lengthProperty = 'length';
    var i, j; // Used as a counter across the whole file
    var result = '';

    var words = [];
    var asciiBitLength = ascii[lengthProperty] * 8;

    //* caching results is optional - remove/add slash from front of this line to toggle
    // Initial hash value: first 32 bits of the fractional parts of the square roots of the first 8 primes
    // (we actually calculate the first 64, but extra values are just ignored)
    var hash = sha256.h = sha256.h || [];
    // Round constants: first 32 bits of the fractional parts of the cube roots of the first 64 primes
    var k = sha256.k = sha256.k || [];
    var primeCounter = k[lengthProperty];
    /*/
     var hash = [], k = [];
     var primeCounter = 0;
     //*/

    var isComposite = {};
    for (var candidate = 2; primeCounter < 64; candidate++) {
        if (!isComposite[candidate]) {
            for (i = 0; i < 313; i += candidate) {
                isComposite[i] = candidate;
            }
            hash[primeCounter] = (mathPow(candidate, .5) * maxWord) | 0;
            k[primeCounter++] = (mathPow(candidate, 1 / 3) * maxWord) | 0;
        }
    }

    ascii += '\x80'; // Append Ƈ' bit (plus zero padding)
    while (ascii[lengthProperty] % 64 - 56)
        ascii += '\x00'; // More zero padding

    for (i = 0; i < ascii[lengthProperty]; i++) {
        j = ascii.charCodeAt(i);
        if (j >> 8)
            return; // ASCII check: only accept characters in range 0-255
        words[i >> 2] |= j << ((3 - i) % 4) * 8;
    }
    words[words[lengthProperty]] = ((asciiBitLength / maxWord) | 0);
    words[words[lengthProperty]] = (asciiBitLength);

    // process each chunk
    for (j = 0; j < words[lengthProperty]; ) {
        var w = words.slice(j, j += 16); // The message is expanded into 64 words as part of the iteration
        var oldHash = hash;
        // This is now the undefinedworking hash", often labelled as variables a...g
        // (we have to truncate as well, otherwise extra entries at the end accumulate
        hash = hash.slice(0, 8);

        for (i = 0; i < 64; i++) {
            var i2 = i + j;
            // Expand the message into 64 words
            // Used below if 
            var w15 = w[i - 15], w2 = w[i - 2];

            // Iterate
            var a = hash[0], e = hash[4];
            var temp1 = hash[7]
                    + (rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25)) // S1
                    + ((e & hash[5]) ^ ((~e) & hash[6])) // ch
                    + k[i]
                    // Expand the message schedule if needed
                    + (w[i] = (i < 16) ? w[i] : (
                            w[i - 16]
                            + (rightRotate(w15, 7) ^ rightRotate(w15, 18) ^ (w15 >>> 3)) // s0
                            + w[i - 7]
                            + (rightRotate(w2, 17) ^ rightRotate(w2, 19) ^ (w2 >>> 10)) // s1
                            ) | 0
                            );
            // This is only used once, so *could* be moved below, but it only saves 4 bytes and makes things unreadble
            var temp2 = (rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22)) // S0
                    + ((a & hash[1]) ^ (a & hash[2]) ^ (hash[1] & hash[2])); // maj

            hash = [(temp1 + temp2) | 0].concat(hash); // We don't bother trimming off the extra ones, they're harmless as long as we're truncating when we do the slice()
            hash[4] = (hash[4] + temp1) | 0;
        }

        for (i = 0; i < 8; i++) {
            hash[i] = (hash[i] + oldHash[i]) | 0;
        }
    }

    for (i = 0; i < 8; i++) {
        for (j = 3; j + 1; j--) {
            var b = (hash[i] >> (j * 8)) & 255;
            result += ((b < 16) ? 0 : '') + b.toString(16);
        }
    }
    return result;
};
0
PerryCS