diff --git a/CMakeLists.txt b/CMakeLists.txt index 43528ffff..f95771c82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ set(sources policy puff random + rsa rss session session_impl diff --git a/Jamfile b/Jamfile index 74292191f..25bc8f68c 100755 --- a/Jamfile +++ b/Jamfile @@ -414,6 +414,7 @@ SOURCES = policy puff random + rsa rss session session_impl diff --git a/include/libtorrent/Makefile.am b/include/libtorrent/Makefile.am index 64598066a..25961d1d5 100644 --- a/include/libtorrent/Makefile.am +++ b/include/libtorrent/Makefile.am @@ -80,6 +80,7 @@ nobase_include_HEADERS = \ ptime.hpp \ puff.hpp \ random.hpp \ + rsa.hpp \ rss.hpp \ session.hpp \ session_settings.hpp \ diff --git a/include/libtorrent/rsa.hpp b/include/libtorrent/rsa.hpp new file mode 100644 index 000000000..944e88d83 --- /dev/null +++ b/include/libtorrent/rsa.hpp @@ -0,0 +1,59 @@ +/* + +Copyright (c) 2011, Arvid Norberg, Magnus Jonsson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TORRENT_SIGN_HPP_INCLUDED +#define TORRENT_SIGN_HPP_INCLUDED + +#include "libtorrent/config.hpp" + +namespace libtorrent +{ + // both of these use SHA-1 as the message digest to be signed/verified + + // returns the size of the resulting signature + TORRENT_EXPORT int sign_rsa(char const* data, int data_len + , char const* private_key, int private_len + , char* signature, int sig_len); + + // returns true if the signature is valid + TORRENT_EXPORT bool verify_rsa(char const* data, int data_len + , char const* public_key, int public_len + , char const* signature, int sig_len); + + // returns false if it fails, for instance if the key + // buffers are too small. public_len and private_len + // are in-out values, set to the actual sizes + TORRENT_EXPORT bool generate_rsa_keys(char* public_key, int* public_len + , char* private_key, int* private_len, int key_size); +} + +#endif // TORRENT_SIGN_HPP_INCLUDED diff --git a/src/Makefile.am b/src/Makefile.am index ce2f5199d..5657c4d76 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -64,6 +64,7 @@ libtorrent_rasterbar_la_SOURCES = \ policy.cpp \ puff.cpp \ random.cpp \ + rsa.cpp \ rss.cpp \ session.cpp \ session_impl.cpp \ diff --git a/src/rsa.cpp b/src/rsa.cpp new file mode 100644 index 000000000..5938ec213 --- /dev/null +++ b/src/rsa.cpp @@ -0,0 +1,151 @@ +/* + +Copyright (c) 2011, Arvid Norberg, Magnus Jonsson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "libtorrent/rsa.hpp" +#include "libtorrent/hasher.hpp" + +#if defined TORRENT_USE_OPENSSL + +extern "C" +{ +#include +#include // for NID_sha1 +} + +namespace libtorrent +{ + +// returns the size of the resulting signature +int sign_rsa(char const* data, int data_len + , char const* private_key, int private_len + , char* signature, int sig_len) +{ + // convert bytestring to internal representation + // of the private key + RSA* priv = 0; + unsigned char const* key = (unsigned char const*)private_key; + priv = d2i_RSAPrivateKey(&priv, &key, private_len); + + if (RSA_size(priv) > sig_len) + { + RSA_free(priv); + return -1; + } + + // hash the data + sha1_hash digest = hasher(data, data_len).final(); + + RSA_sign(NID_sha1, &digest[0], 20, (unsigned char*)signature, (unsigned int*)&sig_len, priv); + + RSA_free(priv); + + return sig_len; +} + +// returns true if the signature is valid +bool verify_rsa(char const* data, int data_len + , char const* public_key, int public_len + , char const* signature, int sig_len) +{ + // convert bytestring to internal representation + // of the public key + RSA* pub = 0; + unsigned char const* key = (unsigned char const*)public_key; + pub = d2i_RSAPublicKey(&pub, &key, public_len); + + // hash the data + sha1_hash digest = hasher(data, data_len).final(); + + int ret = RSA_verify(NID_sha1, &digest[0], 20, (unsigned char*)signature, sig_len, pub); + + RSA_free(pub); + + return ret; +} + +bool generate_rsa_keys(char* public_key, int* public_len + , char* private_key, int* private_len, int key_size) +{ + RSA* keypair = RSA_generate_key(key_size, 3, 0, 0); + if (keypair == 0) return false; + + bool ret = false; + if (RSA_size(keypair) > *public_len) goto getout; + if (RSA_size(keypair) > *private_len) goto getout; + + unsigned char* pub = (unsigned char*)public_key; + unsigned char* priv = (unsigned char*)private_key; + *public_len = i2d_RSAPublicKey(keypair, &pub); + *private_len = i2d_RSAPrivateKey(keypair, &priv); + + ret = true; + +getout: + RSA_free(keypair); + return ret; +} + +} // namespace libtorrent + +#else + +// just stub these out for now, since they're not used anywhere yet +namespace libtorrent +{ + +// returns the size of the resulting signature +int sign_rsa(char const* data, int data_len + , char const* private_key, int private_len + , char* signature, int sig_len) +{ + return 0; +} + +// returns true if the signature is valid +bool verify_rsa(char const* data, int data_len + , char const* public_key, int public_len + , char const* signature, int sig_len) +{ + return false; +} + +bool generate_rsa_keys(char* public_key, int* public_len + , char* private_key, int* private_len, int key_size) +{ + return false; +} + +} // namespace libtorrent + +#endif + + diff --git a/test/test_primitives.cpp b/test/test_primitives.cpp index 15c541a1d..3983d14c8 100644 --- a/test/test_primitives.cpp +++ b/test/test_primitives.cpp @@ -50,6 +50,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/enum_net.hpp" #include "libtorrent/bloom_filter.hpp" #include "libtorrent/aux_/session_impl.hpp" +#include "libtorrent/rsa.hpp" #ifndef TORRENT_DISABLE_DHT #include "libtorrent/kademlia/node_id.hpp" #include "libtorrent/kademlia/routing_table.hpp" @@ -394,6 +395,30 @@ int test_main() error_code ec; int ret = 0; +#if defined TORRENT_USE_OPENSSL + // test sign_rsa and verify_rsa + char private_key[256]; + int private_len = sizeof(private_key); + char public_key[512]; + int public_len = sizeof(public_key); + + ret = generate_rsa_keys(public_key, &public_len, private_key, &private_len, 2048); + + TEST_CHECK(ret); + + char test_message[1024]; + std::generate(test_message, test_message + 1024, &std::rand); + + char signature[256]; + int sig_len = sign_rsa(test_message, sizeof(test_message) + , private_key, private_len, signature, sizeof(signature)); + + TEST_CHECK(sig_len == 256); + + ret = verify_rsa(test_message, sizeof(test_message), public_key, public_len, signature, sig_len); + TEST_CHECK(ret == 1); +#endif + // test verify_message const static key_desc_t msg_desc[] = { {"A", lazy_entry::string_t, 4, 0}, @@ -818,30 +843,6 @@ int test_main() TEST_EQUAL(is_complete(""), false); #endif -#ifndef TORRENT_DISABLE_DHT - // test search_torrent_entry - - dht::search_torrent_entry ste1; - dht::search_torrent_entry ste2; - char const* ste1_tags[] = {"tag1", "tag2", "tag3", "tag4"}; - ste1.publish("ste1", ste1_tags, 4); - char const* ste11_tags[] = {"tag2", "tag3"}; - ste1.publish("ste1", ste11_tags, 2); - char const* ste2_tags[] = {"tag1", "tag2", "tag5", "tag6"}; - ste2.publish("ste2", ste2_tags, 4); - char const* ste21_tags[] = {"tag1", "tag5"}; - ste2.publish("ste2", ste21_tags, 2); - - char const* test_tags1[] = {"tag1", "tag2"}; - char const* test_tags2[] = {"tag3", "tag2"}; - int m1 = ste1.match(test_tags1, 2); - int m2 = ste2.match(test_tags1, 2); - TEST_CHECK(m1 == m2); - m1 = ste1.match(test_tags2, 2); - m2 = ste2.match(test_tags2, 2); - TEST_CHECK(m1 > m2); -#endif - // test split_string char const* tags[10]; @@ -1576,7 +1577,7 @@ int test_main() std::generate(tmp.begin(), tmp.end(), &std::rand); table.find_node(tmp, temp, 0, 15); std::cout << "returned: " << temp.size() << std::endl; - TEST_EQUAL(temp.size(), (std::min)(15, int(nodes.size()))); + TEST_EQUAL(int(temp.size()), (std::min)(15, int(nodes.size()))); std::sort(nodes.begin(), nodes.end(), boost::bind(&compare_ref , boost::bind(&node_entry::id, _1)