We had a string
with byte array
(hexadecimal) sequence, like: "0x65,0x31,0xb6,0x9e,0xaf,0xd2,0x39,0xc9,0xad,0x07,0x78,0x99,0x73,0x52,0x91,0xf5,0x93,0x1a,0x49,0xc6"
and we need to recovery this sequence to byte array
again.
We are using the following approach:
string byteSequence = "0x65,0x31,0xb6,0x9e,0xaf,0xd2,0x39,0xc9,0xad,0x07,0x78,0x99,0x73,0x52,0x91,0xf5,0x93,0x1a,0x49,0xc6";
byte[] myBytes = stringByteSequence.Split(',').Select(s => Convert.ToByte(s, 16)).ToArray();
This hash sequence it been generated by this sample:
string password = "<your password here>";
using (var cryptoProvider = System.Security.Cryptography.SHA1.Create())
{
byte[] passwordHash = cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(password));
string result = "new byte[] { " +
String.Join(",", passwordHash.Select(x => "0x" + x.ToString("x2")).ToArray())
+ " } ";
//...
// result = "new byte[] { 0x65,0x31,0xb6,0x9e,0xaf,0xd2,0x39,0xc9,0xad,0x07,0x78,0x99,0x73,0x52,0x91,0xf5,0x93,0x1a,0x49,0xc6 }"
//...
}
Is there a "cleaner" way to do this conversion?
Illustrative code, like:
byte[] myBytes = byteSequence.Which.Method.I.Can.Use.To.Convert.It.To.Byte.Array.Again?();
Original sample (referenced link above):
new BasicAuthAuthorizationUser
{
Login = "Administrator-2",
// Password as SHA1 hash
Password = new byte[]{0xa9,
0x4a, 0x8f, 0xe5, 0xcc, 0xb1, 0x9b,
0xa6, 0x1c, 0x4c, 0x08, 0x73, 0xd3,
0x91, 0xe9, 0x87, 0x98, 0x2f, 0xbb,
0xd3}
}
Our main idea:
new BasicAuthAuthorizationUser
{
Login = "Administrator-2",
// Password as SHA1 hash
Password = configuration["MY_ENV_VAR_NAME"].Split(',').Select(s => Convert.ToByte(s, 16)).ToArray();
}
-
2\$\begingroup\$ Please note that your edits seem to be responding directly to the answers provided. We take answer invalidation quite seriously here, so please make sure the answers still make sense after your edits. \$\endgroup\$Mast– Mast ♦2022年03月17日 15:02:49 +00:00Commented Mar 17, 2022 at 15:02
-
1\$\begingroup\$ Please do not edit the question, especially the code, after an answer has been posted. Changing the question may cause answer invalidation. Everyone needs to be able to see what the reviewer was referring to. What to do after the question has been answered. \$\endgroup\$pacmaninbw– pacmaninbw ♦2022年03月17日 16:26:57 +00:00Commented Mar 17, 2022 at 16:26
-
\$\begingroup\$ All right np! But the "edited code" do not change the main objective of question. Please read the first version of question and compare with the only remaining "answer" and tell me if this answer make sense... \$\endgroup\$Igor– Igor2022年03月17日 16:36:17 +00:00Commented Mar 17, 2022 at 16:36
-
\$\begingroup\$ Whyy downvoted? \$\endgroup\$Igor– Igor2022年03月17日 18:48:47 +00:00Commented Mar 17, 2022 at 18:48
1 Answer 1
Not sure why are you storing the hexadecimal hash like that, if you can just use plain hexadecimal it would be more readable and would prevent from adding unnecessary work.
For your current work, you can use extension methods to convert from hexadecimal string to bytes, and vise versa.
public static class Extensions
{
public static string ToHexadecimalSeparatedString(this byte[] bytes) => bytes != null ? string.Join(",", bytes.Select(x => $"0x{x:X2}")) : null;
public static byte[] FromHexadecimalSeparatedString(this string hexadecimal)
{
if (string.IsNullOrWhiteSpace(hexadecimal)) return null;
return hexadecimal.Split(',').Select(x=> Convert.ToByte(x, 16)).ToArray();
}
}
usage :
string byteSequence = "0x65,0x31,0xb6,0x9e,0xaf,0xd2,0x39,0xc9,0xad,0x07,0x78,0x99,0x73,0x52,0x91,0xf5,0x93,0x1a,0x49,0xc6";
byte[] bytes = byteSequence.FromHexadecimalSeparatedString();
string hexadecimal = bytes.ToHexadecimalSeparatedString();
so in your sample would be :
new BasicAuthAuthorizationUser
{
Login = "Administrator-2",
// Password as SHA1 hash
Password = configuration["MY_ENV_VAR_NAME"].FromHexadecimalSeparatedString()
}
Although, I'm still not convinced of the way that hexadecimal is stored, if you planning to revert it to plain hexadecimal (no separators, and no hexadecimal prefix) then you might be interested in using the following extensions :
public static class Extensions
{
public static string ToHexadecimal(this byte[] bytes) => bytes != null ? string.Concat(bytes.Select(x => $"{x:X2}")) : null;
public static byte[] FromHexadecimal(this string hexadecimal, string separater = null)
{
if(string.IsNullOrWhiteSpace(hexadecimal)) return null;
if(!string.IsNullOrWhiteSpace(separater))
{
hexadecimal = hexadecimal.Replace(separater, string.Empty);
}
var temp = hexadecimal.Replace("0x", string.Empty);
byte[] bytes = new byte[temp.Length / 2];
for (int i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(temp.Substring(i * 2, 2), 16);
}
return bytes;
}
}
the following part is just for backward compatibility, to support the hashes that were already stored with separators. If all stored hashes are plain (no separators, no hexadecimal prefix) then, you can drop that part.
if(!string.IsNullOrWhiteSpace(separater))
{
hexadecimal = hexadecimal.Replace(separater, string.Empty);
}
var temp = hexadecimal.Replace("0x", string.Empty);
-
\$\begingroup\$ Hey @iSR5 thanks for your time! The extension method is not the mais objetive. The main objetive is another "algorithm" to make the reverse conversion (string sequence to byte). \$\endgroup\$Igor– Igor2022年03月19日 00:32:59 +00:00Commented Mar 19, 2022 at 0:32
-
\$\begingroup\$ When you say "Not sure why are you storing the hexadecimal hash like that, if you can just use plain hexadecimal it would be more readable and would prevent from adding unnecessary work." What the better form to make it (store)? To avoid in "hard code"? The library (Hangfire) "requires" SHA1 formated byte array hexadecimal. \$\endgroup\$Igor– Igor2022年03月19日 00:36:18 +00:00Commented Mar 19, 2022 at 0:36
-
\$\begingroup\$ In this cenario, we only store the "string byte sequence" generated by code semple:
cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(password))...
(at the body of question) and after useJoins
. This method has been created by "Hangfire" library creators. \$\endgroup\$Igor– Igor2022年03月19日 00:48:00 +00:00Commented Mar 19, 2022 at 0:48 -
1\$\begingroup\$ @Igor the better form would be either storing the original hash bytes (no conversion to string) or convert it to hexadecimal if needs to be stored as string (use
ToHexadecimal
). TheHangfire
seems to only requiresbyte[]
inPassword
property, so using the hash bytes that generated fromComputeHash
withPassword
property would be enough. It's been done also in the source code take a look atPasswordClear
property github.com/HangfireIO/Hangfire.Dashboard.Authorization/blob/… \$\endgroup\$iSR5– iSR52022年03月19日 11:07:05 +00:00Commented Mar 19, 2022 at 11:07 -
1\$\begingroup\$ @Igor I've never thought about it, however, doing direct
Select
usingLINQ
won't do the job. But you could useEnumerable.Range
instead. with something likeEnumerable.Range(0, hex.Length / 2).Select(x => Convert.ToByte(hex.Substring(x * 2, 2), 16)).ToArray();
\$\endgroup\$iSR5– iSR52022年03月30日 14:22:54 +00:00Commented Mar 30, 2022 at 14:22