From d4f29089c87029ca49cf9e087b5f8b1f96c96774 Mon Sep 17 00:00:00 2001 From: Kees Monshouwer Date: Sat, 8 Aug 2015 13:28:42 +0200 Subject: [PATCH] use libsodium for ed25519 Testing algorithm 250: 'Ref10 ED25519' ->'Ref10 ED25519' -> 'Ref10 ED25519' Signature & verify ok, signature 164usec, verify 400usec Testing algorithm 250: 'Ref10 ED25519' ->'Ref10 ED25519' -> 'Sodium' Signature & verify ok, signature 169usec, verify 165usec Testing algorithm 250: 'Ref10 ED25519' ->'Sodium' -> 'Ref10 ED25519' Signature & verify ok, signature 62usec, verify 407usec Testing algorithm 250: 'Ref10 ED25519' ->'Sodium' -> 'Sodium' Signature & verify ok, signature 62usec, verify 149usec Testing algorithm 250: 'Sodium' ->'Ref10 ED25519' -> 'Ref10 ED25519' Signature & verify ok, signature 162usec, verify 397usec Testing algorithm 250: 'Sodium' ->'Ref10 ED25519' -> 'Sodium' Signature & verify ok, signature 161usec, verify 149usec Testing algorithm 250: 'Sodium' ->'Sodium' -> 'Ref10 ED25519' Signature & verify ok, signature 61usec, verify 394usec Testing algorithm 250: 'Sodium' ->'Sodium' -> 'Sodium' Signature & verify ok, signature 60usec, verify 150usec --- .travis.yml | 1 + pdns/Makefile.am | 10 +++ pdns/pdnssec.cc | 10 +++ pdns/receiver.cc | 10 +++ pdns/sodiumsigners.cc | 152 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 183 insertions(+) create mode 100644 pdns/sodiumsigners.cc diff --git a/.travis.yml b/.travis.yml index 35c18cf41..f53eecd7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,6 +64,7 @@ before_script: - sudo dpkg -i dnsperf_2.0.0.0-2_amd64.deb - wget https://xs.powerdns.com/tmp/libsodium_1.0.2-1_amd64.deb - sudo dpkg -i libsodium_1.0.2-1_amd64.deb + - sudo mv /usr/local/lib/libsodium.* /usr/lib - wget http://s3.amazonaws.com/alexa-static/top-1m.csv.zip - unzip top-1m.csv.zip -d ./pdns/regression-tests - cd pdns diff --git a/pdns/Makefile.am b/pdns/Makefile.am index 3b2b5221b..d19d09e5d 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -231,6 +231,11 @@ pdns_server_SOURCES += ed25519signers.cc pdns_server_LDADD += $(ED25519_LIBS) endif +if LIBSODIUM +pdns_server_SOURCES += sodiumsigners.cc +pdns_server_LDADD += $(LIBSODIUM_LIBS) +endif + if SQLITE3 pdns_server_SOURCES += ssqlite3.cc ssqlite3.hh pdns_server_LDADD += $(SQLITE3_LIBS) @@ -331,6 +336,11 @@ pdnssec_SOURCES += ed25519signers.cc pdnssec_LDADD += $(ED25519_LIBS) endif +if LIBSODIUM +pdnssec_SOURCES += sodiumsigners.cc +pdnssec_LDADD += $(LIBSODIUM_LIBS) +endif + if SQLITE3 pdnssec_SOURCES += ssqlite3.cc ssqlite3.hh pdnssec_LDADD += $(SQLITE3_LIBS) diff --git a/pdns/pdnssec.cc b/pdns/pdnssec.cc index 88c5b9119..b83968fa8 100644 --- a/pdns/pdnssec.cc +++ b/pdns/pdnssec.cc @@ -18,6 +18,9 @@ #include "signingpipe.hh" #include "dns_random.hh" #include +#ifdef HAVE_LIBSODIUM +#include +#endif #ifdef HAVE_SQLITE3 #include "ssqlite3.hh" #include "bind-dnssec.schema.sqlite3.sql.h" @@ -1336,6 +1339,13 @@ try return 0; } +#ifdef HAVE_LIBSODIUM + if (sodium_init() == -1) { + cerr<<"Unable to initialize sodium crypto library"< #include #include +#ifdef HAVE_LIBSODIUM +#include +#endif #include "dns.hh" #include "dnsbackend.hh" @@ -482,6 +485,13 @@ int main(int argc, char **argv) #endif seedRandom(::arg()["entropy-source"]); + +#ifdef HAVE_LIBSODIUM + if (sodium_init() == -1) { + cerr<<"Unable to initialize sodium crypto library"< +} +#include "dnssecinfra.hh" + +class SodiumED25519DNSCryptoKeyEngine : public DNSCryptoKeyEngine +{ +public: + explicit SodiumED25519DNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo) + {} + string getName() const { return "Sodium ED25519"; } + void create(unsigned int bits); + storvector_t convertToISCVector() const; + std::string getPubKeyHash() const; + std::string sign(const std::string& hash) const; + std::string hash(const std::string& hash) const; + bool verify(const std::string& msg, const std::string& signature) const; + std::string getPublicKeyString() const; + int getBits() const; + void fromISCMap(DNSKEYRecordContent& drc, std::map& stormap); + void fromPublicKeyString(const std::string& content); + void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) + {} + + static DNSCryptoKeyEngine* maker(unsigned int algorithm) + { + return new SodiumED25519DNSCryptoKeyEngine(algorithm); + } + +private: + unsigned char d_pubkey[crypto_sign_ed25519_PUBLICKEYBYTES]; + unsigned char d_seckey[crypto_sign_ed25519_SECRETKEYBYTES]; +}; + +void SodiumED25519DNSCryptoKeyEngine::create(unsigned int bits) +{ + if(bits != crypto_sign_ed25519_SEEDBYTES * 8) { + throw runtime_error("Unsupported key length of "+lexical_cast(bits)+" bits requested, SodiumED25519 class"); + } + crypto_sign_ed25519_keypair(d_pubkey, d_seckey); +} + +int SodiumED25519DNSCryptoKeyEngine::getBits() const +{ + return crypto_sign_ed25519_SEEDBYTES * 8; +} + +DNSCryptoKeyEngine::storvector_t SodiumED25519DNSCryptoKeyEngine::convertToISCVector() const +{ + /* + Private-key-format: v1.2 + Algorithm: 250 (ED25519SHA512) + PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ= + */ + + storvector_t storvector; + string algorithm = "250 (ED25519SHA512)"; + + storvector.push_back(make_pair("Algorithm", algorithm)); + + vector buffer; + storvector.push_back(make_pair("PrivateKey", string((char*)d_seckey, crypto_sign_ed25519_SEEDBYTES))); + return storvector; +} + +void SodiumED25519DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map& stormap ) +{ + /* + Private-key-format: v1.2 + Algorithm: 250 (ED25519SHA512) + PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ= + */ + + drc.d_algorithm = atoi(stormap["algorithm"].c_str()); + string privateKey = stormap["privatekey"]; + + if (privateKey.length() != crypto_sign_ed25519_SEEDBYTES) + throw runtime_error("Seed size mismatch in ISCMap, SodiumED25519 class"); + + std::unique_ptr seed(new unsigned char[crypto_sign_ed25519_SEEDBYTES]); + + memcpy(seed.get(), privateKey.c_str(), crypto_sign_ed25519_SEEDBYTES); + crypto_sign_ed25519_seed_keypair(d_pubkey, d_seckey, seed.get()); +} + +std::string SodiumED25519DNSCryptoKeyEngine::getPubKeyHash() const +{ + return this->getPublicKeyString(); +} + +std::string SodiumED25519DNSCryptoKeyEngine::getPublicKeyString() const +{ + return string((char*)d_pubkey, crypto_sign_ed25519_PUBLICKEYBYTES); +} + +void SodiumED25519DNSCryptoKeyEngine::fromPublicKeyString(const std::string& input) +{ + if (input.length() != crypto_sign_ed25519_PUBLICKEYBYTES) + throw runtime_error("Public key size mismatch, SodiumED25519 class"); + + memcpy(d_pubkey, input.c_str(), crypto_sign_ed25519_PUBLICKEYBYTES); +} + +std::string SodiumED25519DNSCryptoKeyEngine::sign(const std::string& msg) const +{ + string hash=this->hash(msg); + unsigned long long smlen = hash.length() + crypto_sign_ed25519_BYTES; + std::unique_ptr sm(new unsigned char[smlen]); + + crypto_sign_ed25519(sm.get(), &smlen, (const unsigned char*)hash.c_str(), hash.length(), d_seckey); + + return string((const char*)sm.get(), crypto_sign_ed25519_BYTES); +} + +std::string SodiumED25519DNSCryptoKeyEngine::hash(const std::string& orig) const +{ + std::unique_ptr out(new unsigned char[crypto_hash_sha512_BYTES]); + + crypto_hash_sha512(out.get(), (const unsigned char*)orig.c_str(), orig.length()); + + return string((const char*)out.get(), crypto_hash_sha512_BYTES); +} + +bool SodiumED25519DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const +{ + if (signature.length() != crypto_sign_ed25519_BYTES) + return false; + + string hash=this->hash(msg); + unsigned long long smlen = hash.length() + crypto_sign_ed25519_BYTES; + std::unique_ptr sm(new unsigned char[smlen]); + + memcpy(sm.get(), signature.c_str(), crypto_sign_ed25519_BYTES); + memcpy(sm.get() + crypto_sign_ed25519_BYTES, hash.c_str(), hash.length()); + + std::unique_ptr m(new unsigned char[smlen]); + + return crypto_sign_ed25519_open(m.get(), &smlen, sm.get(), smlen, d_pubkey) == 0; +} + +namespace { +struct LoaderSodiumStruct +{ + LoaderSodiumStruct() + { + DNSCryptoKeyEngine::report(250, &SodiumED25519DNSCryptoKeyEngine::maker); + } +} loadersodium; +} -- 2.49.0