2015-09-27 21 views
7

Durante la codifica in precedenza ho notato qualcosa di strano su SHA256, in quanto sembra generare più numeri interi di lettere per l'hash. All'inizio ho pensato che stavo solo immaginandolo, quindi ho messo insieme un test rapido per essere sicuro. Sorprendentemente, il mio test sembra dimostrare che SHA256 favorisce i valori interi nell'hash che genera. Voglio sapere perché questo è. Non dovrebbe la differenza tra un indice di hash essere una lettera e un numero essere esattamente lo stesso? Qui è il mio esempio di test:SHA256 preferisce numeri interi?

namespace TestingApp 
{ 
    static class Program 
    { 
     private static string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 
     private static char[] characters = letters.ToCharArray(); 
     private static Random _rng = new Random(); 

     static void Main(string[] args) 
     { 
      int totalIntegers = 0; 
      int totalLetters = 0; 
      for (int testingIntervals = 0; testingIntervals < 3000; testingIntervals++) 
      { 
       string randomString = NextString(10); 
       string checksum = DreamforceChecksum.GenerateSHA256(randomString); 
       int integerCount = checksum.Count(Char.IsDigit); 
       int letterCount = checksum.Count(Char.IsLetter); 
       Console.WriteLine("String: " + randomString); 
       Console.WriteLine("Checksum: " + checksum); 
       Console.WriteLine("Integers: " + integerCount); 
       Console.WriteLine("Letters: " + letterCount); 
       totalIntegers += integerCount; 
       totalLetters += letterCount; 
      } 
      Console.WriteLine("Total Integers: " + totalIntegers); 
      Console.WriteLine("Total Letters: " + totalLetters); 
      Console.Read(); 
     } 

     private static string NextString(int length) 
     { 
      StringBuilder builder = new StringBuilder(); 
      for (int i = 0; i < length; i++) 
      { 
       builder.Append(characters[_rng.Next(characters.Length)]); 
      } 
      return builder.ToString(); 
     } 
    } 
} 

e la mia classe checksum/hash:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Security.Cryptography; 
using System.Text; 
using System.Threading.Tasks; 

namespace DreamforceFramework.Framework.Cryptography 
{ 
    public static class DreamforceChecksum 
    { 
     private static readonly SHA256Managed _shaManagedInstance = new SHA256Managed(); 
     private static readonly StringBuilder _checksumBuilder = new StringBuilder(); 
     public static string GenerateSHA256(string text) 
     { 
      byte[] bytes = Encoding.UTF8.GetBytes(text); 
      byte[] hash = _shaManagedInstance.ComputeHash(bytes); 
      _checksumBuilder.Clear(); 
      for (int index = 0; index < hash.Length; index++) 
      { 
       _checksumBuilder.Append(hash[index].ToString("x2")); 
      } 
      return _checksumBuilder.ToString(); 
     } 

     public static byte[] GenerateSHA256Bytes(string text) 
     { 
      byte[] bytes = Encoding.UTF8.GetBytes(text); 
      byte[] hash = _shaManagedInstance.ComputeHash(bytes); 
      _checksumBuilder.Clear(); 
      for (int index = 0; index < hash.Length; index++) 
      { 
       _checksumBuilder.Append(hash[index].ToString("x2")); 
      } 
      return Encoding.UTF8.GetBytes(_checksumBuilder.ToString()); 
     } 

     public static bool ValidateDataIntegrity(string data, string targetHashcode) 
     { 
      return GenerateSHA256(data).Equals(targetHashcode); 
     } 
    } 
} 

Ho eseguito la mia prova più volte, e ogni volta sembra che più gli interi vengono generati entro l'hash di lettere . Qui ci sono 3 corse di prova:

enter image description here

enter image description here

enter image description here

Qualcuno sa perché SHA256 sembra favorire numeri al posto di una equa distribuzione di entrambe le lettere e numeri?

+1

SHA-256 (come quasi tutti gli hash) restituisce byte non elaborati. Questi si trasformano in caratteri solo quando applichi una codifica, esadecimale nel tuo caso. La distribuzione dei caratteri è una proprietà di tale codifica. – CodesInChaos

risposta

25

Dato che ci sono 10 cifre e 6 lettere possibili, la proporzione dovrebbe essere all'incirca 10: 6. Questo è giusto in linea con i tuoi risultati.

+0

Ciascuno di 0-9a-f è distribuito uniformemente. – mksteve

+3

Man, come mi sono perso? – Krythic

2

L'output è esadecimale. 0-9 e a-f

Problemi correlati