From 99f170b8888d806204c17a211c189db406147d6b Mon Sep 17 00:00:00 2001 From: Nils Maier Date: Tue, 24 Sep 2013 02:22:00 +0200 Subject: [PATCH] Provide internal ARC4 implementation Now you can build bittorrent support without without external libraries, meaning you can skip libnettle, libgmp, libgcrypt, GnuTLS and OpenSSL on OSX (for now). --- configure.ac | 7 ++-- src/ARC4Encryptor.h | 24 ++---------- src/InternalARC4Encryptor.cc | 73 ++++++++++++++++++++++++++++++++++++ src/InternalARC4Encryptor.h | 60 +++++++++++++++++++++++++++++ src/Makefile.am | 4 ++ test/ARC4Test.cc | 8 ++-- 6 files changed, 150 insertions(+), 26 deletions(-) create mode 100644 src/InternalARC4Encryptor.cc create mode 100644 src/InternalARC4Encryptor.h diff --git a/configure.ac b/configure.ac index c61e8be1..b1220a88 100644 --- a/configure.ac +++ b/configure.ac @@ -518,12 +518,13 @@ fi if test "x$have_libnettle" = "xyes" || test "x$have_libgcrypt" = "xyes" || test "x$have_openssl" = "xyes"; then - have_rc4=yes + AM_CONDITIONAL([USE_INTERNAL_ARC4], false) +else + AC_DEFINE([USE_INTERNAL_ARC4], [1], [Define to 1 if internal ARC4 support is enabled.]) + AM_CONDITIONAL([USE_INTERNAL_ARC4], true) fi - if test "x$enable_bittorrent" = "xyes" && - test "x$have_rc4" = "xyes" && test "x$enable_message_digest" = "xyes"; then AC_DEFINE([ENABLE_BITTORRENT], [1], [Define to 1 if BitTorrent support is enabled.]) diff --git a/src/ARC4Encryptor.h b/src/ARC4Encryptor.h index 1eb101ad..96c55936 100644 --- a/src/ARC4Encryptor.h +++ b/src/ARC4Encryptor.h @@ -36,31 +36,15 @@ #define D_ARC4_ENCRYPTOR_H #include "common.h" -#ifdef HAVE_LIBNETTLE + +#ifdef USE_INTERNAL_ARC4 +# include "InternalARC4Encryptor.h" +#elif HAVE_LIBNETTLE # include "LibnettleARC4Encryptor.h" #elif HAVE_LIBGCRYPT # include "LibgcryptARC4Encryptor.h" #elif HAVE_OPENSSL # include "LibsslARC4Encryptor.h" -#else - -// provide empty implementation to compile sources without both libgcrypt and -// openssl installed -namespace aria2 { - -class ARC4Encryptor { -public: - ARC4Encryptor() {} - - ~ARC4Encryptor() {} - - void init(const unsigned char* key, size_t keyLength) {} - - void encrypt(size_t len, unsigned char* out, const unsigned char* in); -}; - -} // namespace aria2 - #endif #endif // D_ARC4_ENCRYPTOR_H diff --git a/src/InternalARC4Encryptor.cc b/src/InternalARC4Encryptor.cc new file mode 100644 index 00000000..67c939ef --- /dev/null +++ b/src/InternalARC4Encryptor.cc @@ -0,0 +1,73 @@ +/* */ + +#include "InternalARC4Encryptor.h" + +namespace aria2 { + +ARC4Encryptor::~ARC4Encryptor() +{ + for (auto& c : state_) c = 0; + i = j = 0; +} +void ARC4Encryptor::init(const unsigned char* key, size_t keyLength) +{ + j = 0; + for (auto& c : state_) c = j++; + + j = 0; + for (i = 0; i < sizeof(state_); ++i) { + j = (j + state_[i] + key[i % keyLength]) & 0xff; + auto tmp = state_[i]; + state_[i] = state_[j]; + state_[j] = tmp; + } + i = j = 0; +} + +void ARC4Encryptor::encrypt(size_t len, unsigned char* out, + const unsigned char* in) +{ + for (auto c = 0; c < len; ++c) { + i = (i + 1) & 0xff; + j = (j + state_[i]) & 0xff; + auto sj = state_[i]; + auto si = state_[i] = state_[j]; + state_[j] = sj; + out[c] = in[c] ^ state_[(si + sj) & 0xff]; + } +} + +} // namespace aria2 diff --git a/src/InternalARC4Encryptor.h b/src/InternalARC4Encryptor.h new file mode 100644 index 00000000..ab33e604 --- /dev/null +++ b/src/InternalARC4Encryptor.h @@ -0,0 +1,60 @@ +/* */ +#ifndef D_INTERNAL_ARC4_ENCRYPTOR_H +#define D_INTERNAL_ARC4_ENCRYPTOR_H + +#include "common.h" + +namespace aria2 { + +class ARC4Encryptor { +private: + unsigned char state_[256]; + unsigned i, j; + +public: + ARC4Encryptor() {} + ~ARC4Encryptor(); + + void init(const unsigned char* key, size_t keyLength); + + // Encrypts data in in buffer to out buffer. in and out can be the + // same buffer. + void encrypt(size_t len, unsigned char* out, const unsigned char* in); +}; + +} // namespace aria2 + +#endif // D_INTERNAL_ARC4_ENCRYPTOR_H diff --git a/src/Makefile.am b/src/Makefile.am index f4466018..3d492753 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -337,6 +337,10 @@ if USE_INTERNAL_BIGNUM SRCS += InternalDHKeyExchange.cc InternalDHKeyExchange.h bignum.h endif +if USE_INTERNAL_ARC4 +SRCS += InternalARC4Encryptor.cc InternalARC4Encryptor.h +endif + if USE_INTERNAL_MD SRCS += InternalMessageDigestImpl.cc sha1.c md5.c endif # USE_WINDOWS_MD diff --git a/test/ARC4Test.cc b/test/ARC4Test.cc index 7666728a..4d91d31d 100644 --- a/test/ARC4Test.cc +++ b/test/ARC4Test.cc @@ -37,14 +37,16 @@ void ARC4Test::testEncrypt() unsigned char encrypted[LEN]; unsigned char decrypted[LEN]; - enc.encrypt(LEN, encrypted, key); - dec.encrypt(LEN, decrypted, encrypted); + enc.encrypt(LEN, encrypted, key); + CPPUNIT_ASSERT(memcmp(key, encrypted, LEN) != 0); + dec.encrypt(LEN, decrypted, encrypted); CPPUNIT_ASSERT(memcmp(key, decrypted, LEN) == 0); + // once more enc.encrypt(LEN, encrypted, key); + CPPUNIT_ASSERT(memcmp(key, encrypted, LEN) != 0); dec.encrypt(LEN, decrypted, encrypted); - CPPUNIT_ASSERT(memcmp(key, decrypted, LEN) == 0); }