Subject | Re: [Firebird-Architect] Encryption |
---|---|
Author | Jim Starkey |
Post date | 2010-11-07T16:45:18Z |
On 11/7/2010 7:50 AM, Alex Peshkoff wrote:
In specific, cipher transforms retain their computed keys. Transforms
are also required to pass the reset to their source transforms, if any.
This allows, for example, to use a single pair of transform chains for a
socket for the duration of the session or a single transform chain for
private key of a server instance.
I've attached an AES transform as an example.
----------
// Copyright (C) 2010 by NimbusDB, Inc. 2010
#include "Cloud.h"
#include "AESTransform.h"
#include "TransformException.h"
#include "tomcrypt.h"
#define SETUP rijndael_setup
#define ECB_ENC rijndael_ecb_encrypt
#define ECB_DEC rijndael_ecb_decrypt
#define ECB_DONE rijndael_done
#define ECB_TEST rijndael_test
#define ECB_KS rijndael_keysize
extern int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
extern int ECB_DEC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
#ifdef _DEBUG
#undef THIS_FILE
static const char THIS_FILE[]=__FILE__;
#endif
AESTransform::AESTransform(int operatingMode, Transform *src)
{
mode = operatingMode;
source = src;
schedule = new symmetric_key;
blockSize = AES_blocksize;
reset();
}
AESTransform::~AESTransform(void)
{
delete schedule;
}
unsigned int AESTransform::get(unsigned int bufferLength, UCHAR* buffer)
{
UCHAR *p = buffer;
UCHAR *endBuffer = buffer + bufferLength;
UCHAR input[AES_blocksize];
// If there is residual data from the last call, move it to output buffer
if (ptr < end)
{
int len = MIN(bufferLength, (unsigned int)(end - ptr));
memcpy (p, ptr, len);
ptr += len;
p += len;
}
// loop until output buffer is full or we run out of data
while (p < endBuffer && !done)
{
int len = source->get(sizeof(input), input);
// If we got less than a full block, we've run the input source dry
if (len < sizeof(input))
{
done = true;
if (len == 0)
break;
memset(input + len, 0, AES_blocksize - len);
}
// Encode or decode a block
switch(mode)
{
case AES_encrypt:
ECB_ENC(input, block, schedule);
break;
case AES_decrypt:
if (len < sizeof(input))
throw TransformException("partial AES block");
ECB_DEC(input, block, schedule);
break;
}
// Figure out how much of the block fits in the output buffer and more than amount of data
len = MIN(endBuffer - p, AES_blocksize);
memcpy(p, block, len);
p += len;
// If there's residual data, set up for the next call
if (len < sizeof(block))
{
ptr = block + len;
break;
}
}
return p - buffer;
}
unsigned int AESTransform::getLength(void)
{
int len = source->getLength();
//return (len + AES_blocksize - 1) / BLOCK_SIZE8 * AES_blocksize;
return ROUNDUP(len, AES_blocksize);
}
void AESTransform::reset(void)
{
end = block + sizeof(block);
ptr = end;
done = false;
if (source)
source->reset();
}
void AESTransform::setKey(int keyLength, const UCHAR* key)
{
int rounds = 0;
switch (keyLength)
{
case 16:
rounds = 10;
break;
case 24:
rounds = 12;
break;
case 32:
rounds = 14;
break;
default:
throw TransformException("Invalid AES keysize");
}
SETUP(key, keyLength, rounds, schedule);
}
----------
// Copyright (C) 2010 by NimbusDB, Inc.
#ifndef _AES_TRANSFORM_H_
#define _AES_TRANSFORM_H_
#include "Transform.h"
static const int AES_encrypt = 0;
static const int AES_decrypt = 1;
static const int AES_blocksize = 16;
union Symmetric_key;
class AESTransform : public Transform
{
public:
AESTransform(int operatingMode, Transform *src);
virtual ~AESTransform(void);
virtual unsigned int get(unsigned int bufferLength, UCHAR* buffer);
virtual unsigned int getLength(void);
virtual void reset(void);
void setKey(int keyLength, const UCHAR* key);
int mode;
uint blockSize;
bool done;
Transform *source;
UCHAR block[AES_blocksize];
UCHAR *ptr;
UCHAR *end;
Symmetric_key *schedule;
};
#endif
[Non-text portions of this message have been removed]
> On 11/05/10 03:31, Jim Starkey wrote:Not the case at all. The reset method prepares a transform for re-use.
>> If anyone is planning to screw around with encryption, may I recommend a
>> formalism that I developed a awhile back that may help.
> Looks like it's as designed here that transforms are objects of single
> use - in constructor initial data in some form is passed to transform,
> then we get() from transform result of it's job, and after it transform
> can be only destroyed. Does it mean that on practice transform
> constructors are so fast that we can ignore possible performance issues
> with it?
>
In specific, cipher transforms retain their computed keys. Transforms
are also required to pass the reset to their source transforms, if any.
This allows, for example, to use a single pair of transform chains for a
socket for the duration of the session or a single transform chain for
private key of a server instance.
I've attached an AES transform as an example.
----------
// Copyright (C) 2010 by NimbusDB, Inc. 2010
#include "Cloud.h"
#include "AESTransform.h"
#include "TransformException.h"
#include "tomcrypt.h"
#define SETUP rijndael_setup
#define ECB_ENC rijndael_ecb_encrypt
#define ECB_DEC rijndael_ecb_decrypt
#define ECB_DONE rijndael_done
#define ECB_TEST rijndael_test
#define ECB_KS rijndael_keysize
extern int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
extern int ECB_DEC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
#ifdef _DEBUG
#undef THIS_FILE
static const char THIS_FILE[]=__FILE__;
#endif
AESTransform::AESTransform(int operatingMode, Transform *src)
{
mode = operatingMode;
source = src;
schedule = new symmetric_key;
blockSize = AES_blocksize;
reset();
}
AESTransform::~AESTransform(void)
{
delete schedule;
}
unsigned int AESTransform::get(unsigned int bufferLength, UCHAR* buffer)
{
UCHAR *p = buffer;
UCHAR *endBuffer = buffer + bufferLength;
UCHAR input[AES_blocksize];
// If there is residual data from the last call, move it to output buffer
if (ptr < end)
{
int len = MIN(bufferLength, (unsigned int)(end - ptr));
memcpy (p, ptr, len);
ptr += len;
p += len;
}
// loop until output buffer is full or we run out of data
while (p < endBuffer && !done)
{
int len = source->get(sizeof(input), input);
// If we got less than a full block, we've run the input source dry
if (len < sizeof(input))
{
done = true;
if (len == 0)
break;
memset(input + len, 0, AES_blocksize - len);
}
// Encode or decode a block
switch(mode)
{
case AES_encrypt:
ECB_ENC(input, block, schedule);
break;
case AES_decrypt:
if (len < sizeof(input))
throw TransformException("partial AES block");
ECB_DEC(input, block, schedule);
break;
}
// Figure out how much of the block fits in the output buffer and more than amount of data
len = MIN(endBuffer - p, AES_blocksize);
memcpy(p, block, len);
p += len;
// If there's residual data, set up for the next call
if (len < sizeof(block))
{
ptr = block + len;
break;
}
}
return p - buffer;
}
unsigned int AESTransform::getLength(void)
{
int len = source->getLength();
//return (len + AES_blocksize - 1) / BLOCK_SIZE8 * AES_blocksize;
return ROUNDUP(len, AES_blocksize);
}
void AESTransform::reset(void)
{
end = block + sizeof(block);
ptr = end;
done = false;
if (source)
source->reset();
}
void AESTransform::setKey(int keyLength, const UCHAR* key)
{
int rounds = 0;
switch (keyLength)
{
case 16:
rounds = 10;
break;
case 24:
rounds = 12;
break;
case 32:
rounds = 14;
break;
default:
throw TransformException("Invalid AES keysize");
}
SETUP(key, keyLength, rounds, schedule);
}
----------
// Copyright (C) 2010 by NimbusDB, Inc.
#ifndef _AES_TRANSFORM_H_
#define _AES_TRANSFORM_H_
#include "Transform.h"
static const int AES_encrypt = 0;
static const int AES_decrypt = 1;
static const int AES_blocksize = 16;
union Symmetric_key;
class AESTransform : public Transform
{
public:
AESTransform(int operatingMode, Transform *src);
virtual ~AESTransform(void);
virtual unsigned int get(unsigned int bufferLength, UCHAR* buffer);
virtual unsigned int getLength(void);
virtual void reset(void);
void setKey(int keyLength, const UCHAR* key);
int mode;
uint blockSize;
bool done;
Transform *source;
UCHAR block[AES_blocksize];
UCHAR *ptr;
UCHAR *end;
Symmetric_key *schedule;
};
#endif
[Non-text portions of this message have been removed]