将字节数组转换为字符串,然后再返回,产生不同的结果 [英] Converting a byte array to string and then back again produced different results

查看:170
本文介绍了将字节数组转换为字符串,然后再返回,产生不同的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 .net port of libsodium 一>。哈希生成函数有两种形式,一种接受字节数组和一种接受字符串:

  public static byte [] ArgonHashBinary字符串密码,字符串salt,long opsLimit,int memLimit,long outputLength = ARGON_SALTBYTES)

公共静态字节[] ArgonHashBinary(byte [] password,byte [] salt,long opsLimit,int memLimit,long outputLength = ARGON_SALTBYTES)

我遇到的问题是两种形式在输入时产生相同的散列值是相同的。

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

任何包含PasswordHash的内容。是libsodium而不是我的代码。

从上面的代码中,我将它从字符串转换为字节数组,然后返回到字节数组。字节数组数组总是不同的长度。 ArgonGenerateSalt()产生一个长度为16的字节数组。当我将它从一个大于30的字符串转换回来时(每次都因为生成不同的盐而不同)。

为什么我要转换为UTF8?因为那就是他们在内部做的事情:
https://github.com/adamcaudill/libsodium-net/blob/master/libsodium-net/PasswordHash.cs

  {
return ArgonHashBinary(Encoding.UTF8.GetBytes(password),Encoding .UTF8.GetBytes(salt),limit,outputLength);
}

当我将salt转换为UTF8字符串时,哈希函数将失败,因为它们正在检查字节数组的长度以确保其16个字节。如果我将它转换为ASCII字符串,但它会生成不同的哈希值(这是预期的)。

澄清此代码中的散列片段不是问题。找出为什么 tmp 不同,那么 saltAsBytes 是关键。

将字节数组转换为字符串,然后再返回,产生不同的结果

二进制数据不能转换为字符串,然后使用编码返回字节数组
[AnyEncoding] .GetBytes
编码。[AnyEncoding] .GetString



改用 Convert.ToBase64String Convert.FromBase64String



您可以轻松测试...

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

newbytes 的长度将为9。 ....



编辑:这是@Theo的测试用例

  var bytes = new byte [] {0,216}; //任何新的字节[] {X,216}; 
var buf = Encoding.Unicode.GetString(bytes);
var newbytes = Encoding.Unicode.GetBytes(buf); // 253,255


I'm 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)

What i'm having an issue with is 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." is libsodium and not my code.

From the code above when i convert it from a string and then back to a byte array the byte array. The byte array array is always a different length. ArgonGenerateSalt() produces a byte array with a length of 16. When i convert it back from a string above its generally ~30 (different every time because of different salts produced).

Why am i converting to UTF8? Because thats what they are doing internally: 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 hashing function will fail because they are checking the length of the byte array to make sure its 16 bytes. If i convert it to a ASCII string it works but produces a different hash (which is expected).

To clarify the hashing piece in this code is not the issue. Figuring out why tmp is different then saltAsBytes is the key.

解决方案

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

A binary data may not be converted to string and then back to byte array using Encoding.[AnyEncoding].GetBytes and Encoding.[AnyEncoding].GetString

Instead use Convert.ToBase64String and Convert.FromBase64String

You can easily test...

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

newbytes's length will be 9.....

Edit: This is the 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

这篇关于将字节数组转换为字符串,然后再返回,产生不同的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆