Some time ago I was working in a pet project for a type of database engine. And I thought about securing the data in disk with encryption.. and since the main code was already developed.. I had a few requirements..
- a simple stream class that I could hook instead of my file stream had
- to support random access (both read/write at random positions)
- be able to work at any byte position (since the data might not be aligned)
- encrypt/decrypt only the requested data, not the all file,(because the file maybe several MB)
- fast encryption/decryption, since this was for a database system
nowhere on the web I found information about this, or implementation of such code. Normal stream ciphers don't support random access/lookup, and block ciphers require the data to be aligned and in fixed blocks.. So I thought about developing my own. I do know that developing your own encryption is always a bad choice.. but this was kind of theoretical exercise..
So I would like to present you the code.. just to see how far of I am from a security point of view
First the stream is initialized with a password.. but that password is not used for the encryption itself.. it is used as a seed to scramble an array of 256 values in hope of of increasing the key space
public CipherStream(String sKey,Stream oStream)
{
_oStream = oStream;
//initialize key space
_oVector = new byte[256];
for(int i = 0; i <= 255; i++)
_oVector[i] = (byte)i;
//shuffle the keyspace
for (int i = 0; i <= 255; i++)//shuffle the box
{
//shuffle this item with other
//other is chosen by char(i) of password
//and the currently shuffling vector(I)
// this means that even repeating passwords 'aaaaaa' will produce random results
int j = ((sKey[i % sKey.Length]) + _oVector[i]) % 256;
byte cTemp = _oVector[i];
_oVector[i] = _oVector[j];
_oVector[j] = cTemp;
}
}
after this all we have to do is choose the cipher byte for the position we are trying to read/write from.. in my implementation I used xor, witch I know is not the most safe.. but that is can be changed and is not the core of the algorithm..
public override void Write(byte[] buffer, int offset, int count)
{
long nPosition = this.Position;
for (int i = offset; i < count; i++)
{
byte oPlain = buffer[i];
byte nKey = GetKey(nPosition);
byte oCypher = (byte)(oPlain ^ nKey);
buffer[i] = oCypher;
nPosition++;
}
_oStream.Write(buffer, offset, count);
}
the 'key' to the byte is chosen from the key vector dependently from the position we are trying to access.. calculations are done so that there are no repetitions and the chosen value is as random as possible
private byte GetKey(long nPosition)
{
byte nOffset = _oVector[nPosition % _oVector.Length];
byte nOffset2 = _oVector[(nPosition / (nOffset + 1)) % _oVector.Length];
int nDif = nOffset - nOffset2;
if (nDif < 0)
nDif += 255;
byte nKey = (Byte)(nDif % 256);
return nKey;
}
I did try to render the stream as a bitmap.. just so make sure no patterns where obvious.. and did some fine tunning there.. and it seemed ok..
the best I can describe this algorithm is a 'deterministic predictable pseudo-random generator' where I can just ask 'give me the nth random number', and the seed is a 2048 bit vector that is initialized randomly with a password..
how far am I from a solution? Is this completely insecure? or there is not even point of trying because there is no solution for this 'random access stream' problem?