PBKDF2在充气城堡C# [英] PBKDF2 in Bouncy Castle C#

查看:257
本文介绍了PBKDF2在充气城堡C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经被周围的C#充气城堡API搞乱找到如何做一个PBKDF2密钥导出。

我现在真的很无能。

我想读通过Pkcs5S2ParametersGenerator.cs和PBKDF2Params.cs文件,但我真的无法弄清楚如何做到这一点。

据到目前为止,我还做了研究,PBKDF2需要一个字符串(或CHAR [])这是口令,盐和迭代次数。

到目前为止,最有前途,最明显的我已经走了这么远是PBKDF2Params和Pkcs5S2ParametersGenerator。

这些都不似乎是接受一个字符串或一个char []。

有没有人在C#这样做或对此有任何线索?也许有人谁已经实施BouncyCastle的Java和帮助?

感谢名单很多提前:)

更新:我已经找到了如何在充气城堡做到这一点。看看下面的回答:)


解决方案

在时间和通过code要去小时,我发现,要做到这一点,最简单的方法是采取$ C $的几部分下在Pkcs5S2ParametersGenerator.cs,创造我自己的类当然也使用其它BouncyCastle的API的。这与点NET精简框架(Windows Mobile的)完美的作品。这是Rfc2898DeriveBytes类相当于是不是在点NET Compact Framework的2.0 / 3.5 present。好吧,也许不是完全对等,但做这项工作:)

这是PKCS5 / PKCS#5

这是用来将HMAC-SHA1的PRF(伪随机函数)

第一件事,第一。从下载 http://www.bouncycastle.org/csharp/ 的充气城堡编译的程序集,添加 BouncyCastle.Crypto.dll 为您的项目提供参考。

之后,创建新类文件与下面的code。

 使用系统;
使用Org.BouncyCastle.Crypto;
使用Org.BouncyCastle.Crypto.Parameters;
使用Org.BouncyCastle.Crypto.Digests;
使用Org.BouncyCastle.Crypto.Macs;
使用Org.BouncyCastle.Math;
使用Org.BouncyCastle.Security;命名空间PBKDF2_PKCS5
{
    类PBKDF2
    {        私人只读的iMac HMAC = HMAC新(新Sha1Digest());        私人无效F(
            字节[] P,
            字节[] S,
            INT C,
            字节[] IBUF,
            字节[] outBytes,
            INT OUTOFF)
        {
            字节[] =国家新的字节[hMac.GetMacSize()];
            ICipherParameters参数=新KeyParameter的(P);            hMac.Init(参数);            如果(S!= NULL)
            {
                hMac.BlockUpdate(S,O,S.Length);
            }            hMac.BlockUpdate(IBUF,0,iBuf.Length);            hMac.DoFinal(州,0);            Array.Copy(州,0,outBytes,OUTOFF,state.Length);            对于(诠释计数= 1;计数= C;!算++)
            {
                hMac.Init(参数);
                hMac.BlockUpdate(州,0,state.Length);
                hMac.DoFinal(州,0);                对于(INT J = 0; J = state.Length;!J ++)
                {
                    outBytes [OUTOFF + J] ^ =状态[J]。
                }
            }
        }        私人无效IntToOctet(
            字节[]缓冲区,
            int i)以
        {
            缓冲器[0] =(字节)((UINT)I>> 24);
            缓冲液[1] =(字节)((UINT)I>> 16);
            缓冲液[2] =(字节)((UINT)I>→8);
            缓冲液[3] =(字节)I;
        }        //使用这个功能来获取派生密钥。
        //为dkLen是八位字节,多少字节希望在函数返回。
        // mPassword是转换为字节的密码。
        // mSalt是转换为字节盐
        // mIterationCount是您要执行多少次迭代。
        公众的byte [] GenerateDerivedKey(
            INT为dkLen,
            字节[] mPassword,
            字节[] mSalt,
            INT mIterationCount
            )
        {
            INT为hLen = hMac.GetMacSize();
            INT L =(为dkLen +的hLen - 1)/ hLen的;
            字节[] = IBUF新的字节[4];
            字节[] = outBytes新的字节[L *为hLen]。            的for(int i = 1; I< = 1;我++)
            {
                IntToOctet(IBUF,I);                F(mPassword,mSalt,mIterationCount,IBUF,outBytes,(I - 1)*为hLen);
            }        //这个时候outBytes将包含派生键+更多的字节。
       //按照PKCS#5 V2.0:基于密码的加密标准(www.truecrypt.org/docs/pkcs5v2-0.pdf)
       //我们以提取的第一个dkLen字节以产生导出密钥。       //我创造与为dkLen大小的字节数组,然后使用
       //Buffer.BlockCopy只字节为dkLen量复制到其中
       //最后返回它:D        字节[] =输出新的字节[为dkLen]        Buffer.BlockCopy(outBytes,0,输出,0,为dkLen);        返回输出;
        }
    }
}

那么,如何使用这个功能呢?简单! :)
这是密码和盐是由用户提供的一个非常简单的例子。

 私人无效cmdDeriveKey_Click(对象发件人,EventArgs的发送)
        {
            字节[] =盐ASCIIEncoding.UTF8.GetBytes(txtSalt.Text);            PBKDF2 passwordDerive =新PBKDF2();
      //欲用于AES-128的密钥,因此,我想导出密钥是
      // 128位。因此,我将使用为dkLen8分之128= 16(导出密钥长度)。
      //同样,如果你想要一个256位的密钥,为dkLen将八分之二百五十六= 32。            字节[]结果= passwordDerive.GenerateDerivedKey(16,ASCIIEncoding.UTF8.GetBytes(txtPassword.Text),盐,1000);           //结果现在将包含派生密钥。现在用它来加密的任何目的:)
           //下面的code仅显示在TextBox派生密钥。            字符串x =;            的for(int i = 0; I< result.Length;我++)
            {
                X + =结果[I]的ToString(X);
            }            txtResult.Text = X;        }

如何检查是否正确?
有一个在线的JavaScript实现PBKDF2的
http://anandam.name/pbkdf2/

我得到了一致的结果:)
请报告,如果有人越来越不正确的结果:)

希望这可以帮助别人:)

更新:确认与这里提供测试向量工作<​​/ P>

<一个href=\"http://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-00\">http://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-00

更新:
或者,盐我们可以使用 RNGCryptoServiceProvider 。确保引用 System.Security.Cryptography 命名空间。

  RNGCryptoServiceProvider RNG =新RNGCryptoServiceProvider();字节[] =盐新的字节[16];rng.GetBytes(盐);

I've being messing around the C# Bouncy Castle API to find how to do a PBKDF2 key derivation.

I am really clueless right now.

I tried reading through the Pkcs5S2ParametersGenerator.cs and PBKDF2Params.cs files but i really cant figure out how to do it.

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.

So far the most promising and most obvious i've come so far is the PBKDF2Params and Pkcs5S2ParametersGenerator.

None of these seems to be accepting a string or a char[].

Has anyone done this in C# or have any clue about this? Or perhaps someone who has implemented BouncyCastle in Java and can help?

Thanx a lot in advance :)

UPDATE: I have found how to do this in Bouncy Castle. Look below for answer :)

解决方案

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 :)

This is PKCS5/PKCS#5

The PRF (Pseudo Random Function) which is used will be HMAC-SHA1

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;

        }

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

http://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-00

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);

这篇关于PBKDF2在充气城堡C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆