From d49fc3aeac4daa65416751f94943b6611ad247d3 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 10 Apr 2012 08:32:23 +0000 Subject: Rearranged the Cipher system, and added four modes of operation. It's pretty slick, really, and we actually support four of the most common modes. Blowfish is still a template, but it doesn't really need to be anymore... --- src/experimental/blowfish.cpp | 405 ------------------------------------ src/experimental/blowfish.h | 415 ++++++++++++++++++++++++++++++++++++- src/experimental/cipher.h | 2 +- src/experimental/ciphermodecbc.cpp | 2 + src/experimental/ciphermodecbc.h | 54 +++++ src/experimental/ciphermodecfb.cpp | 2 + src/experimental/ciphermodecfb.h | 53 +++++ src/experimental/ciphermodeecb.cpp | 1 + src/experimental/ciphermodeecb.h | 32 +++ src/experimental/ciphermodeofb.cpp | 2 + src/experimental/ciphermodeofb.h | 56 +++++ src/tests/blowfish.cpp | 16 +- 12 files changed, 619 insertions(+), 421 deletions(-) create mode 100644 src/experimental/ciphermodecbc.cpp create mode 100644 src/experimental/ciphermodecbc.h create mode 100644 src/experimental/ciphermodecfb.cpp create mode 100644 src/experimental/ciphermodecfb.h create mode 100644 src/experimental/ciphermodeecb.cpp create mode 100644 src/experimental/ciphermodeecb.h create mode 100644 src/experimental/ciphermodeofb.cpp create mode 100644 src/experimental/ciphermodeofb.h diff --git a/src/experimental/blowfish.cpp b/src/experimental/blowfish.cpp index 7f89f0f..d01ecd3 100644 --- a/src/experimental/blowfish.cpp +++ b/src/experimental/blowfish.cpp @@ -1,407 +1,2 @@ #include "bu/blowfish.h" -#include "bu/sio.h" - -using Bu::sio; - -#define F(x) \ - (((SB[0][x.byte.zero] + SB[1][x.byte.one]) ^ SB[2][x.byte.two]) + \ - SB[3][x.byte.three]) - -Bu::Blowfish::Blowfish( Bu::Stream &rNext ) : - Bu::Cipher<8>( rNext ) -{ -} - -Bu::Blowfish::~Blowfish() -{ - reset(); -} - -#define revBytes( x ) x = (((x&0xff)<<24)|((x&0xff00)<<8)|((x&0xff0000)>>8)|((x&0xff000000)>>24)) - -void Bu::Blowfish::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 ); -} - -void Bu::Blowfish::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 ); -} - -void Bu::Blowfish::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 ); -} - diff --git a/src/experimental/blowfish.h b/src/experimental/blowfish.h index c043b12..855ce2b 100644 --- a/src/experimental/blowfish.h +++ b/src/experimental/blowfish.h @@ -3,22 +3,78 @@ #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 ); - virtual ~Blowfish(); + Blowfish( Bu::Stream &rNext ) : + Bu::Cipher<8>( rNext ) + { + } + + virtual ~Blowfish() + { + 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/experimental/cipher.h b/src/experimental/cipher.h index 613bc88..9e6f87d 100644 --- a/src/experimental/cipher.h +++ b/src/experimental/cipher.h @@ -6,7 +6,7 @@ namespace Bu { template - class Cipher : Bu::Filter + class Cipher : public Bu::Filter { public: Cipher( Bu::Stream &rNext ) : diff --git a/src/experimental/ciphermodecbc.cpp b/src/experimental/ciphermodecbc.cpp new file mode 100644 index 0000000..169c1d3 --- /dev/null +++ b/src/experimental/ciphermodecbc.cpp @@ -0,0 +1,2 @@ +#include "ciphermodecbc.h" + diff --git a/src/experimental/ciphermodecbc.h b/src/experimental/ciphermodecbc.h new file mode 100644 index 0000000..8fbf9f6 --- /dev/null +++ b/src/experimental/ciphermodecbc.h @@ -0,0 +1,54 @@ +#ifndef BU_MODE_CBC_H +#define BU_MODE_CBC_H + +#include "bu/filter.h" +#include "bu/string.h" + +namespace Bu +{ + 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/experimental/ciphermodecfb.cpp b/src/experimental/ciphermodecfb.cpp new file mode 100644 index 0000000..271d371 --- /dev/null +++ b/src/experimental/ciphermodecfb.cpp @@ -0,0 +1,2 @@ +#include "ciphermodecfb.h" + diff --git a/src/experimental/ciphermodecfb.h b/src/experimental/ciphermodecfb.h new file mode 100644 index 0000000..dab6c2e --- /dev/null +++ b/src/experimental/ciphermodecfb.h @@ -0,0 +1,53 @@ +#ifndef BU_MODE_CFB_H +#define BU_MODE_CFB_H + +#include "bu/filter.h" +#include "bu/string.h" + +namespace Bu +{ + 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/experimental/ciphermodeecb.cpp b/src/experimental/ciphermodeecb.cpp new file mode 100644 index 0000000..8856304 --- /dev/null +++ b/src/experimental/ciphermodeecb.cpp @@ -0,0 +1 @@ +#include "ciphermodeecb.h" diff --git a/src/experimental/ciphermodeecb.h b/src/experimental/ciphermodeecb.h new file mode 100644 index 0000000..006741a --- /dev/null +++ b/src/experimental/ciphermodeecb.h @@ -0,0 +1,32 @@ +#ifndef BU_MODE_ECB_H +#define BU_MODE_ECB_H + +namespace Bu +{ + 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/experimental/ciphermodeofb.cpp b/src/experimental/ciphermodeofb.cpp new file mode 100644 index 0000000..bebbce2 --- /dev/null +++ b/src/experimental/ciphermodeofb.cpp @@ -0,0 +1,2 @@ +#include "ciphermodeofb.h" + diff --git a/src/experimental/ciphermodeofb.h b/src/experimental/ciphermodeofb.h new file mode 100644 index 0000000..8c2aa20 --- /dev/null +++ b/src/experimental/ciphermodeofb.h @@ -0,0 +1,56 @@ +#ifndef BU_MODE_OFB_H +#define BU_MODE_OFB_H + +#include "bu/filter.h" +#include "bu/string.h" + +namespace Bu +{ + 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 diff --git a/src/tests/blowfish.cpp b/src/tests/blowfish.cpp index c7486e1..293539d 100644 --- a/src/tests/blowfish.cpp +++ b/src/tests/blowfish.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include using namespace Bu; @@ -50,13 +52,13 @@ int main( int argc, char *argv[] ) for( int j = 0; j < 34; j++ ) { MemBuf mb; - Blowfish bf( mb ); + BlowfishEcb bf( mb ); bf.setPassword( decodeStr( testdat[j][0] ) ); bf.write( decodeStr( testdat[j][1] ) ); sio << "Test " << j << ": " << (mb.getString() == decodeStr( testdat[j][2] )) << " (" << encodeStr( mb.getString(), true ) << " == " << testdat[j][2] << ")" << sio.nl; mb.setPos( 0 ); - Blowfish bf2( mb ); + BlowfishEcb bf2( mb ); bf2.setPassword( decodeStr( testdat[j][0] ) ); char buf[8]; bf2.read( buf, 8 ); @@ -64,29 +66,27 @@ int main( int argc, char *argv[] ) sio << " - Back: " << (Bu::String(testdat[j][1]) == encodeStr(String(buf,8),true)) << sio.nl; } - /* { File fIn("data.plain", File::Read ); File fOut("data.crypt", File::WriteNew ); - Blowfish bOut( fOut ); + BlowfishOfb bOut( fOut ); + bOut.setIv("01234567"); bOut.setPassword("abcdefghijklmnop"); bOut.write( fIn.readAll() ); } - */ - /* { File fIn("data.java", File::Read ); File fOut("data.stuff", File::WriteNew ); - Blowfish bIn( fIn ); + BlowfishOfb bIn( fIn ); + bIn.setIv("01234567"); bIn.setPassword("abcdefghijklmnop"); char buf[64]; bIn.read( buf, 64 ); fOut.write( buf, 64 ); sio << sio.nl << "All done." << sio.nl; } - */ return 0; } -- cgit v1.2.3