From 32e73057b064833f1931bf134ad56ef3f6642d9b Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Wed, 5 Feb 2020 17:03:15 +0100 Subject: [PATCH] fixed a bug in RC6 --- include/rc6_generic.hpp | 80 +++++++++++++++++++++++++++++++++-------- tests/rc6_generic.cpp | 49 +++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 16 deletions(-) diff --git a/include/rc6_generic.hpp b/include/rc6_generic.hpp index a5f2ce3..5322583 100644 --- a/include/rc6_generic.hpp +++ b/include/rc6_generic.hpp @@ -52,17 +52,19 @@ size_t lg(uint64_t v) -template +template class RC6 { static constexpr size_t word_size = 8*sizeof(word_t); - static word_t r_l(const word_t& w, size_t v) { - return (w << v) | ( w >> (sizeof(w)-v)); + + constexpr static word_t r_l(const word_t& w, size_t v) { + return (w << v) | ( w >> (word_size-v)); } - static word_t r_r(const word_t& w, size_t v) { - return (w >> v) | ( w << (sizeof(w)-v)); + constexpr static word_t r_r(const word_t& w, size_t v) { + return (w >> v) | ( w << (word_size-v)); } + class RC6_KeySched { public: static constexpr size_t c = (b+word_size-1)/word_size; @@ -73,6 +75,7 @@ class RC6 { public: RC6_KeySched(std::array L) { + assert(r_l(r_r(13,13),13) == 13); S[0] = P; for(auto it = S.begin()+1; it < S.end(); ++it) { @@ -95,6 +98,26 @@ class RC6 { const word_t& operator[](const size_t pos) { return S[pos]; } + + auto begin() + { + return S.begin(); + } + + auto end() + { + return S.end(); + } + + auto rbegin() + { + return S.rbegin(); + } + + auto rend() + { + return S.rend(); + } }; RC6_KeySched S; @@ -108,26 +131,55 @@ public: : S(key) {} - void encrypt(block_type& plaintext) { + block_type encrypt(block_type plaintext) { auto& A = plaintext[0]; auto& B = plaintext[1]; auto& C = plaintext[2]; auto& D = plaintext[3]; - B += S[0]; - D += S[1]; + auto it = S.begin(); - for(size_t i = 1; i <= r; ++i) + B += *(it++); + D += *(it++); + + for(size_t i = 0; i < r; ++i) { + auto u = r_l( D * ( 2 * D + 1 ), 5); auto t = r_l( B * ( 2 * B + 1 ), 5); + A = r_l((A ^ t), u % word_size) + *(it++); + C = r_l((C ^ u), t % word_size) + *(it++); + std::rotate(plaintext.begin(), plaintext.begin()+1, plaintext.end()); + } + + A += *(it++); + C += *(it++); + assert(it == S.end()); + return plaintext; + } + + block_type decrypt(block_type plaintext) { + auto& A = plaintext[0]; + auto& B = plaintext[1]; + auto& C = plaintext[2]; + auto& D = plaintext[3]; + auto it = S.rbegin(); + + C -= *(it++); + A -= *(it++); + + for(size_t i = 0; i < r; ++i) + { + std::rotate(plaintext.begin(), plaintext.end()-1, plaintext.end()); auto u = r_l( D * ( 2 * D + 1 ), 5); - A = r_l((A ^ t), u % word_size) + S[ 2 * i ]; - C = r_l((C ^ u), t % word_size) + S[ 2 * i + 1 ]; - auto tmp = A; A = B; B = C; C = D; D = tmp; + auto t = r_l( B * ( 2 * B + 1 ), 5); + C = r_r( (C - *(it++)) , t % word_size) ^ u ; + A = r_r( (A - *(it++)) , u % word_size) ^ t ; } - A += S[2*r+2]; - C += S[2*r+3]; + D -= *(it++); + B -= *(it++); + assert(it == S.rend()); + return plaintext; } }; \ No newline at end of file diff --git a/tests/rc6_generic.cpp b/tests/rc6_generic.cpp index 466ba53..41c8809 100644 --- a/tests/rc6_generic.cpp +++ b/tests/rc6_generic.cpp @@ -21,7 +21,7 @@ struct RC6test : public test_scaffold { std::cout << std::hex << a; auto cipher = rc(key); - cipher.encrypt(plaintext); + plaintext = cipher.encrypt(plaintext); std::cout<<"\nkey__:"; for(auto a : key) @@ -40,4 +40,49 @@ struct RC6test : public test_scaffold { } }; -append_test dummy_szfhu5463(new RC6test{}); \ No newline at end of file +append_test dummy_szfhu5463(new RC6test{}); + +struct RC6test2 : public test_scaffold { + RC6test2() { + name = __FILE__ ":2"; + } + + virtual int run() { + using rc = RC6<>; + + rc::key_type key = {0,0,0,0}; + rc::block_type plaintext = {0,0,0,0}; + rc::block_type expected{0,0,0,0}; + + + std::cout<<"plain:"; + for(auto a : plaintext) + std::cout << std::hex << a; + + auto cipher = rc(key); + plaintext = cipher.encrypt(plaintext); + + std::cout<<"\nkey__:"; + for(auto a : key) + std::cout << std::hex << a; + + std::cout<<"\nciphe:"; + for(auto a : plaintext) + std::cout << std::hex << a; + + plaintext = cipher.decrypt(plaintext); + + std::cout<<"\ncidec:"; + for(auto a : plaintext) + std::cout << std::hex << a; + + std::cout<<"\nexpec:"; + for(auto a : expected) + std::cout << std::hex << a; + std::cout << std::endl; + + return plaintext != expected; + } +}; + +append_test dummy_szmltz63(new RC6test2{}); \ No newline at end of file