RFC2898 (Salt can have less than 8 bytes)


RFC2898 (Salt can have less than 8 bytes)

I my previous post : http://dotnetspider.com/resources/40614-PBKDF-Rfc-DeriveBytes-Encryption.aspx
I had said (at the end) that, You cannot have a salt value less than 8 bytes and the iteration should never be less than 1 or else
"Rfc2898DeriveBytes.GetBytes Method" will throw an exception {The specified salt size is smaller than 8 bytes or the iteration count is less than 1.}

But we can have a salt which can be less than 8 bytes.
To achieve this we have to do some changes on Rfc2898DeriveBytes().
As we cannot do a direct changes to System.Security.Cryptography.Rfc2898DeriveBytes.cs in which we have the Rfc2898DeriveBytes() member function,
because we cannot do a direct changes to a metadata file.

So we have to apply here some inheritance concepts.

Below is the code on how to acchive our goal.
The code is self explainatory.

In case of any doubt give a RESPONSE

First create a class My_Rfc2898DeriveBytes.cs


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

namespace My_Rfc2898DeriveBytes
{
//inherit properties from DeriveBytes
public class Rfc2898DeriveBytes : DeriveBytes
{
const int BlockSize = 20;
uint block;
byte[] buffer;
int endIndex;
readonly HMACSHA1 hmacsha1;
uint iterations;
byte[] salt;
int startIndex;

// Create Rfc2898DeriveBytes Constructors
public Rfc2898DeriveBytes(string password, byte[] salt, int iterations)
: this(new UTF8Encoding(false).GetBytes(password), salt, iterations)
{
}

public Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations)
{
Salt = salt;
IterationCount = iterations;
hmacsha1 = new HMACSHA1(password);
Initialize();
}

//get and set salt
public byte[] Salt
{
get
{
return (byte[]) salt.Clone();
}
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
salt = (byte[]) value.Clone();
Initialize();
}

//get bytes for DeriveKey()
static byte[] Int(uint i)
{
byte[] bytes = BitConverter.GetBytes(i);
byte[] buffer2 = new byte[] {bytes[3], bytes[2], bytes[1], bytes[0]};
if (!BitConverter.IsLittleEndian)
{
return bytes;
}
return buffer2;
}

//Derive the key
byte[] DeriveKey()
{
byte[] inputBuffer = Int(block);
hmacsha1.TransformBlock(salt, 0, salt.Length, salt, 0);
hmacsha1.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
byte[] hash = hmacsha1.Hash;
hmacsha1.Initialize();
byte[] buffer3 = hash;
for (int i = 2; i <= iterations; i++)
{
hash = hmacsha1.ComputeHash(hash);
for (int j = 0; j < BlockSize; j++)
{
buffer3[j] = (byte) (buffer3[j] ^ hash[j]);
}
}
block++;
return buffer3;
}
//Get Bytes of the Generated Key
public override byte[] GetBytes(int bytesToGet)
{
if (bytesToGet <= 0)
{
throw new ArgumentOutOfRangeException("bytesToGet");
}
byte[] dst = new byte[bytesToGet];
int dstOffset = 0;
int count = endIndex - startIndex;
if (count > 0)
{
if (bytesToGet < count)
{
Buffer.BlockCopy(buffer, startIndex, dst, 0, bytesToGet);
startIndex += bytesToGet;
return dst;
}
Buffer.BlockCopy(buffer, startIndex, dst, 0, count);
startIndex = endIndex = 0;
dstOffset += count;
}
while (dstOffset < bytesToGet)
{
byte[] src = DeriveKey();
int num3 = bytesToGet - dstOffset;
if (num3 > BlockSize)
{
Buffer.BlockCopy(src, 0, dst, dstOffset, BlockSize);
dstOffset += BlockSize;
}
else
{
Buffer.BlockCopy(src, 0, dst, dstOffset, num3);
dstOffset += num3;
Buffer.BlockCopy(src, num3, buffer, startIndex, BlockSize - num3);
endIndex += BlockSize - num3;
return dst;
}
}
return dst;
}

void Initialize()
{
if (buffer != null)
{
Array.Clear(buffer, 0, buffer.Length);
}
buffer = new byte[BlockSize];
block = 1;
startIndex = endIndex = 0;
}

public override void Reset()
{
Initialize();
}
//get iteration count
public int IterationCount
{
get
{
return (int) iterations;
}
set
{
if (value <= 0)
{
throw new ArgumentOutOfRangeException("value");
}
iterations = (uint) value;
Initialize();
}
}
}
}


Cheers
Paul


Comments

Guest Author: GFR01 Aug 2012

Hi, ther is the same class My_Rfc2898DeriveBytes for visual studio 2010 (Visual Basic language)?

Author: Mrinmay Paul06 Aug 2012 Member Level: Gold   Points : 1

Hi GFR,
"My_Rfc2898DeriveBytes", is a custom namespace that I have created, the class is "Rfc2898DeriveBytes" which is again a custom class, which I inherit from "DeriveBytes";

"DeriveBytes" is the class provided in VS 2010, and you can inherit from this class to write your own custom class.

Paul

Guest Author: Jefferson20 Jan 2013

Is there an example like in your previous post : http://dotnetspider.com/resources/40614-PBKDF-Rfc-DeriveBytes-Encryption.aspx ?

How can I use this one?

Thanks a lot, the other one helped me alot.



  • Do not include your name, "with regards" etc in the comment. Write detailed comment, relevant to the topic.
  • No HTML formatting and links to other web sites are allowed.
  • This is a strictly moderated site. Absolutely no spam allowed.
  • Name:
    Email: