Byte.Parse (c #): Formatexception sulla stringa esadecimale
-
20-12-2019 - |
Domanda
In realtà sto cercando di implementare un semplice meccanismo di accesso molto semplice per un'app che mi sto sviluppando in Visual C # .NET 2.0 su un dispositivo incorporato. Dopo alcune ricerche, ho trovato sul msdn un campione di codice eseguendo la password hashing:
Come memorizzare le password < / P >.
Sfortunatamente, quando provo a usarlo, quel campione di codice è sollevare una formatexception sulla chiamata a byte.Parse
sulle sottostringhe della stringa esadecimale SaltValue
. Ho davvero problemi a capire perché, dal momento che non ho fatto alcuna modifica al codice.
Ecco il codice:
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Globalization;
private const int SaltValueSize = 4;
private static string GenerateSaltValue()
{
UnicodeEncoding utf16 = new UnicodeEncoding();
if (utf16 != null)
{
// Create a random number object seeded from the value
// of the last random seed value. This is done
// interlocked because it is a static value and we want
// it to roll forward safely.
Random random = new Random(unchecked((int)DateTime.Now.Ticks));
if (random != null)
{
// Create an array of random values.
byte[] saltValue = new byte[SaltValueSize];
random.NextBytes(saltValue);
// Convert the salt value to a string. Note that the resulting string
// will still be an array of binary values and not a printable string.
// Also it does not convert each byte to a double byte.
//Original line :
//string saltValueString = utf16.GetString(saltValue);
//Replaced by :
string saltValueString = utf16.GetString(saltValue, 0, SaltValueSize);
// Return the salt value as a string.
return saltValueString;
}
}
return null;
}
private static string HashPassword(string clearData, string saltValue, HashAlgorithm hash)
{
UnicodeEncoding encoding = new UnicodeEncoding();
if (clearData != null && hash != null && encoding != null)
{
// If the salt string is null or the length is invalid then
// create a new valid salt value.
if (saltValue == null)
{
// Generate a salt string.
saltValue = GenerateSaltValue();
}
// Convert the salt string and the password string to a single
// array of bytes. Note that the password string is Unicode and
// therefore may or may not have a zero in every other byte.
byte[] binarySaltValue = new byte[SaltValueSize];
//FormatException raised here
binarySaltValue[0] = byte.Parse(saltValue.Substring(0, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
binarySaltValue[1] = byte.Parse(saltValue.Substring(2, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
binarySaltValue[2] = byte.Parse(saltValue.Substring(4, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
binarySaltValue[3] = byte.Parse(saltValue.Substring(6, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
//...
//Some more code
//...
}
}
.
Ho solo modificato una riga:
string saltValueString = utf16.GetString(saltValue);
a
string saltValueString = utf16.GetString(saltValue, 0, SaltValueSize);
Poiché la prima versione del metodo non sembra essere disponibile per C # embedded. Ma comunque ho testato senza cambiare questa linea (su un ambiente non incorporato), e stava ancora sollevando una formatexception.
Ho copiato il valore SaltValueSize
da quell'altro campione di codice MSDN (che è correlato):
Come convalidare le password
Il test che solleva l'eccezione:
HashPassword("youpi", null, new SHA1CryptoServiceProvider());
Soluzione
Il problema è nel fatto che il metodo GenerateSaltValue
non restituisce la stringa di numeri esadaci.
Restituisce una stringa di alcuni simboli casuali, che possono o di solito potrebbero non essere simboli esadadi validi - per me ha creato una stringa di ghieroglifi principalmente cinesi che di sicuro non sono parassibili da byte.parrse metodo.
Inoltre, il tuo esempio si estende a Microsoft Commerce Server - I Non ho idea di qualunque sia.
"Soluzione:"
Non sono sicuro che tutti questi esempi vogliono realizzare con queste conversioni di stringa-tohex-tobinary, ma per questo per eseguire con successo il GeneratealtValue dovrebbe essere qualcosa come:
public static string ByteArrayToString(byte[] byteArray)
{
StringBuilder hex = new StringBuilder(byteArray.Length * 2);
foreach (byte b in byteArray)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
// Renamed GenerateSaltValue method
private static string GenerateHexSaltString()
{
Random random = new Random();
// Create an array of random values.
byte[] saltValue = new byte[SaltValueSize];
random.NextBytes(saltValue);
string saltValueString = ByteArrayToString(saltValue);
// Return the salt value as a string.
return saltValueString;
}
.
E il tuo programma "funzionerà", grazie a Come converti la matrice byte in stringa esadecimale e viceversa?
Ma:
- .
- usando casuale per la creazione di sale è una cattiva idea.
- La conversione Tbinary a string-tohex sembra persino peggioratore.
- e altri problemi ...
SO:
Leggi alcuni articoli che rappresentano davvero a C # Password hashing e crittografia, come:
ed essere molto attento durante la ricerca di esempi di codice - potrebbero usare un'altra versione, piattaforma o anche linguaggio. Buona fortuna.