2016-01-22 11 views
5

में एक पीबीकेडीएफ 2-SHA256 पासवर्ड हैश बनाने के लिए कैसे मुझे एक पीबीकेडीएफ 2-SHA256 पासवर्ड हैश बनाने की ज़रूरत है, लेकिन मुझे कुछ परेशानी हो रही है।सी #/बाउंसी कैसल

मैंने Bouncy Castle रेपो डाउनलोड किया, लेकिन यूनिट टेस्ट में जो खोज रहा था उसे ढूंढने में थोड़ा फंस गया।

कुछ नमूना कोड here मिला, लेकिन यह केवल SHA1 करता है। कोड का मुख्य बिट है:

/// <summary> 
/// Computes the PBKDF2-SHA1 hash of a password. 
/// </summary> 
/// <param name="password">The password to hash.</param> 
/// <param name="salt">The salt.</param> 
/// <param name="iterations">The PBKDF2 iteration count.</param> 
/// <param name="outputBytes">The length of the hash to generate, in bytes.</param> 
/// <returns>A hash of the password.</returns> 
private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes) 
{ 
    var pdb = new Pkcs5S2ParametersGenerator(); 
    pdb.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()), salt, 
       iterations); 
    var key = (KeyParameter)pdb.GenerateDerivedMacParameters(outputBytes * 8); 
    return key.GetKey(); 
} 

मुझे इसे SHA1 से SHA256 में बदलने की आवश्यकता है।

जावा प्रलेखन और this post से, ऐसा लगता है कि निम्नलिखित संभव होगा, लेकिन सी # लाइब्रेरी में कन्स्ट्रक्टर पर कोई अधिभार नहीं है।

var pdb = new Pkcs5S2ParametersGenerator(new Sha256Derived()); 

ढेर अतिप्रवाह पर another article ढूँढना, मैंने सोचा निम्नलिखित संभव हो सकता है, लेकिन SHA हैशिंग एल्गोरिदम देखने सूची में नहीं हैं, तो निम्नलिखित काम नहीं करेगा।

var bcparam = (KeyParameter)pdb.GenerateDerivedParameters("sha256", outputBytes * 8); 

मुझे यह काम करने के लिए क्या करने की ज़रूरत है?

नोट: यदि आप इसे पढ़ते हैं और बाउंसी कैसल में नहीं जानते हैं, लेकिन एक और तरीका जानते हैं, तो भी मैं आपकी मदद की सराहना करता हूं।

+0

स्रोत कोड उपलब्ध है। ऐसा क्यों नहीं करते? –

+1

@JamesKPolk - एक वैध टिप्पणी। कारण हैं: ए क्योंकि मुझे यह अच्छी तरह से समझ में नहीं आता है और बी। मुझे लगता है कि एन्क्रिप्शन की बात आती है तो मुझे किसी भी तरह से रोलिंग गंभीर नहीं माना जाता है। हालांकि शायद यह सेटअप के साथ छेड़छाड़ कर रहा है, यह ठीक हो सकता है। मैंने माना कि एक रास्ता होना चाहिए, लेकिन शायद सी # बाउंसीकास्ट जावा संस्करण के पीछे पीछे है और इसमें अभी शामिल नहीं है? यदि वास्तव में सी # में ऐसा करने का कोई तरीका नहीं है तो मैं जावा संस्करण के आधार पर पुल अनुरोध का प्रयास कर सकता हूं और कोड अपडेट कर सकता हूं। वास्तव में कुछ उपलब्ध था जो मैं बस उपयोग कर सकता था। – HockeyJ

उत्तर

7

संपादित (पिछला जवाब इतिहास संक्षिप्तता के लिए निकाला गया)

अब एक Bouncy Castle Crypto API NuGet पैकेज है कि इस्तेमाल किया जा सकता है। वैकल्पिक रूप से, आप सीधे गिटहब से source प्राप्त कर सकते हैं, जो काम करेगा। मुझे NuGet से मानक बाउंसी कैसल मिला था, जिसे लेखन के समय 1.8.1 में अपडेट नहीं किया गया था।

खोजकर्ताओं के लाभ के लिए, यहां हैशिंग के लिए एक सी # सहायक वर्ग है। कई धागे पर परीक्षण किया है और ठीक लगता है। आप को संशोधित करने के लिए

/// <summary> 
/// Contains the relevant Bouncy Castle Methods required to encrypt a password. 
/// References NuGet Package BouncyCastle.Crypto.dll 
/// </summary> 
public class BouncyCastleHashing 
{ 
    private SecureRandom _cryptoRandom; 

    public BouncyCastleHashing() 
    { 
     _cryptoRandom = new SecureRandom(); 
    } 

    /// <summary> 
    /// Random Salt Creation 
    /// </summary> 
    /// <param name="size">The size of the salt in bytes</param> 
    /// <returns>A random salt of the required size.</returns> 
    public byte[] CreateSalt(int size) 
    { 
     byte[] salt = new byte[size]; 
     _cryptoRandom.NextBytes(salt); 
     return salt; 
    } 

    /// <summary> 
    /// Gets a PBKDF2_SHA256 Hash (Overload) 
    /// </summary> 
    /// <param name="password">The password as a plain text string</param> 
    /// <param name="saltAsBase64String">The salt for the password</param> 
    /// <param name="iterations">The number of times to encrypt the password</param> 
    /// <param name="hashByteSize">The byte size of the final hash</param> 
    /// <returns>A base64 string of the hash.</returns> 
    public string PBKDF2_SHA256_GetHash(string password, string saltAsBase64String, int iterations, int hashByteSize) 
    { 
     var saltBytes = Convert.FromBase64String(saltAsBase64String); 

     var hash = PBKDF2_SHA256_GetHash(password, saltBytes, iterations, hashByteSize); 

     return Convert.ToBase64String(hash); 
    } 

    /// <summary> 
    /// Gets a PBKDF2_SHA256 Hash (CORE METHOD) 
    /// </summary> 
    /// <param name="password">The password as a plain text string</param> 
    /// <param name="salt">The salt as a byte array</param> 
    /// <param name="iterations">The number of times to encrypt the password</param> 
    /// <param name="hashByteSize">The byte size of the final hash</param> 
    /// <returns>A the hash as a byte array.</returns> 
    public byte[] PBKDF2_SHA256_GetHash(string password, byte[] salt, int iterations, int hashByteSize) 
    { 
     var pdb = new Pkcs5S2ParametersGenerator(new Org.BouncyCastle.Crypto.Digests.Sha256Digest()); 
     pdb.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()), salt, 
        iterations); 
     var key = (KeyParameter)pdb.GenerateDerivedMacParameters(hashByteSize * 8); 
     return key.GetKey(); 
    } 

    /// <summary> 
    /// Validates a password given a hash of the correct one. (OVERLOAD) 
    /// </summary> 
    /// <param name="password">The original password to hash</param> 
    /// <param name="salt">The salt that was used when hashing the password</param> 
    /// <param name="iterations">The number of times it was encrypted</param> 
    /// <param name="hashByteSize">The byte size of the final hash</param> 
    /// <param name="hashAsBase64String">The hash the password previously provided as a base64 string</param> 
    /// <returns>True if the hashes match</returns> 
    public bool ValidatePassword(string password, string salt, int iterations, int hashByteSize, string hashAsBase64String) 
    { 
     byte[] saltBytes = Convert.FromBase64String(salt); 
     byte[] actualHashBytes = Convert.FromBase64String(hashAsBase64String); 
     return ValidatePassword(password, saltBytes, iterations, hashByteSize, actualHashBytes); 
    } 

    /// <summary> 
    /// Validates a password given a hash of the correct one (MAIN METHOD). 
    /// </summary> 
    /// <param name="password">The password to check.</param> 
    /// <param name="correctHash">A hash of the correct password.</param> 
    /// <returns>True if the password is correct. False otherwise.</returns> 
    public bool ValidatePassword(string password, byte[] saltBytes, int iterations, int hashByteSize, byte[] actualGainedHasAsByteArray) 
    { 
     byte[] testHash = PBKDF2_SHA256_GetHash(password, saltBytes, iterations, hashByteSize); 
     return SlowEquals(actualGainedHasAsByteArray, testHash); 
    } 

    /// <summary> 
    /// Compares two byte arrays in length-constant time. This comparison 
    /// method is used so that password hashes cannot be extracted from 
    /// on-line systems using a timing attack and then attacked off-line. 
    /// </summary> 
    /// <param name="a">The first byte array.</param> 
    /// <param name="b">The second byte array.</param> 
    /// <returns>True if both byte arrays are equal. False otherwise.</returns> 
    private bool SlowEquals(byte[] a, byte[] b) 
    { 
     uint diff = (uint)a.Length^(uint)b.Length; 
     for (int i = 0; i < a.Length && i < b.Length; i++) 
      diff |= (uint)(a[i]^b[i]); 
     return diff == 0; 
    } 

} 

प्रयोग उदाहरण Pkcs5S2ParametersGenerator() के लिए

public void CreatePasswordHash_Single() 
{ 
    int iterations = 100000; // The number of times to encrypt the password - change this 
    int saltByteSize = 64; // the salt size - change this 
    int hashByteSize = 128; // the final hash - change this 

    BouncyCastleHashing mainHashingLib = new BouncyCastleHashing(); 

    var password = "password"; // That's really secure! :) 

    byte[] saltBytes = mainHashingLib.CreateSalt(saltByteSize); 
    string saltString = Convert.ToBase64String(saltBytes); 

    string pwdHash = mainHashingLib.PBKDF2_SHA256_GetHash(password, saltString, iterations, hashByteSize); 

    var isValid = mainHashingLib.ValidatePassword(password, saltBytes, iterations, hashByteSize, Convert.FromBase64String(pwdHash)); 

} 
+0

ने पुष्टि की है कि ऊपर उल्लिखित बाउंसी कैसल क्रिप्टो एपीआई न्यूज पैकेज अब संस्करण 1.8.1 है – kyle

संबंधित मुद्दे