2013-01-08 23 views
5

mogę dokonać HMAC przy użyciu następujących:Jak mogę odszyfrować HMAC?

var encrypt = crypto.createHmac("SHA256", secret).update(string).digest('base64'); 

próbuję odszyfrować zakodowanego HMAC z kluczem:

var decrypt = crypto.createDecipher("SHA256", secret).update(string).final("ascii"); 

Poniższa była nieudana. Jak mogę odszyfrować HMAC za pomocą klucza?

pojawia się następujący błąd:

node-crypto : Unknown cipher SHA256 

crypto.js:155 
    return (new Decipher).init(cipher, password); 
         ^
Error: DecipherInit error 

Odpowiedz

28

HMAC jest MAC/nadwozia hash, a nie szyfr. Nie jest przeznaczony do odszyfrowania. Jeśli chcesz zaszyfrować coś, użyj szyfru, takiego jak AES, najlepiej w trybie uwierzytelnionym, takim jak AES-GCM.

Jedynym sposobem na "odszyfrowanie" jest zgadywanie całego wejścia, a następnie porównanie danych wyjściowych.

+3

Nawet wtedy, nie można odszyfrować ponieważ wiele kluczy może hash do ta sama wartość. Hash jest funkcją jednokierunkową. Aby uzyskać więcej informacji: http://en.wikipedia.org/wiki/Hash_function –

+3

@JustinEthier W wielu przypadkach przestrzeń wejściowa jest na tyle mała, że ​​zgaduje. W praktyce nigdy nie zgadniesz błędnego wejścia z poprawnym hashem. Albo zgadniesz poprawne dane wejściowe, albo nie znajdziesz pasującego wejścia w ogóle. | Ale ponieważ HMAC jest kluczowany, tylko ci, którzy znają klucz, mogą użyć tego ataku na odgadywanie, więc zwykle nie jest to problemem (z haszowanymi hasłami odgadywanie danych wejściowych jest często problemem). – CodesInChaos

+0

Hmm, prawda, posunąłem się naprzód od tego komentarza, niszcząc go. –

1

Jak już zostało powiedziane przez CodesInChaos, HMAC z SHA256 może być używany tylko do mieszania wartości, która jest tylko w jedną stronę. Jeśli chcesz mieć możliwość szyfrowania/odszyfrowywania, będziesz musiał użyć szyfru, takiego jak aes lub .

przykład jak szyfrowanie/deszyfrowanie:

const crypto = require("crypto"); 

// key and iv 
var key = crypto.createHash("sha256").update("OMGCAT!", "ascii").digest(); 
var iv = "123456789"; 

// this is the string we want to encrypt/decrypt 
var secret = "ermagherd"; 

console.log("Initial: %s", secret); 

// create a aes256 cipher based on our password 
var cipher = crypto.createCipheriv("aes-256-cbc", key, iv); 
// update the cipher with our secret string 
cipher.update(secret, "ascii"); 
// save the encryption as base64-encoded 
var encrypted = cipher.final("base64"); 

console.log("Encrypted: %s", encrypted); 

// create a aes267 decipher based on our password 
var decipher = crypto.createDecipheriv("aes-256-cbc", key, iv); 
// update the decipher with our encrypted string 
decipher.update(encrypted, "base64"); 

console.log("Decrypted: %s", decipher.final("ascii")); 

Uwaga: Musisz zapisać szyfr/rozszyfrować do własnej zmiennej, a także upewnić się, że nie do łańcucha .final po .update.

Jeśli chcesz wiedzieć, jakie są dostępne szyfrów w systemie, należy użyć następującego polecenia:

openssl list-cipher-algorithm 
+0

Który tryb łączenia działa? Brak soli/iv też jest dziwny. – CodesInChaos

+0

@ CodesInChaos '.update' nie zwraca obiektu Cipher, więc nie możesz zrobić' .update (data) .final() 'jak w jego przykładzie. Brak soli/iv nie jest dziwny? Trzeba by użyć do tego '.createCipheriv' i' .createDecipheriv'. – mekwall

+2

Poprosiłem o tryb szyfrowania.Nie można po prostu szyfrować danych za pomocą AES, potrzebny jest tryb łączenia i tryb wypełnienia. Na przykład EBC, CBC, GCM, ... są typowymi trybami łączenia. EBC jest zepsuty, a podczas korzystania z CBC zwykle musisz dodać uwierzytelnienie samodzielnie, czego nie zrobiłeś. | Szyfrowanie za pomocą hasła i bez soli jest dziwne. O ile interfejs API nie tworzy wewnętrznej soli dla każdego połączenia, jest to słabość zabezpieczeń. | Więc twój kod ma duże szanse na brak bezpieczeństwa przy użyciu złego trybu lub braku soli/IV. – CodesInChaos

8

znowu powtórzyć skróty nie są przeznaczone do odszyfrowane. Jednak po uzyskaniu skrótu możesz sprawdzić, czy dowolny ciąg jest równy temu hashowi, umieszczając go za pomocą tego samego szyfrowania z tym samym sekretem.

var crypto = require('crypto') 

var secret = 'alpha' 
var string = 'bacon' 

var hash = crypto.createHmac('SHA256', secret).update(string).digest('base64'); 
// => 'IbNSH3Lc5ffMHo/wnQuiOD4C0mx5FqDmVMQaAMKFgaQ=' 

if (hash === crypto.createHmac('SHA256', secret).update(string).digest('base64')) { 
    console.log('match') // logs => 'match' 
} else { 
    console.log('no match') 
} 

Wydaje się oczywiste, ale bardzo potężne.

+1

Ta odpowiedź zasługuje na więcej miłości. Pozostałe odpowiedzi rozchodzą się i mówią o szyfrowaniu, podczas gdy to ładnie wyjaśnia, w jaki sposób powinien zostać użyty sam HMAC. – Zaccone

+1

Należy używać funkcji porównania, która nie powoduje wycieku liczby znaków zgodnych z taktowaniem. – CodesInChaos

0

Clean-up kodu dla minimalistycznym View i usunięcie bałaganu: uwaga: Iife runnable w węźle repl „jak jest”

!function(){ 

const crypto = require("crypto"); 

// key 
var key = crypto.createHash("sha256").digest(); 


// this is the string we want to encrypt/decrypt 
var secret = "ermagherd"; 

console.log("Initial: %s", secret); 

// create a aes256 cipher based on our password 
var cipher = crypto.createCipher("aes-256-cbc", key); 

// update the cipher with our secret string 
cipher.update(secret); 

// save the encryption 
var encrypted = cipher.final(); 

console.log("Encrypted: %s", encrypted); 

// create a aes267 decipher based on our password 
var decipher = crypto.createDecipher("aes-256-cbc", key); 

// update the decipher with our encrypted string 
decipher.update(encrypted); 

console.log("Decrypted: %s", decipher.final()); //default is utf8 encoding final("utf8") not needed for default 

}() 

/* REPL Output 

      Initial: ermagherd 
    Encrypted: T)��l��Ʀ��,�' 
    Decrypted: ermagherd 
    true 
*/ 
Powiązane problemy