From c4d22997f364a7fc2e5a8150c0a4a55590a92df5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 16 Feb 2016 16:38:44 +0100 Subject: Add C++ functions for .narinfo processing / signing This is currently only used by the Hydra queue runner rework, but like eff5021eaa6dc69f65ea1a8abe8f3ab11ef5eb0a it presumably will be useful for the C++ rewrite of nix-push and download-from-binary-cache. (@shlevy) --- src/libstore/crypto.cc | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/libstore/crypto.cc (limited to 'src/libstore/crypto.cc') diff --git a/src/libstore/crypto.cc b/src/libstore/crypto.cc new file mode 100644 index 000000000000..18ff3f89dea4 --- /dev/null +++ b/src/libstore/crypto.cc @@ -0,0 +1,79 @@ +#include "crypto.hh" +#include "util.hh" + +#if HAVE_SODIUM +#include +#endif + +namespace nix { + +static std::pair split(const string & s) +{ + size_t colon = s.find(':'); + if (colon == std::string::npos || colon == 0) + return {"", ""}; + return {std::string(s, 0, colon), std::string(s, colon + 1)}; +} + +Key::Key(const string & s) +{ + auto ss = split(s); + + name = ss.first; + key = ss.second; + + if (name == "" || key == "") + throw Error("secret key is corrupt"); + + key = base64Decode(key); +} + +SecretKey::SecretKey(const string & s) + : Key(s) +{ +#if HAVE_SODIUM + if (key.size() != crypto_sign_SECRETKEYBYTES) + throw Error("secret key is not valid"); +#endif +} + +std::string SecretKey::signDetached(const std::string & data) const +{ +#if HAVE_SODIUM + unsigned char sig[crypto_sign_BYTES]; + unsigned long long sigLen; + crypto_sign_detached(sig, &sigLen, (unsigned char *) data.data(), data.size(), + (unsigned char *) key.data()); + return name + ":" + base64Encode(std::string((char *) sig, sigLen)); +#else + throw Error("Nix was not compiled with libsodium, required for signed binary cache support"); +#endif +} + +PublicKey::PublicKey(const string & s) + : Key(s) +{ +#if HAVE_SODIUM + if (key.size() != crypto_sign_PUBLICKEYBYTES) + throw Error("public key is not valid"); +#endif +} + +bool verifyDetached(const std::string & data, const std::string & sig, + const PublicKeys & publicKeys) +{ + auto ss = split(sig); + + auto key = publicKeys.find(ss.first); + if (key == publicKeys.end()) return false; + + auto sig2 = base64Decode(ss.second); + if (sig2.size() != crypto_sign_BYTES) + throw Error("signature is not valid"); + + return crypto_sign_verify_detached((unsigned char *) sig2.data(), + (unsigned char *) data.data(), data.size(), + (unsigned char *) key->second.key.data()) == 0; +} + +} -- cgit 1.4.1