2010-03-22 73 views
0

以下是處理:我將.NET網站移動到Python。我有一個數據庫密碼散列使用System.Security.Cryptography.SHA1Managed實用程序。如何在Python中重現System.Security.Cryptography.SHA1Managed結果

我創建用下面的代碼在.NET中的哈希:

string hashedPassword = Cryptographer.CreateHash("MYHasher", userInfo.Password); 

的MYHasher塊看起來是這樣的:

<add algorithmType="System.Security.Cryptography.SHA1Managed, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=blahblahblah" 
    saltEnabled="true" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=3.0.0.0, Culture=neutral, PublicKeyToken=daahblahdahdah" 
    name="MYHasher" /> 

所以對於一個給定的密碼,我回去和存儲在數據庫中一個48字節的salted sha1。我假設最後8個字節是鹽。我試圖通過執行sha1(鹽+密碼)和sha1(密碼+鹽)來重現python中的哈希過程,但我沒有運氣。

我的問題給你:

  1. 是如何被使用的公鑰?
  2. 如何使用salt重新設置密碼。
  3. 鹽是如何產生的? (例如,當我說saltEnabled =「true」時,會發生什麼額外的魔法?)

我需要不只引用其他.NET庫的具體細節,我正在尋找發生的實際操作邏輯在黑匣子裏。

謝謝!

回答

1

根據this previous thread,這應該是像sha1(密碼+鹽)+鹽的東西。 SHA-1輸出是20個字節,所以對於48個字節,這應該是一個28字節的鹽,而不是8字節的鹽,除非使用某種編碼。

1

當使用string CreateHash(string, string)過載,發生以下情況:

  1. 的字符串使用UTF-16轉換爲字節(使用Encoding.Unicode.GetBytes())。
  2. 生成隨機的16字節鹽。
  3. 將salt附加到轉換後的字符串並進行散列。
  4. 鹽被添加到散列。
  5. 將hash + salt轉換回使用base64的字符串(使用Convert.ToBase64String())。
3

對不起,對於最近的回覆,但我剛剛遇到類似的情況,試圖複製企業庫的密碼塊中使用的SHA1哈希邏輯,但使用Java。

要回答你的每一個問題:

  1. 是如何被使用的公鑰?

    上面配置塊中的PublicKeyToken用於標識一個帶符號的,強名的.net程序集。這是與用於簽署程序集的私鑰對應的公鑰的64位散列。 注意:此密鑰對您的實施散列數據絕對沒有影響。

  2. 如何使用salt重新設置密碼。

    事件序列創建哈希密碼與鹽如下:

    • 呼叫Cryptographer.CreateHash("MYHasher",value); 其中"MYHasher"是在配置塊中指定的配置System.Security.Cryptography.SHA1Managed實例提供者的名稱,並value是要被散列的字符串。

    • 上述方法致電CreateHash(IHashProvider provider, string plaintext),提供解析的IHashProvider。在此方法中,下面的代碼運行:

    
    byte[] bytes = Encoding.Unicode.GetBytes(plaintext); 
    byte[] hash = provider.CreateHash(bytes); 
    CryptographyUtility.GetRandomBytes(bytes); 
    return Convert.ToBase64String(hash); 
    
    
    • 這是在開始時合適的傳遞(也就是現在的plaintext參數)的value參數被轉換爲一個字節數組,使用Unicode編碼。

    • 接下來,使用上面創建的字節數組調用SHA1哈希提供程序的CreateHash(bytes)方法。在此方法中,將發生以下步驟:

    • this.CreateHashWithSalt(plaintext, (byte[]) null);被調用,其中plaintext是包含原始value在堆棧作爲字符串的頂部傳遞的字節數組。第二個參數是salt字節數組(它是null)。在此方法中,下面的代碼被稱爲:

    
    this.AddSaltToPlainText(ref salt, ref plaintext); 
    byte[] hash = this.HashCryptographer.ComputeHash(plaintext); 
    this.AddSaltToHash(salt, ref hash); 
    return hash; 
    
    
    • this.AddSaltToPlainText(ref salt, ref plaintext)是第一個線索提供的文本是如何醃製。在此方法中,下面的代碼運行:
    
    if (!this.saltEnabled) 
        return; 
        if (salt == null) 
        salt = CryptographyUtility.GetRandomBytes(16); 
        plaintext = CryptographyUtility.CombineBytes(salt, plaintext); 
    
    
    • this.saltEnabled變量由saltEnabled="true"在配置塊初始化。如果爲true,並且沒有提供salt,則會爲您生成一個由16個隨機字節組成的字節數組(通過調用外部C API)。
    • plaintext變量然後具有鹽前加它。例如: - [鹽] [明文]

這是要注意的很重要的!

  • 鹽的組合和plaintext然後通過調用this.HashCryptographer.ComputeHash(plaintext); SHA1哈希。這將產生一個20字節長的數組。

  • 然後,鹽再前面前面創建的20字節陣列,通過調用this.AddSaltToHash(salt, ref hash);,給你一個36字節長陣列。

  • 返回堆棧最終會導致您在CreateHash()方法內調用return Convert.ToBase64String(hash);。這將返回提供的SHA1鹽味散列值+鹽的Base64字符串表示形式。

式:的Base64(鹽+ SHA1(鹽+值))

  • 是如何創建的鹽? (例如,當我說saltEnabled = 「真」,有什麼額外的奇蹟發生?)

    這是回答問題2,具體調用CryptographyUtility.GetRandomBytes(16);最終調用C庫:

  • [DllImport("QCall", CharSet = CharSet.Unicode)] private static extern void GetBytes(SafeProvHandle hProv, byte[] randomBytes, int count);

    希望這有助於某種方式!