Converting a byte array to a string and then back to different results

I am using the .NET port of libsodium . The hash generation function has two forms: one that accepts byte arrays, and one that accepts strings:

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) 

I am having a problem with both forms producing the same hash when the input values ​​are identical.

 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); 

Anything with "PasswordHash". this is libsodium, not my code.

From the code above, when I convert it from a string and then back to a byte array, an array of bytes. An array of byte arrays always has a different length. ArgonGenerateSalt() creates an array of bytes of length 16. When I convert it from a string above it altogether ~ 30 (each time each time due to getting different salts).

Why am I converting to UTF8? Because this is what they do inside: 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); } 

When I convert the salt to a UTF8 string, the hash function will not work, because they check the length of the byte array to make sure its 16 bytes. If I convert it to an ASCII string, it works, but creates another hash (which is expected).

To clarify the hashing in this code, this is not a problem. Finding out why tmp is different, then saltAsBytes is the key.

+5
source share
2 answers

I think the problem here is that the ArgonGenerateSalt method ArgonGenerateSalt not return a UTF8 encoded string, it returns completely random bytes .

You cannot decode random bytes as a UTF8 string and expect it to be rounded. A trivial example to see where it explodes is to do the following:

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

After that, dataAsBytes will be 3 bytes (in particular, 239, 191, 189).

+2
source

Converting an array of bytes to a string and then backward led to different results

Binary data cannot be converted to a string and then back to a byte array using Encoding.[AnyEncoding].GetBytes and Encoding.[AnyEncoding].GetString

Use Convert.ToBase64String and Convert.FromBase64String instead

You can easily check ...

 var bytes = new byte[] { 255, 255, 255 }; var buf = Encoding.UTF8.GetString(bytes); var newbytes = Encoding.UTF8.GetBytes(buf); 

newbytes length will be 9 .....

Edit: This is a test case for @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 
+2
source

Source: https://habr.com/ru/post/1261733/


All Articles