2016-12-22 15 views
5

Tôi đang sử dụng .net port of libsodium. Chức năng thế hệ băm có hai dạng, một là chấp nhận mảng byte và một trong đó chấp nhận chuỗi:Chuyển đổi mảng byte thành chuỗi và sau đó lại tạo ra các kết quả khác nhau

public static byte[] ArgonHashBinary(string password, string salt, long opsLimit, int memLimit, long outputLength = ARGON_SALTBYTES) 

public static byte[] ArgonHashBinary(byte[] password, byte[] salt, long opsLimit, int memLimit, long outputLength = ARGON_SALTBYTES) 

gì tôi đang gặp một vấn đề với cả hai hình thức là sản xuất các hash tương tự khi các giá trị đầu vào là giống hệt nhau.

var saltAsBytes = PasswordHash.ArgonGenerateSalt(); 
var saltAsString = Encoding.UTF8.GetString(saltAsBytes); 
var tmp = Encoding.UTF8.GetBytes(saltAsString); 

var hash1 = PasswordHash.ArgonHashBinary(password, saltAsString, 6, 134217728, 16); 
var hash2 = PasswordHash.ArgonHashBinary(Encoding.UTF8.GetBytes(password), saltAsBytes, 6, 134217728, 16); 

Bất kỳ thứ gì có "PasswordHash". là libsodium chứ không phải mã của tôi.

Từ mã ở trên khi tôi chuyển đổi từ chuỗi và sau đó quay lại mảng byte mảng byte. Mảng mảng byte luôn có độ dài khác nhau. ArgonGenerateSalt() tạo ra một mảng byte với chiều dài là 16. Khi tôi chuyển đổi nó trở lại từ một chuỗi trên của nó thường ~ 30 (khác nhau mỗi lần vì các muối khác nhau được sản xuất).

Tại sao tôi chuyển sang UTF8? Bởi vì đó là những gì họ đang làm trong nội bộ: https://github.com/adamcaudill/libsodium-net/blob/master/libsodium-net/PasswordHash.cs

public static byte[] ArgonHashBinary(string password, string salt, StrengthArgon limit = StrengthArgon.Interactive, long outputLength = ARGON_SALTBYTES) 
    { 
     return ArgonHashBinary(Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(salt), limit, outputLength); 
    } 

Khi tôi chuyển đổi các muối vào một chuỗi UTF8 chức năng băm sẽ thất bại bởi vì họ đang kiểm tra độ dài của mảng byte để đảm bảo 16 byte của nó. Nếu tôi chuyển đổi nó thành một chuỗi ASCII nó hoạt động nhưng tạo ra một hash khác nhau (được mong đợi).

Để làm rõ phần băm trong mã này không phải là vấn đề. Tìm ra lý do tại sao tmp khác nhau sau đó saltAsBytes là chìa khóa.

+0

Bạn đã đơn bước mã trong 'PasswordHash 'để xem nơi mọi thứ đang đi khác nhau? –

+0

@JimMischel Phần nào?Phần quan trọng nhất ở trên là khi tôi tạo ra muối và sau đó bí mật nó thành một chuỗi và sau đó trở lại một mảng byte. Phần lớn mã đó là của riêng tôi. Chỉ có điều thư viện đang làm là tạo ra muối ngẫu nhiên. Điều gì liên quan nhiều nhất đến biến 'tmp' không giống như 'saltAsBytes'. Vì vậy, tôi không nghĩ rằng điều này có bất cứ điều gì để làm với phần băm. Một khi tôi tìm ra lý do tại sao điều đó xảy ra phần băm có thể sẽ hoạt động. – coding4fun

+0

Bạn có chắc chắn mảng byte chỉ chứa các mã UTF-8 hợp lệ không? Tôi không chắc chắn cách GetBytes() hoạt động, khi mảng chứa các điểm mã không hợp lệ. –

Trả lời

2

Tôi nghĩ rằng vấn đề ở đây là phương pháp ArgonGenerateSalt không trả lại chuỗi được mã hóa UTF8, nó returns completely random bytes.

Bạn không thể giải mã các byte ngẫu nhiên dưới dạng chuỗi UTF8 và mong đợi nó đi vòng. Một ví dụ nhỏ để xem nơi này thổi lên là phải làm như sau:

var data = new byte[] { 128 }; 
var dataAsString = Encoding.UTF8.GetString(data); 
var dataAsBytes = Encoding.UTF8.GetBytes(dataAsString); 

Sau này, dataAsBytes sẽ là 3 byte (cụ thể là 239, 191, 189).

+0

Điều này khiến bạn nghĩ rằng tham số 'muối' cho phiên bản chuỗi 'ArgonHashBinary' không bao giờ có thể được tạo ra bởi thư viện. Bạn phải tự mình tạo ra nó. Nếu đúng thì có vẻ như một thiết kế tồi. – coding4fun

+0

@ coding4fun Điều đó chắc chắn dường như là một sự giám sát đáng kể. – Kyle

2

Chuyển đổi một mảng byte thành chuỗi và sau đó trở lại một lần nữa tạo ra kết quả khác nhau

Một dữ liệu nhị phân có thể không được chuyển đổi sang chuỗi và sau đó trở lại byte mảng sử dụng Encoding.[AnyEncoding].GetBytesEncoding.[AnyEncoding].GetString

Thay vào đó sử dụng Convert.ToBase64StringConvert.FromBase64String

Bạn có thể dễ dàng kiểm tra ...

chiều dài
var bytes = new byte[] { 255, 255, 255 }; 
var buf = Encoding.UTF8.GetString(bytes); 
var newbytes = Encoding.UTF8.GetBytes(buf); 

newbytes 's sẽ là 9 .....

Edit: Đây là trường hợp thử nghiệm cho @Theo

var bytes = new byte[] { 0, 216 }; //any new byte[] { X, 216 }; 
var buf = Encoding.Unicode.GetString(bytes); 
var newbytes = Encoding.Unicode.GetBytes(buf); //253,255 
+0

Trên thực tế đã có suy nghĩ quá trước khi đặt câu hỏi nhưng tiếc là nó không hoạt động. Khi truyền chuỗi tới hàm băm, chiều dài sẽ là! = 16, điều này gây ra ngoại lệ 'SaltOutOfRangeException' xảy ra – coding4fun

+0

@ coding4fun Tôi không hiểu ý bạn là gì nhưng bạn sẽ cần một hàm * đảo ngược * giữa chuỗi và dữ liệu nhị phân phân xử .... Sử dụng mã hóa không đúng cách ... Bạn có các tùy chọn khác như 'BitConverter.ToString' hoặc' SoapHexBinary' Nhưng mã hóa base64 là tự nhiên nhất ... –

+0

@ coding4fun BTW: Bạn nên mã hóa mảng byte của chiều dài 16 và chuyển đổi thành chuỗi Base64 ... Đảo ngược nó sẽ lại là mảng byte 16 byte –

Các vấn đề liên quan