2015-04-01 59 views
0

我有一個由我的網站的內容管理器使用Python編寫的後端應用程序。用戶的密碼使用passlib's pbkdf2_sha512函數進行散列。我開始開發前端應用程序,因此我決定將nodejs與React用於UX原因。如何驗證由Python的Passlib使用Node.js創建的加密哈希?

現在我的問題是我無法弄清楚如何驗證passlib使用nodejs驗證用戶身份的密碼。 Passlib的實現看起來對我來說太具體了,我並不是真的想到隱藏的東西。

我有MCF,所以我知道算法和消化類型,鹽,迭代次數和密鑰長度。我如何在節點中驗證來自passlib的輸出?我應該選擇另一種更好的兩種平臺支持的算法嗎?

回答

1

好吧,我轉向sha512_crypt,而不是找到一個名爲sha512crypt-node的節點的好庫。 README本身包含一個Python和Node的例子,正是我所需要的。這是一個關於體力勞動的小例子。使用這些平臺:

的Python:

from passlib.hash import sha512_crypt 

orig = "password" 
h = sha512_crypt.encrypt(orig) 
print("hash", h) 
# h for eg. is $6$rounds=100000$5YnTXatKh4b1pLjp$3QQjVIfjrbiTakj.wkaw1woAcFiPRAjJP2U/b3BiGW4m8OvI8x0tgw1bb63dNQWMUl1uYNDBcTO3tWgrJ6eHh1 

okay = sha512_crypt.verify(orig, h) 
print("verified", okay) 

節點:

var sha512crypt = require("sha512crypt-node").sha512crypt; 

// origHash is the hash generated by passlib  
var origHash = "$6$rounds=100000$5YnTXatKh4b1pLjp$3QQjVIfjrbiTakj.wkaw1woAcFiPRAjJP2U/b3BiGW4m8OvI8x0tgw1bb63dNQWMUl1uYNDBcTO3tWgrJ6eHh1", 
    parts = origHash.split('$'), 
    rounds = parts[2], 
    salt = '$' + parts[1] + '$' + rounds + '$' + parts[3], 
    password = "password"; 

var hash = sha512crypt(password, salt); 
console.log("verified", hash === origHash); 
0

我們有完全相同的問題,但切換到sha512crypt不是一種選擇。在我們的例子中,密碼是使用安全瓶生成的。以下示例涵蓋了常規passlib和flask-security哈希,它們首先生成一個帶有祕密鹽的HMAC並將其用作pbkdf2-sha512密碼。見下面的代碼。

來源是在GitHub上:https://github.com/badzong/node-verify-flask-security-passwords

var crypto = require('crypto'); 
 
var pbkdf2_sha512 = require('pbkdf2-sha512'); 
 

 
function b64trimmed(buf) { 
 
     return buf.toString('base64').replace(/=*$/, '').replace('+', '.'); 
 
} 
 

 
function b64decode(str) { 
 
     // . in Base64? 
 
     str = str.replace('.', '+'); 
 
     if (str.length % 4) { 
 
       str += '='.repeat(4 - str.length % 4); 
 
     } 
 
     return new Buffer(str, 'base64'); 
 
} 
 

 
function get_hmac(secret, password) { 
 
     var hmac = crypto.createHmac('sha512', secret).update(password).digest('base64'); 
 

 
     return hmac; 
 
} 
 

 
function get_hash(password, salt, rounds) { 
 

 
     // FIXME: KeyLenBytes is hardcoded 
 
     var h = b64trimmed(pbkdf2_sha512(password, salt, rounds, 64)); 
 
     var joined_hash = ['', 'pbkdf2-sha512', rounds, b64trimmed(salt), h].join('$'); 
 

 
     return joined_hash; 
 
} 
 

 
function verify_hash(password, stored_hash) { 
 
     var scheme = stored_hash.split('$')[1]; 
 
     var rounds = stored_hash.split('$')[2]; 
 
     var salt = stored_hash.split('$')[3]; 
 

 
     // FIXME: Maybe throw an exception 
 
     if (scheme !== 'pbkdf2-sha512') { 
 
       return false; 
 
     } 
 

 
     var h = get_hash(password, b64decode(salt), rounds); 
 

 
     return h === stored_hash; 
 
} 
 

 
function new_hash(password, rounds) { 
 

 
     // FIXME: Salt size is hardcoded 
 
     var salt = crypto.randomBytes(16); 
 

 
     return get_hash(password, salt, rounds); 
 
} 
 

 
var password = 'Example Password'; 
 

 
// Usage: 
 
var h = new_hash(password, 20000); 
 
console.log('HASH ' + h); 
 
console.log('VERIFY ' + verify_hash(password, h)); 
 

 
// Usage for passwords generated with flask_security: 
 

 
// SECURITY_PASSWORD_SALT is set in config.py and used by flask-security 
 
var SECURITY_PASSWORD_SALT = 'Many random bytes...'; 
 

 
var password_hmac = get_hmac(SECURITY_PASSWORD_SALT, password); 
 
var h = new_hash(password_hmac, 20000); 
 
console.log('HASH ' + h); 
 
console.log('VERIFY ' + verify_hash(password_hmac, h));