From 03e8c5ad314252cde58c53688c70b9f836a1d5b4 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Wed, 28 Nov 2012 17:39:09 +0000 Subject: More comments; moved the encryption system to unstable. --- src/unstable/blowfish.cpp | 13 ++ src/unstable/blowfish.h | 476 +++++++++++++++++++++++++++++++++++++++++ src/unstable/cipher.cpp | 10 + src/unstable/cipher.h | 137 ++++++++++++ src/unstable/ciphermodecbc.cpp | 2 + src/unstable/ciphermodecbc.h | 59 +++++ src/unstable/ciphermodecfb.cpp | 2 + src/unstable/ciphermodecfb.h | 59 +++++ src/unstable/ciphermodeecb.cpp | 1 + src/unstable/ciphermodeecb.h | 40 ++++ src/unstable/ciphermodeofb.cpp | 2 + src/unstable/ciphermodeofb.h | 65 ++++++ 12 files changed, 866 insertions(+) create mode 100644 src/unstable/blowfish.cpp create mode 100644 src/unstable/blowfish.h create mode 100644 src/unstable/cipher.cpp create mode 100644 src/unstable/cipher.h create mode 100644 src/unstable/ciphermodecbc.cpp create mode 100644 src/unstable/ciphermodecbc.h create mode 100644 src/unstable/ciphermodecfb.cpp create mode 100644 src/unstable/ciphermodecfb.h create mode 100644 src/unstable/ciphermodeecb.cpp create mode 100644 src/unstable/ciphermodeecb.h create mode 100644 src/unstable/ciphermodeofb.cpp create mode 100644 src/unstable/ciphermodeofb.h (limited to 'src/unstable') diff --git a/src/unstable/blowfish.cpp b/src/unstable/blowfish.cpp new file mode 100644 index 0000000..3da32a9 --- /dev/null +++ b/src/unstable/blowfish.cpp @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2007-2012 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "bu/blowfish.h" + +template class Bu::CipherModeEcb<8, Bu::Blowfish<1> >; +template class Bu::CipherModeCfb<8, Bu::Blowfish<1> >; +template class Bu::CipherModeCbc<8, Bu::Blowfish<1> >; +template class Bu::CipherModeOfb<8, Bu::Blowfish<1> >; diff --git a/src/unstable/blowfish.h b/src/unstable/blowfish.h new file mode 100644 index 0000000..b287bd4 --- /dev/null +++ b/src/unstable/blowfish.h @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2007-2012 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#ifndef BU_BLOWFISH_H +#define BU_BLOWFISH_H + +#include "bu/config.h" +#include "bu/cipher.h" + +#include "bu/ciphermodeecb.h" +#include "bu/ciphermodecfb.h" +#include "bu/ciphermodecbc.h" +#include "bu/ciphermodeofb.h" + +#define NUM_SUBKEYS 18 +#define NUM_S_BOXES 4 +#define NUM_ENTRIES 256 + +#define MAX_STRING 256 +#define MAX_PASSWD 56 // 448bits +#define F(x) \ + (((SB[0][x.byte.zero] + SB[1][x.byte.one]) ^ SB[2][x.byte.two]) + \ + SB[3][x.byte.three]) +#define revBytes( x ) x = (((x&0xff)<<24)|((x&0xff00)<<8)|((x&0xff0000)>>8)|((x&0xff000000)>>24)) + +namespace Bu +{ + template + class Blowfish : public Bu::Cipher<8> + { + public: + Blowfish( Bu::Stream &rNext ) : + Bu::Cipher<8>( rNext ) + { + } + + virtual ~Blowfish() + { + stop(); + reset(); + } + + void setPassword( const Bu::String &sPass ) + { + reset(); + + uint32_t i,j,len=sPass.getSize(); + Word Work,null0,null1; + + if (len > 0) + { + j = 0; + for (i=0;iword0, &w2 = dwWork->word1; + + w1.word = be32toh( w1.word ); + w2.word = be32toh( w2.word ); + + keyEncipher( w1, w2 ); + + revBytes( w1.word ); + revBytes( w2.word ); + } + + virtual void decipher( void *pData ) + { + DWord *dwWork = (DWord *)pData; + Word &w1 = dwWork->word0, &w2 = dwWork->word1; + + revBytes( w1.word ); + revBytes( w2.word ); + + w1.word ^= PA[17]; + w2.word ^= F(w1)^PA[16]; w1.word ^= F(w2)^PA[15]; + w2.word ^= F(w1)^PA[14]; w1.word ^= F(w2)^PA[13]; + w2.word ^= F(w1)^PA[12]; w1.word ^= F(w2)^PA[11]; + w2.word ^= F(w1)^PA[10]; w1.word ^= F(w2)^PA[9]; + w2.word ^= F(w1)^PA[8]; w1.word ^= F(w2)^PA[7]; + w2.word ^= F(w1)^PA[6]; w1.word ^= F(w2)^PA[5]; + w2.word ^= F(w1)^PA[4]; w1.word ^= F(w2)^PA[3]; + w2.word ^= F(w1)^PA[2]; w1.word ^= F(w2)^PA[1]; + w2.word ^= PA[0]; + + Bu::swap( w1, w2 ); + + w1.word = htobe32( w1.word ); + w2.word = htobe32( w2.word ); + } + + inline void keyEncipher( Word &w1, Word &w2 ) + { + w1.word ^= PA[0]; + w2.word ^= F(w1)^PA[1]; w1.word ^= F(w2)^PA[2]; + w2.word ^= F(w1)^PA[3]; w1.word ^= F(w2)^PA[4]; + w2.word ^= F(w1)^PA[5]; w1.word ^= F(w2)^PA[6]; + w2.word ^= F(w1)^PA[7]; w1.word ^= F(w2)^PA[8]; + w2.word ^= F(w1)^PA[9]; w1.word ^= F(w2)^PA[10]; + w2.word ^= F(w1)^PA[11]; w1.word ^= F(w2)^PA[12]; + w2.word ^= F(w1)^PA[13]; w1.word ^= F(w2)^PA[14]; + w2.word ^= F(w1)^PA[15]; w1.word ^= F(w2)^PA[16]; + w2.word ^= PA[17]; + + Bu::swap( w1, w2 ); + } + }; + + typedef CipherModeEcb<8, Blowfish<1> > BlowfishEcb; + typedef CipherModeCfb<8, Blowfish<1> > BlowfishCfb; + typedef CipherModeCbc<8, Blowfish<1> > BlowfishCbc; + typedef CipherModeOfb<8, Blowfish<1> > BlowfishOfb; +}; + +#endif diff --git a/src/unstable/cipher.cpp b/src/unstable/cipher.cpp new file mode 100644 index 0000000..e1ed0e5 --- /dev/null +++ b/src/unstable/cipher.cpp @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2007-2012 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "bu/cipher.h" + + diff --git a/src/unstable/cipher.h b/src/unstable/cipher.h new file mode 100644 index 0000000..eed73af --- /dev/null +++ b/src/unstable/cipher.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2007-2012 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#ifndef BU_CIPHER_H +#define BU_CIPHER_H + +#include "bu/filter.h" +#include "bu/util.h" + +namespace Bu +{ + /** + * Represents a nice base class for a stream filter block encryption scheme. + * This class handles efficient caching during reading and writing, + * encrypting and decrypting for block ciphers. For each individual cipher + * you only have to worry about the block encryption and decryption. Cipher + * modes are handled with seperate classes, see Bu::CipherModeCbc, + * Bu::CipherModeCfb, Bu::CipherModeEcb, and Bu::CipherModeOfb. + * + * + */ + template + class Cipher : public Bu::Filter + { + public: + Cipher( Bu::Stream &rNext ) : + Bu::Filter( rNext ), + iReadBufFill( 0 ), + iReadBufPos( 0 ), + iWriteBufFill( 0 ) + { + } + + virtual ~Cipher() + { + } + + virtual void start() + { + } + + virtual Bu::size stop() + { + flush(); + return 0; + } + + virtual Bu::size read( void *pBuf, Bu::size iBytes ) + { + Bu::size iRead = 0; + while( iRead < iBytes ) + { + if( iReadBufFill < iBlockSize ) + { + int iR = rNext.read( + aReadBuf+iReadBufFill, + iBlockSize-iReadBufFill + ); + if( iR == 0 ) + return iRead; + + iReadBufFill += iR; + + if( iReadBufFill == iBlockSize ) + decipher( aReadBuf ); + } + + if( iReadBufFill == iBlockSize ) + { + int iCpy = Bu::buMin( (int)(iBytes-iRead), iBlockSize-iReadBufPos ); + memcpy( ((char *)pBuf)+iRead, aReadBuf+iReadBufPos, iCpy ); + iRead += iCpy; + iReadBufPos += iCpy; + if( iReadBufPos == iBlockSize ) + { + iReadBufPos = iReadBufFill = 0; + } + } + } + + return iRead; + } + + virtual Bu::size write( const void *pBuf, Bu::size iBytes ) + { + Bu::size iPos = 0; + + while( iPos < iBytes ) + { + int iLeft = Bu::buMin((int)(iBytes-iPos),iBlockSize-iWriteBufFill); + memcpy( aWriteBuf+iWriteBufFill, (char *)pBuf+iPos, iLeft ); + iPos += iLeft; + iWriteBufFill += iLeft; + if( iWriteBufFill == iBlockSize ) + { + encipher( aWriteBuf ); + rNext.write( aWriteBuf, iBlockSize ); + iWriteBufFill = 0; + } + } + + return iPos; + } + + virtual void flush() + { + if( iWriteBufFill > 0 && iWriteBufFill < iBlockSize ) + { + memset( aWriteBuf+iWriteBufFill, 0, iBlockSize-iWriteBufFill ); + encipher( aWriteBuf ); + rNext.write( aWriteBuf, iBlockSize ); + iWriteBufFill = 0; + } + rNext.flush(); + } + + using Bu::Stream::read; + using Bu::Stream::write; + + protected: + virtual void encipher( void *pData )=0; + virtual void decipher( void *pData )=0; + + private: + char aReadBuf[iBlockSize]; + char aWriteBuf[iBlockSize]; + int iReadBufFill; + int iReadBufPos; + int iWriteBufFill; + }; +}; + +#endif diff --git a/src/unstable/ciphermodecbc.cpp b/src/unstable/ciphermodecbc.cpp new file mode 100644 index 0000000..169c1d3 --- /dev/null +++ b/src/unstable/ciphermodecbc.cpp @@ -0,0 +1,2 @@ +#include "ciphermodecbc.h" + diff --git a/src/unstable/ciphermodecbc.h b/src/unstable/ciphermodecbc.h new file mode 100644 index 0000000..19fdd7d --- /dev/null +++ b/src/unstable/ciphermodecbc.h @@ -0,0 +1,59 @@ +#ifndef BU_MODE_CBC_H +#define BU_MODE_CBC_H + +#include "bu/filter.h" +#include "bu/string.h" + +namespace Bu +{ + /** + * Cipher-block chaining mode. The Initialization Vector (IV) is fed into + * the first block, then each subsequent block is fed into the next making + * each block dependant on all previous blocks. + */ + template + class CipherModeCbc : public CipherType + { + public: + CipherModeCbc(class Stream &rNext ) : + CipherType( rNext ), + bStart( true ) + { + memset( aVector, 0, iBlockSize ); + } + + virtual ~CipherModeCbc() + { + } + + void setIv( const Bu::String &sIv ) + { + memcpy( aVector, sIv.getStr(), iBlockSize ); + } + + protected: + void decipher( void *pBuf ) + { + uint8_t aTmp[iBlockSize]; + memcpy( aTmp, pBuf, iBlockSize ); + CipherType::decipher( pBuf ); + for( int j = 0; j < iBlockSize; j++ ) + ((uint8_t *)pBuf)[j] ^= aVector[j]; + memcpy( aVector, aTmp, iBlockSize ); + } + + void encipher( void *pBuf ) + { + for( int j = 0; j < iBlockSize; j++ ) + ((uint8_t *)pBuf)[j] ^= aVector[j]; + CipherType::encipher( pBuf ); + memcpy( aVector, pBuf, iBlockSize ); + } + + private: + bool bStart; + uint8_t aVector[iBlockSize]; + }; +}; + +#endif diff --git a/src/unstable/ciphermodecfb.cpp b/src/unstable/ciphermodecfb.cpp new file mode 100644 index 0000000..271d371 --- /dev/null +++ b/src/unstable/ciphermodecfb.cpp @@ -0,0 +1,2 @@ +#include "ciphermodecfb.h" + diff --git a/src/unstable/ciphermodecfb.h b/src/unstable/ciphermodecfb.h new file mode 100644 index 0000000..1c9c5e9 --- /dev/null +++ b/src/unstable/ciphermodecfb.h @@ -0,0 +1,59 @@ +#ifndef BU_MODE_CFB_H +#define BU_MODE_CFB_H + +#include "bu/filter.h" +#include "bu/string.h" + +namespace Bu +{ + /** + * Cipher Feedback mode. This is very similar to the Cipher-block chaining + * mode, with a slight tweak (Bu::CipherModeCbc). Each block is still + * dependant on all previous blocks. Any corruption and the entire stream + * will be corrupt. + */ + template + class CipherModeCfb : public CipherType + { + public: + CipherModeCfb(class Stream &rNext ) : + CipherType( rNext ), + bStart( true ) + { + memset( aVector, 0, iBlockSize ); + } + + virtual ~CipherModeCfb() + { + } + + void setIv( const Bu::String &sIv ) + { + memcpy( aVector, sIv.getStr(), iBlockSize ); + } + + protected: + void decipher( void *pBuf ) + { + uint8_t aTmp[iBlockSize]; + memcpy( aTmp, pBuf, iBlockSize ); + CipherType::encipher( aVector ); + for( int j = 0; j < iBlockSize; j++ ) + ((uint8_t *)pBuf)[j] ^= aVector[j]; + memcpy( aVector, aTmp, iBlockSize ); + } + + void encipher( void *pBuf ) + { + CipherType::encipher( aVector ); + for( int j = 0; j < iBlockSize; j++ ) + aVector[j] = ((uint8_t *)pBuf)[j] ^= aVector[j]; + } + + private: + bool bStart; + uint8_t aVector[iBlockSize]; + }; +}; + +#endif diff --git a/src/unstable/ciphermodeecb.cpp b/src/unstable/ciphermodeecb.cpp new file mode 100644 index 0000000..8856304 --- /dev/null +++ b/src/unstable/ciphermodeecb.cpp @@ -0,0 +1 @@ +#include "ciphermodeecb.h" diff --git a/src/unstable/ciphermodeecb.h b/src/unstable/ciphermodeecb.h new file mode 100644 index 0000000..c4a7f23 --- /dev/null +++ b/src/unstable/ciphermodeecb.h @@ -0,0 +1,40 @@ +#ifndef BU_MODE_ECB_H +#define BU_MODE_ECB_H + +namespace Bu +{ + /** + * Electronic Code Book mode. This cipher mode is the simplest, it's + * effectively a pass-through mode. It's the same as using the encryption + * scheme without a mode, but at least you absolutely know that you've got + * the correct mode. I recommend using this instead of the raw mode if for + * no other reason than it makes your code more self-documenting, and with + * optomization shouldn't add any extra calls to your code. + */ + template + class CipherModeEcb : public CipherType + { + public: + CipherModeEcb( class Stream &rNext ) : + CipherType( rNext ) + { + } + + virtual ~CipherModeEcb() + { + } + + protected: + virtual void decipher( void *pBuf ) + { + CipherType::decipher( pBuf ); + } + + virtual void encipher( void *pBuf ) + { + CipherType::encipher( pBuf ); + } + }; +}; + +#endif diff --git a/src/unstable/ciphermodeofb.cpp b/src/unstable/ciphermodeofb.cpp new file mode 100644 index 0000000..bebbce2 --- /dev/null +++ b/src/unstable/ciphermodeofb.cpp @@ -0,0 +1,2 @@ +#include "ciphermodeofb.h" + diff --git a/src/unstable/ciphermodeofb.h b/src/unstable/ciphermodeofb.h new file mode 100644 index 0000000..19d0f83 --- /dev/null +++ b/src/unstable/ciphermodeofb.h @@ -0,0 +1,65 @@ +#ifndef BU_MODE_OFB_H +#define BU_MODE_OFB_H + +#include "bu/filter.h" +#include "bu/string.h" + +namespace Bu +{ + /** + * Output Feedback Mode. This cipher mode is one of the most resiliant. + * Instead of encrypting your data directly it encrypts a "key stream" using + * the initialization vector, and then XORs those blocks with your stream + * blocks. This means that an error in your stream will still produce an + * error in the output, but it will not propegate. Also, with most + * encryption schemes error correction codes on the source data will still + * work on the encrypted data or decrypted output. + */ + template + class CipherModeOfb : public CipherType + { + public: + CipherModeOfb(class Stream &rNext ) : + CipherType( rNext ), + bStart( true ) + { + memset( aVector, 0, iBlockSize ); + } + + virtual ~CipherModeOfb() + { + } + + void setIv( const Bu::String &sIv ) + { + memcpy( aVector, sIv.getStr(), iBlockSize ); + } + + protected: + void decipher( void *pBuf ) + { + CipherType::encipher( aVector ); + uint8_t aTmp[iBlockSize]; + memcpy( aTmp, aVector, iBlockSize ); + for( int j = 0; j < iBlockSize; j++ ) + ((uint8_t *)pBuf)[j] ^= aVector[j]; + memcpy( aVector, aTmp, iBlockSize ); + } + + void encipher( void *pBuf ) + { + CipherType::encipher( aVector ); + uint8_t aTmp[iBlockSize]; + memcpy( aTmp, aVector, iBlockSize ); + for( int j = 0; j < iBlockSize; j++ ) + ((uint8_t *)pBuf)[j] ^= aVector[j]; + memcpy( aVector, aTmp, iBlockSize ); + } + + private: + bool bStart; + uint8_t aVector[iBlockSize]; + }; +}; + +#endif -- cgit v1.2.3