diff --git a/bfinit.cpp b/bfinit.cpp index 06db2096..5c4a5db4 100644 --- a/bfinit.cpp +++ b/bfinit.cpp @@ -3,16 +3,18 @@ NAMESPACE_BEGIN(CryptoPP) -const word32 Blowfish::Base::p_init[Blowfish::ROUNDS+2] = +template +const word32 Blowfish_Base::p_init[Info::ROUNDS+2] = { 608135816U, 2242054355U, 320440878U, 57701188U, 2752067618U, 698298832U, 137296536U, 3964562569U, 1160258022U, 953160567U, 3193202383U, 887688300U, 3232508343U, 3380367581U, 1065670069U, 3041331479U, 2450970073U, 2306472731U -} ; +}; -const word32 Blowfish::Base::s_init[4*256] = { +template +const word32 Blowfish_Base::s_init[4*256] = { 3509652390U, 2564797868U, 805139163U, 3491422135U, 3101798381U, 1780907670U, 3128725573U, 4046225305U, 614570311U, 3012652279U, 134345442U, 2240740374U, @@ -274,4 +276,10 @@ const word32 Blowfish::Base::s_init[4*256] = { 3075367218U, 3463963227U, 1469046755U, 985887462U }; +template const word32 Blowfish_Base::p_init[Blowfish_Info::ROUNDS+2]; +template const word32 Blowfish_Base::s_init[4*256]; + +template const word32 Blowfish_Base::p_init[BlowfishCompat_Info::ROUNDS+2]; +template const word32 Blowfish_Base::s_init[4*256]; + NAMESPACE_END diff --git a/blowfish.cpp b/blowfish.cpp index e615da3b..c20643f1 100644 --- a/blowfish.cpp +++ b/blowfish.cpp @@ -6,9 +6,10 @@ NAMESPACE_BEGIN(CryptoPP) -void Blowfish::Base::UncheckedSetKey(const byte *key_string, unsigned int keylength, const NameValuePairs &) +template +void Blowfish_Base::UncheckedSetKey(const byte *key_string, unsigned int keylength, const NameValuePairs &) { - AssertValidKeyLength(keylength); + this->AssertValidKeyLength(keylength); unsigned i, j=0, k; word32 data, dspace[2] = {0, 0}; @@ -17,7 +18,7 @@ void Blowfish::Base::UncheckedSetKey(const byte *key_string, unsigned int keylen memcpy(sbox, s_init, sizeof(s_init)); // Xor key string into encryption key vector - for (i=0 ; iIsForwardTransformation()) + for (i=0; i<(Info::ROUNDS+2)/2; i++) + std::swap(pbox[i], pbox[Info::ROUNDS+1-i]); } // this version is only used to make pbox and sbox -void Blowfish::Base::crypt_block(const word32 in[2], word32 out[2]) const +template +void Blowfish_Base::crypt_block(const word32 in[2], word32 out[2]) const { word32 left = in[0]; word32 right = in[1]; @@ -51,7 +53,7 @@ void Blowfish::Base::crypt_block(const word32 in[2], word32 out[2]) const left ^= p[0]; - for (unsigned i=0; i +void Blowfish_Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const { - typedef BlockGetAndPut Block; + typedef BlockGetAndPut Block; word32 left, right; Block::Get(inBlock)(left)(right); @@ -80,7 +83,7 @@ void Blowfish::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBloc left ^= p[0]; - for (unsigned i=0; i; +template class Blowfish_Base; + NAMESPACE_END diff --git a/blowfish.h b/blowfish.h index 5f34609f..855795b2 100644 --- a/blowfish.h +++ b/blowfish.h @@ -11,6 +11,25 @@ NAMESPACE_BEGIN(CryptoPP) +/// \brief Class specific implementation and overrides used to operate the cipher. +/// \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions +template +class CRYPTOPP_NO_VTABLE Blowfish_Base : public BlockCipherImpl +{ +public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + void UncheckedSetKey(const byte *key_string, unsigned int keylength, const NameValuePairs ¶ms); + +private: + void crypt_block(const word32 in[2], word32 out[2]) const; + + static const word32 p_init[Info::ROUNDS+2]; + static const word32 s_init[4*256]; + + FixedSizeSecBlock pbox; + FixedSizeSecBlock sbox; +}; + /// \brief Blowfish block cipher information struct Blowfish_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 4, 56>, public FixedRounds<16> { @@ -21,34 +40,31 @@ struct Blowfish_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 4, /// \brief Blowfish block cipher /// \since Crypto++ 1.0 -class Blowfish : public Blowfish_Info, public BlockCipherDocumentation +struct Blowfish : public Blowfish_Info, public BlockCipherDocumentation { - /// \brief Class specific implementation and overrides used to operate the cipher. - /// \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions - class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl - { - public: - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; - void UncheckedSetKey(const byte *key_string, unsigned int keylength, const NameValuePairs ¶ms); - - private: - void crypt_block(const word32 in[2], word32 out[2]) const; - - static const word32 p_init[ROUNDS+2]; - static const word32 s_init[4*256]; - - FixedSizeSecBlock pbox; - FixedSizeSecBlock sbox; - }; - -public: - typedef BlockCipherFinal Encryption; - typedef BlockCipherFinal Decryption; + typedef BlockCipherFinal > Encryption; + typedef BlockCipherFinal > Decryption; }; typedef Blowfish::Encryption BlowfishEncryption; typedef Blowfish::Decryption BlowfishDecryption; +/// \brief BlowfishCompat block cipher information +struct BlowfishCompat_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 4, 56>, public FixedRounds<16> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BlowfishCompat";} +}; + +/// \brief BlowfishCompat block cipher +struct BlowfishCompat : public BlowfishCompat_Info, public BlockCipherDocumentation +{ + typedef BlockCipherFinal > Encryption; + typedef BlockCipherFinal > Decryption; +}; + +typedef BlowfishCompat::Encryption BlowfishCompatEncryption; +typedef BlowfishCompat::Decryption BlowfishCompatDecryption; + NAMESPACE_END #endif diff --git a/test.cpp b/test.cpp index be72405e..4cc5605f 100644 --- a/test.cpp +++ b/test.cpp @@ -1023,6 +1023,7 @@ bool Validate(int alg, bool thorough) case 101: result = ValidateSIMECK(); break; case 102: result = ValidateSIMON(); break; case 103: result = ValidateSPECK(); break; + case 104: result = ValidateBlowfishCompat(); break; case 110: result = ValidateSHA3(); break; case 111: result = ValidateSHAKE(); break; diff --git a/validat3.cpp b/validat3.cpp index b5dcd6d2..64370718 100644 --- a/validat3.cpp +++ b/validat3.cpp @@ -135,6 +135,7 @@ bool ValidateAll(bool thorough) pass=ValidateARC4() && pass; pass=ValidateRC5() && pass; pass=ValidateBlowfish() && pass; + pass=ValidateBlowfishCompat() && pass; pass=ValidateThreeWay() && pass; pass=ValidateGOST() && pass; pass=ValidateSHARK() && pass; diff --git a/validat4.cpp b/validat4.cpp index 59a8c35d..143122da 100644 --- a/validat4.cpp +++ b/validat4.cpp @@ -1126,6 +1126,69 @@ bool ValidateBlowfish() return pass1 && pass2 && pass3; } +bool ValidateBlowfishCompat() +{ + std::cout << "\nBlowfishCompat validation suite running...\n\n"; + bool pass1 = true, pass2 = true, pass3 = true, fail; + + BlowfishCompatEncryption enc1; // 32 to 448-bits (4 to 56-bytes) + pass1 = enc1.StaticGetValidKeyLength(3) == 4 && pass1; + pass1 = enc1.StaticGetValidKeyLength(4) == 4 && pass1; + pass1 = enc1.StaticGetValidKeyLength(5) == 5 && pass1; + pass1 = enc1.StaticGetValidKeyLength(8) == 8 && pass1; + pass1 = enc1.StaticGetValidKeyLength(16) == 16 && pass1; + pass1 = enc1.StaticGetValidKeyLength(24) == 24 && pass1; + pass1 = enc1.StaticGetValidKeyLength(32) == 32 && pass1; + pass1 = enc1.StaticGetValidKeyLength(56) == 56 && pass1; + pass1 = enc1.StaticGetValidKeyLength(57) == 56 && pass1; + pass1 = enc1.StaticGetValidKeyLength(60) == 56 && pass1; + pass1 = enc1.StaticGetValidKeyLength(64) == 56 && pass1; + pass1 = enc1.StaticGetValidKeyLength(128) == 56 && pass1; + + BlowfishCompatDecryption dec1; // 32 to 448-bits (4 to 56-bytes) + pass2 = dec1.StaticGetValidKeyLength(3) == 4 && pass2; + pass2 = dec1.StaticGetValidKeyLength(4) == 4 && pass2; + pass2 = dec1.StaticGetValidKeyLength(5) == 5 && pass2; + pass2 = dec1.StaticGetValidKeyLength(8) == 8 && pass2; + pass2 = dec1.StaticGetValidKeyLength(16) == 16 && pass2; + pass2 = dec1.StaticGetValidKeyLength(24) == 24 && pass2; + pass2 = dec1.StaticGetValidKeyLength(32) == 32 && pass2; + pass2 = dec1.StaticGetValidKeyLength(56) == 56 && pass2; + pass2 = dec1.StaticGetValidKeyLength(57) == 56 && pass2; + pass2 = dec1.StaticGetValidKeyLength(60) == 56 && pass2; + pass2 = dec1.StaticGetValidKeyLength(64) == 56 && pass2; + pass2 = dec1.StaticGetValidKeyLength(128) == 56 && pass2; + std::cout << (pass1 && pass2 ? "passed:" : "FAILED:") << " Algorithm key lengths\n"; + + HexEncoder output(new FileSink(std::cout)); + const char *key[]={"abcdefghijklmnopqrstuvwxyz", "Who is John Galt?"}; + byte *plain[]={(byte *)"BLOWFISH", (byte *)"\xfe\xdc\xba\x98\x76\x54\x32\x10"}; + byte *cipher[]={(byte *)"\x82\x4d\x92\x0d\x00\x4d\x7e\xe3", (byte *)"\xd4\xf9\xb0\x06\xd3\x84\x92\x7e"}; + byte out[8], outplain[8]; + + for (int i=0; i<2; i++) + { + ECB_Mode::Encryption enc2((byte *)key[i], strlen(key[i])); + enc2.ProcessData(out, plain[i], 8); + fail = memcmp(out, cipher[i], 8) != 0; + + ECB_Mode::Decryption dec2((byte *)key[i], strlen(key[i])); + dec2.ProcessData(outplain, cipher[i], 8); + fail = fail || memcmp(outplain, plain[i], 8); + pass3 = pass3 && !fail; + + std::cout << (fail ? "FAILED " : "passed "); + std::cout << '\"' << key[i] << '\"'; + for (int j=0; j<(signed int)(30-strlen(key[i])); j++) + std::cout << ' '; + output.Put(outplain, 8); + std::cout << " "; + output.Put(out, 8); + std::cout << std::endl; + } + return pass1 && pass2 && pass3; +} + bool ValidateThreeWay() { std::cout << "\n3-WAY validation suite running...\n\n"; diff --git a/validate.h b/validate.h index 4b2ca683..c17c6da1 100644 --- a/validate.h +++ b/validate.h @@ -83,6 +83,7 @@ bool ValidateARC4(); bool ValidateRC5(); bool ValidateBlowfish(); +bool ValidateBlowfishCompat(); bool ValidateThreeWay(); bool ValidateGOST(); bool ValidateSHARK();