openssl crypto wrapper

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
Post Reply
prophet
Knows some wx things
Knows some wx things
Posts: 32
Joined: Wed Sep 01, 2004 6:19 am

openssl crypto wrapper

Post by prophet »

Use it to encrypt your streams !!!

Header file

[syntax="wxwidgets"]
#include <openssl/evp.h>
#include <wx/stream.h>

extern unsigned char Key[16];
extern unsigned char Key_IV[8];

class Cipher
{
const EVP_CIPHER *m_cipher;

public:
Cipher(const EVP_CIPHER *cipher);

int GetNid() const
{
return EVP_CIPHER_nid(m_cipher);
}

int GetBlockSize() const
{
return EVP_CIPHER_block_size(m_cipher);
}

int GetKeyLength() const
{
return EVP_CIPHER_key_length(m_cipher);
}

int GetIVLength() const
{
return EVP_CIPHER_iv_length(m_cipher);
}

int GetFlags() const
{
return EVP_CIPHER_flags(m_cipher);
}

int GetMode() const
{
return EVP_CIPHER_mode(m_cipher);
}

const EVP_CIPHER *GetCipher() const
{
return m_cipher;
}
};

extern Cipher Cipher_NULL;

extern Cipher Cipher_DES_CBC;
extern Cipher Cipher_DES_ECB;
extern Cipher Cipher_DES_CFB;
extern Cipher Cipher_DES_OFB;

extern Cipher Cipher_DES_EDE_CBC;
extern Cipher Cipher_DES_EDE;
extern Cipher Cipher_DES_EDE_CFB;
extern Cipher Cipher_DES_EDE_OFB;

extern Cipher Cipher_DES_EDE3_CBC;
extern Cipher Cipher_DES_EDE3;
extern Cipher Cipher_DES_EDE3_CFB;
extern Cipher Cipher_DES_EDE3_OFB;

extern Cipher Cipher_DESX_CBC;
extern Cipher Cipher_RC4;
extern Cipher Cipher_RC4_40;

extern Cipher Cipher_IDEA_CBC;
extern Cipher Cipher_IDEA_ECB;
extern Cipher Cipher_IDEA_CFB;
extern Cipher Cipher_IDEA_OFB;

extern Cipher Cipher_RC2_CBC;
extern Cipher Cipher_RC2_ECB;
extern Cipher Cipher_RC2_CFB;
extern Cipher Cipher_RC2_OFB;

extern Cipher Cipher_RC2_40_CBC;
extern Cipher Cipher_RC2_64_CBC;

extern Cipher Cipher_BF_CBC;
extern Cipher Cipher_BF_ECB;
extern Cipher Cipher_BF_CFB;
extern Cipher Cipher_BF_OFB;

extern Cipher Cipher_CAST5_CBC;
extern Cipher Cipher_CAST5_ECB;
extern Cipher Cipher_CAST5_CFB;
extern Cipher Cipher_CAST5_OFB;

extern Cipher Cipher_RC5_CBC;
extern Cipher Cipher_RC5_ECB;
extern Cipher Cipher_RC5_CFB;
extern Cipher Cipher_RC5_OFB;

class CipherStream
{
EVP_CIPHER_CTX m_cipher_ctx;

protected:
bool Update(const unsigned char *in_buffer, int in_buffer_size, unsigned char *out_buffer, int *out_buffer_size)
{
return EVP_CipherUpdate(&m_cipher_ctx, out_buffer, out_buffer_size, in_buffer, in_buffer_size);
}

bool Final(unsigned char *out_buffer, int *out_buffer_size)
{
return EVP_CipherFinal_ex(&m_cipher_ctx, out_buffer, out_buffer_size);
}

public:
CipherStream(const Cipher &cipher, unsigned char *key, unsigned char *iv, int do_encrypt)
{
EVP_CIPHER_CTX_init(&m_cipher_ctx);
EVP_CipherInit_ex(&m_cipher_ctx, cipher.GetCipher(), NULL, key, iv, do_encrypt);
}

const EVP_CIPHER_CTX *GetCipherCtx() const
{
return &m_cipher_ctx;
}
};

class EncryptOutputStream
: public wxFilterOutputStream
, public CipherStream
{
public:
EncryptOutputStream(wxOutputStream& stream, const Cipher &cipher, unsigned char *key, unsigned char *iv);

~EncryptOutputStream()
{
Sync();
}

void Sync();

protected:
size_t OnSysWrite(const void *buffer, size_t size);
};

class DecryptInputStream
: public wxFilterInputStream
, public CipherStream
{
protected:

unsigned char m_d_buffer[2*EVP_MAX_BLOCK_LENGTH];
int m_d_size;
int m_d_ptr;
int m_d_blocksize;

size_t OnSysRead(void *buffer, size_t size);
void FillBuffer();

public:
DecryptInputStream(wxInputStream& stream, const Cipher &cipher, unsigned char *key, unsigned char *iv);
};

class MD
{
const EVP_MD *m_md;

public:
MD(const EVP_MD *md)
{
m_md = md;
}

int GetKeyType() const
{
return EVP_MD_pkey_type(m_md);
}

int GetBlockSize() const
{
return EVP_MD_block_size(m_md);
}

const EVP_MD *GetMD() const
{
return m_md;
}
};

extern MD MD_MD2;
extern MD MD_MD5;
extern MD MD_SHA;
extern MD MD_SHA1;
extern MD MD_DSS;
extern MD MD_DSS1;
extern MD MD_MDC2;
extern MD MD_RIPEMD160;

class MDStream
{
unsigned char *m_md_buffer;
EVP_MD_CTX m_md_ctx;
size_t m_size;

protected:
~MDStream();

void Update(const void *buffer, size_t buffer_size)
{
EVP_DigestUpdate(&m_md_ctx, buffer, buffer_size);
}

void Final();

public:
MDStream(const MD &md_type);

void GetMD(unsigned char *md)
{
wxASSERT_MSG(m_md_buffer != NULL, _T("Message digest was not finalized yet"));
memcpy(md, m_md_buffer, m_size);
}

size_t GetMDSize()
{
wxASSERT_MSG(m_md_buffer != NULL, _T("Message digest was not finalized yet"));
return m_size;
}
};

class MDInputStream
: public wxFilterInputStream
, public MDStream
{
public:
MDInputStream(wxInputStream &stream, const MD &type);

protected:
size_t OnSysRead(void *buffer, size_t size);
};

class MDOutputStream
: public wxFilterOutputStream
, public MDStream
{
public:
MDOutputStream(wxOutputStream &stream, const MD &type);

void Sync()
{
m_parent_o_stream->Sync();
Final();
}

~MDOutputStream()
{
m_parent_o_stream->Sync();
}

protected:
size_t OnSysWrite(const void *buffer, size_t size);
};

#endif
[/code]

Source file:

Code: Select all

#include "Crypto.h"
	
wxUint8 Key[16] = {
	0, 0, 0, 0, 
	0, 0, 0, 0, 
	0, 0, 0, 0, 
	0, 0, 0, 0,
};

wxUint8 Key_IV[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

Cipher::Cipher(const EVP_CIPHER *cipher)
{
	m_cipher = cipher;
}

Cipher Cipher_NULL(EVP_enc_null());

Cipher Cipher_DES_CBC(EVP_des_cbc());
Cipher Cipher_DES_ECB(EVP_des_ecb());
Cipher Cipher_DES_CFB(EVP_des_cfb());
Cipher Cipher_DES_OFB(EVP_des_ofb());

Cipher Cipher_DES_EDE_CBC(EVP_des_ede_cbc());
Cipher Cipher_DES_EDE(EVP_des_ede());
Cipher Cipher_DES_EDE_CFB(EVP_des_ede_cfb());
Cipher Cipher_DES_EDE_OFB(EVP_des_ede_ofb());

Cipher Cipher_DES_EDE3_CBC(EVP_des_ede3_cbc());
Cipher Cipher_DES_EDE3(EVP_des_ede3());
Cipher Cipher_DES_EDE3_CFB(EVP_des_ede3_cfb());
Cipher Cipher_DES_EDE3_OFB(EVP_des_ede3_ofb());

Cipher Cipher_DESX_CBC(EVP_desx_cbc());
Cipher Cipher_RC4(EVP_rc4());
Cipher Cipher_RC4_40(EVP_rc4_40());

Cipher Cipher_IDEA_CBC(EVP_idea_cbc());
Cipher Cipher_IDEA_ECB(EVP_idea_ecb());
Cipher Cipher_IDEA_CFB(EVP_idea_cfb());
Cipher Cipher_IDEA_OFB(EVP_idea_ofb());

Cipher Cipher_RC2_CBC(EVP_rc2_cbc());
Cipher Cipher_RC2_ECB(EVP_rc2_ecb());
Cipher Cipher_RC2_CFB(EVP_rc2_cfb());
Cipher Cipher_RC2_OFB(EVP_rc2_ofb());

Cipher Cipher_RC2_40_CBC(EVP_rc2_40_cbc());
Cipher Cipher_RC2_64_CBC(EVP_rc2_64_cbc());

Cipher Cipher_BF_CBC(EVP_bf_cbc());
Cipher Cipher_BF_ECB(EVP_bf_ecb());
Cipher Cipher_BF_CFB(EVP_bf_cfb());
Cipher Cipher_BF_OFB(EVP_bf_ofb());

Cipher Cipher_CAST5_CBC(EVP_cast5_cbc());
Cipher Cipher_CAST5_ECB(EVP_cast5_ecb());
Cipher Cipher_CAST5_CFB(EVP_cast5_cfb());
Cipher Cipher_CAST5_OFB(EVP_cast5_ofb());

Cipher Cipher_RC5_CBC(EVP_rc5_32_12_16_cbc());
Cipher Cipher_RC5_ECB(EVP_rc5_32_12_16_ecb());
Cipher Cipher_RC5_CFB(EVP_rc5_32_12_16_cfb());
Cipher Cipher_RC5_OFB(EVP_rc5_32_12_16_ofb());

MD MD_MD2(EVP_md2());
MD MD_MD5(EVP_md5());
MD MD_SHA(EVP_sha());
MD MD_SHA1(EVP_sha1());
MD MD_DSS(EVP_dss());
MD MD_DSS1(EVP_dss1());
MD MD_MDC2(EVP_mdc2());
MD MD_RIPEMD160(EVP_ripemd160());

DecryptInputStream::DecryptInputStream(wxInputStream& stream, const Cipher &cipher, unsigned char *key, unsigned char *iv)
  	: wxFilterInputStream(stream)
	, CipherStream(cipher, key, iv, 0)
{	
	m_d_blocksize = cipher.GetBlockSize();
	m_d_size = 0;
	m_d_ptr = 0;
}

void DecryptInputStream::FillBuffer()
{
	m_d_ptr = 0;

	do {	
		unsigned char in_buffer[EVP_MAX_BLOCK_LENGTH];
		int in_size = m_parent_i_stream->Read(in_buffer, m_d_blocksize).LastRead();

		if(in_size > 0) {
			Update(in_buffer, in_size, m_d_buffer, &m_d_size);
		} else {
			Final(m_d_buffer, &m_d_size);
		}
	} while(m_d_size == 0);
}

size_t DecryptInputStream::OnSysRead(void *buffer, size_t buffer_size)
{
	size_t read = 0;

	while(read < buffer_size) {

		if(m_d_size - m_d_ptr == 0) {
			FillBuffer();
		
			if(m_d_size - m_d_ptr == 0) {
				m_lasterror = wxSTREAM_EOF;
				return read;
			}
		}

		size_t todo_size = buffer_size - read;
		size_t buffer_size = m_d_size - m_d_ptr;
		size_t copy_size;

		if(todo_size < buffer_size)
			copy_size = todo_size;
		else
			copy_size = buffer_size;
		
		memcpy((unsigned char *)buffer + read, m_d_buffer + m_d_ptr, copy_size);
		read += copy_size;
		m_d_ptr += copy_size;
	}

	return read;
}

EncryptOutputStream::EncryptOutputStream(wxOutputStream& stream, const Cipher &cipher, unsigned char *key, unsigned char *iv)
	: wxFilterOutputStream(stream)
	, CipherStream(cipher, key, iv, 1)
{
}

void EncryptOutputStream::Sync()
{
	unsigned char out_buffer[EVP_CIPHER_CTX_block_size(GetCipherCtx()) - 1];
	int out_size;

	Final(out_buffer, &out_size);
	m_parent_o_stream->Write(out_buffer, out_size);
}

size_t EncryptOutputStream::OnSysWrite(const void *buffer, size_t buffer_size)
{
	unsigned char out_buffer[buffer_size + EVP_CIPHER_CTX_block_size(GetCipherCtx()) - 1];
	int out_size;

	Update((unsigned char *)buffer, buffer_size, out_buffer, &out_size);

	size_t result = m_parent_o_stream->Write(out_buffer, out_size).LastWrite();
	m_lasterror = m_parent_o_stream->GetLastError();

	return result;
}

MDStream::MDStream(const MD &md_type)
{
	EVP_MD_CTX_init(&m_md_ctx);
	EVP_DigestInit_ex(&m_md_ctx, md_type.GetMD(), NULL);

	m_md_buffer = NULL;	
}

void MDStream::Final()
{
	if(m_md_buffer == NULL) {
		m_size = EVP_MD_CTX_size(&m_md_ctx);
		m_md_buffer = new unsigned char[m_size];

 		EVP_DigestFinal_ex(&m_md_ctx, m_md_buffer, NULL);
	}	
}

MDStream::~MDStream()
{
	EVP_MD_CTX_cleanup(&m_md_ctx);

	if(m_md_buffer != NULL) {
		delete[] m_md_buffer;
	}
}

MDOutputStream::MDOutputStream(wxOutputStream& stream, const MD &type)
	: wxFilterOutputStream(stream)
	, MDStream(type)
{
}

size_t MDOutputStream::OnSysWrite(const void *buffer, size_t buffer_size)
{
	size_t result = m_parent_o_stream->Write(buffer, buffer_size).LastWrite();
	m_lasterror = m_parent_o_stream->GetLastError();

	Update(buffer, result);

	return result;
}

MDInputStream::MDInputStream(wxInputStream& stream, const MD &type)
	: wxFilterInputStream(stream)
	, MDStream(type)
{
}

size_t MDInputStream::OnSysRead(void *buffer, size_t buffer_size)
{
	size_t result = m_parent_i_stream->Read(buffer, buffer_size).LastRead();
	m_lasterror = m_parent_i_stream->GetLastError();
	
	Update(buffer, result);

	if(m_lasterror == wxSTREAM_EOF) {
 		Final();
	}

	return result;
}

[/syntax]
Jorg
Moderator
Moderator
Posts: 3971
Joined: Fri Aug 27, 2004 9:38 pm
Location: Delft, Netherlands
Contact:

Post by Jorg »

Very cool! I really need a way to accomodate all these nice contributions on this page. It would be neat if they can be simply downloaded instead of copied and pasted. But for now I see no other way ;-)

Regards,
- Jorgen
Forensic Software Engineer
Netherlands Forensic Insitute
http://english.forensischinstituut.nl/
-------------------------------------
Jorg's WasteBucket
http://www.xs4all.nl/~jorgb/wb
xpmstos
Knows some wx things
Knows some wx things
Posts: 37
Joined: Mon Aug 30, 2004 8:16 am
Location: Wismar, Germany
Contact:

Post by xpmstos »

Very Nice! I had it pasted into my wxCRP-Repository.

Greetz,
xpmstos
Jorg wrote:It would be neat if they can be simply downloaded instead of copied and pasted. But for now I see no other way ;-)
An alternative Way: Code-Repository (wxCRP) for the wxWidgets-Forum ?!
Post Reply