問題描述
我一直在搞亂 C# Bouncy Castle API 以尋找如何進行 PBKDF2 密鑰派生.
I've being messing around the C# Bouncy Castle API to find how to do a PBKDF2 key derivation.
我現在真的一無所知.
我嘗試閱讀 Pkcs5S2ParametersGenerator.cs 和 PBKDF2Params.cs 文件,但我真的不知道該怎么做.
I tried reading through the Pkcs5S2ParametersGenerator.cs and PBKDF2Params.cs files but i really cant figure out how to do it.
根據我目前所做的研究,PBKDF2 需要一個字符串(或 char[]),即密碼、鹽和迭代次數.
According to the research I have done so far, PBKDF2 requires a string (or char[]) which is the password, a salt and an iteration count.
到目前為止,我最有希望和最明顯的是 PBKDF2Params 和 Pkcs5S2ParametersGenerator.
So far the most promising and most obvious i've come so far is the PBKDF2Params and Pkcs5S2ParametersGenerator.
這些似乎都不接受字符串或 char[].
None of these seems to be accepting a string or a char[].
有沒有人在 C# 中做過這個或對此有任何線索?或者也許有人用 Java 實現了 BouncyCastle 并且可以提供幫助?
Has anyone done this in C# or have any clue about this? Or perhaps someone who has implemented BouncyCastle in Java and can help?
提前感謝很多:)
更新:我在 Bouncy Castle 中找到了如何做到這一點.看看下面的答案:)
UPDATE: I have found how to do this in Bouncy Castle. Look below for answer :)
推薦答案
經過幾個小時的代碼檢查,我發現最簡單的方法是在 Pkcs5S2ParametersGenerator.cs 和創建我自己的課程,當然使用其他 BouncyCastle API.這與 Dot Net Compact Framework (Windows Mobile) 完美配合.這相當于點網緊湊框架 2.0/3.5 中不存在的 Rfc2898DeriveBytes 類.好吧,也許不是確切的等價物,但可以完成工作:)
After hours and hours of going through the code, I found that the easiest way to do this is to take a few parts of the code in Pkcs5S2ParametersGenerator.cs and create my own class which of course use other BouncyCastle API's. This works perfectly with the Dot Net Compact Framework (Windows Mobile). This is the equivalent of Rfc2898DeriveBytes class which is not present in the Dot Net Compact Framework 2.0/3.5. Well, maybe not the EXACT equivalent but does the job :)
這是 PKCS5/PKCS#5
This is PKCS5/PKCS#5
使用的 PRF(偽隨機函數)將是 HMAC-SHA1
The PRF (Pseudo Random Function) which is used will be HMAC-SHA1
第一件事,第一.從 http://www.bouncycastle.org/csharp/ 下載 Bouncy Castle 編譯程序集,添加BouncyCastle.Crypto.dll
作為對您項目的引用.
First things, first. Download the Bouncy Castle compiled assembly from http://www.bouncycastle.org/csharp/, add the BouncyCastle.Crypto.dll
as a reference to your project.
然后使用下面的代碼創建新的類文件.
After that create new class file with the code below.
using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace PBKDF2_PKCS5
{
class PBKDF2
{
private readonly IMac hMac = new HMac(new Sha1Digest());
private void F(
byte[] P,
byte[] S,
int c,
byte[] iBuf,
byte[] outBytes,
int outOff)
{
byte[] state = new byte[hMac.GetMacSize()];
ICipherParameters param = new KeyParameter(P);
hMac.Init(param);
if (S != null)
{
hMac.BlockUpdate(S, 0, S.Length);
}
hMac.BlockUpdate(iBuf, 0, iBuf.Length);
hMac.DoFinal(state, 0);
Array.Copy(state, 0, outBytes, outOff, state.Length);
for (int count = 1; count != c; count++)
{
hMac.Init(param);
hMac.BlockUpdate(state, 0, state.Length);
hMac.DoFinal(state, 0);
for (int j = 0; j != state.Length; j++)
{
outBytes[outOff + j] ^= state[j];
}
}
}
private void IntToOctet(
byte[] Buffer,
int i)
{
Buffer[0] = (byte)((uint)i >> 24);
Buffer[1] = (byte)((uint)i >> 16);
Buffer[2] = (byte)((uint)i >> 8);
Buffer[3] = (byte)i;
}
// Use this function to retrieve a derived key.
// dkLen is in octets, how much bytes you want when the function to return.
// mPassword is the password converted to bytes.
// mSalt is the salt converted to bytes
// mIterationCount is the how much iterations you want to perform.
public byte[] GenerateDerivedKey(
int dkLen,
byte[] mPassword,
byte[] mSalt,
int mIterationCount
)
{
int hLen = hMac.GetMacSize();
int l = (dkLen + hLen - 1) / hLen;
byte[] iBuf = new byte[4];
byte[] outBytes = new byte[l * hLen];
for (int i = 1; i <= l; i++)
{
IntToOctet(iBuf, i);
F(mPassword, mSalt, mIterationCount, iBuf, outBytes, (i - 1) * hLen);
}
//By this time outBytes will contain the derived key + more bytes.
// According to the PKCS #5 v2.0: Password-Based Cryptography Standard (www.truecrypt.org/docs/pkcs5v2-0.pdf)
// we have to "extract the first dkLen octets to produce a derived key".
//I am creating a byte array with the size of dkLen and then using
//Buffer.BlockCopy to copy ONLY the dkLen amount of bytes to it
// And finally returning it :D
byte[] output = new byte[dkLen];
Buffer.BlockCopy(outBytes, 0, output, 0, dkLen);
return output;
}
}
}
那么如何使用這個功能呢?簡單的!:)這是一個非常簡單的示例,其中密碼和鹽由用戶提供.
So how to use this function? Simple! :) This is a very simple example where the password and the salt is provided by the user.
private void cmdDeriveKey_Click(object sender, EventArgs e)
{
byte[] salt = ASCIIEncoding.UTF8.GetBytes(txtSalt.Text);
PBKDF2 passwordDerive = new PBKDF2();
// I want the key to be used for AES-128, thus I want the derived key to be
// 128 bits. Thus I will be using 128/8 = 16 for dkLen (Derived Key Length) .
//Similarly if you wanted a 256 bit key, dkLen would be 256/8 = 32.
byte[] result = passwordDerive.GenerateDerivedKey(16, ASCIIEncoding.UTF8.GetBytes(txtPassword.Text), salt, 1000);
//result would now contain the derived key. Use it for whatever cryptographic purpose now :)
//The following code is ONLY to show the derived key in a Textbox.
string x = "";
for (int i = 0; i < result.Length; i++)
{
x += result[i].ToString("X");
}
txtResult.Text = x;
}
如何檢查這是否正確?有一個 PBKDF2 的在線 javascript 實現http://anandam.name/pbkdf2/
How to check whether this is correct? There is an online javascript implementation of PBKDF2 http://anandam.name/pbkdf2/
我得到了一致的結果 :)如果有人得到不正確的結果,請報告:)
I got consistent results :) Please report if anyone is getting an incorrect result :)
希望這可以幫助某人:)
Hope this helps someone :)
更新:確認使用此處提供的測試向量
UPDATE: Confirmed working with test vectors provided here
https://datatracker.ietf.org/doc/html/draft-josefsson-pbkdf2-test-vectors-00
更新:或者,對于鹽,我們可以使用 RNGCryptoServiceProvider
.確保引用 System.Security.Cryptography
命名空間.
UPDATE:
Alternatively, for the salt we can use a RNGCryptoServiceProvider
. Make sure to reference the System.Security.Cryptography
namespace.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] salt = new byte[16];
rng.GetBytes(salt);
這篇關于充氣城堡 C# 中的 PBKDF2的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!