aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2019-06-20 21:11:49 -0400
committerJack Lloyd <[email protected]>2019-06-20 21:11:49 -0400
commit1643bb636febbbc375c8cbd294fa4309d608428f (patch)
treeaeeffbd50e484955ea998f225904cb44c021b228
parentfaf77d28e2f33555a058372567bc646f9c014a36 (diff)
parent2b38ded27cc0f7883b8611db5b76fe677bbe2bc9 (diff)
Merge GH #2000 Add RFC 8032 compatible Ed25519ph
-rw-r--r--src/lib/compat/sodium/sodium_25519.cpp4
-rw-r--r--src/lib/pubkey/ed25519/ed25519.cpp11
-rw-r--r--src/lib/pubkey/ed25519/ed25519.h6
-rw-r--r--src/lib/pubkey/ed25519/ed25519_key.cpp43
-rw-r--r--src/tests/data/pubkey/ed25519.vec8
-rw-r--r--src/tests/test_pubkey.cpp16
6 files changed, 66 insertions, 22 deletions
diff --git a/src/lib/compat/sodium/sodium_25519.cpp b/src/lib/compat/sodium/sodium_25519.cpp
index 1d520d7a3..e8cce34e5 100644
--- a/src/lib/compat/sodium/sodium_25519.cpp
+++ b/src/lib/compat/sodium/sodium_25519.cpp
@@ -27,7 +27,7 @@ int Sodium::crypto_sign_ed25519_detached(uint8_t sig[],
size_t msg_len,
const uint8_t sk[32])
{
- ed25519_sign(sig, msg, msg_len, sk);
+ ed25519_sign(sig, msg, msg_len, sk, nullptr, 0);
if(sig_len)
*sig_len = 64;
@@ -39,7 +39,7 @@ int Sodium::crypto_sign_ed25519_verify_detached(const uint8_t sig[64],
size_t msg_len,
const uint8_t pk[32])
{
- const bool ok = ed25519_verify(msg, msg_len, sig, pk);
+ const bool ok = ed25519_verify(msg, msg_len, sig, pk, nullptr, 0);
return ok ? 0 : -1;
}
diff --git a/src/lib/pubkey/ed25519/ed25519.cpp b/src/lib/pubkey/ed25519/ed25519.cpp
index b75028041..624f82657 100644
--- a/src/lib/pubkey/ed25519/ed25519.cpp
+++ b/src/lib/pubkey/ed25519/ed25519.cpp
@@ -34,8 +34,9 @@ void ed25519_gen_keypair(uint8_t* pk, uint8_t* sk, const uint8_t seed[32])
}
void ed25519_sign(uint8_t sig[64],
- const uint8_t* m, size_t mlen,
- const uint8_t* sk)
+ const uint8_t m[], size_t mlen,
+ const uint8_t sk[64],
+ const uint8_t domain_sep[], size_t domain_sep_len)
{
uint8_t az[64];
uint8_t nonce[64];
@@ -49,6 +50,7 @@ void ed25519_sign(uint8_t sig[64],
az[31] &= 63;
az[31] |= 64;
+ sha.update(domain_sep, domain_sep_len);
sha.update(az + 32, 32);
sha.update(m, mlen);
sha.final(nonce);
@@ -56,6 +58,7 @@ void ed25519_sign(uint8_t sig[64],
sc_reduce(nonce);
ge_scalarmult_base(sig, nonce);
+ sha.update(domain_sep, domain_sep_len);
sha.update(sig, 32);
sha.update(sk + 32, 32);
sha.update(m, mlen);
@@ -67,7 +70,8 @@ void ed25519_sign(uint8_t sig[64],
bool ed25519_verify(const uint8_t* m, size_t mlen,
const uint8_t sig[64],
- const uint8_t* pk)
+ const uint8_t* pk,
+ const uint8_t domain_sep[], size_t domain_sep_len)
{
uint8_t h[64];
uint8_t rcheck[32];
@@ -83,6 +87,7 @@ bool ed25519_verify(const uint8_t* m, size_t mlen,
return false;
}
+ sha.update(domain_sep, domain_sep_len);
sha.update(sig, 32);
sha.update(pk, 32);
sha.update(m, mlen);
diff --git a/src/lib/pubkey/ed25519/ed25519.h b/src/lib/pubkey/ed25519/ed25519.h
index 51c75e641..97ed023f2 100644
--- a/src/lib/pubkey/ed25519/ed25519.h
+++ b/src/lib/pubkey/ed25519/ed25519.h
@@ -99,12 +99,14 @@ void ed25519_gen_keypair(uint8_t pk[32], uint8_t sk[64], const uint8_t seed[32])
void ed25519_sign(uint8_t sig[64],
const uint8_t msg[],
size_t msg_len,
- const uint8_t sk[64]);
+ const uint8_t sk[64],
+ const uint8_t domain_sep[], size_t domain_sep_len);
bool ed25519_verify(const uint8_t msg[],
size_t msg_len,
const uint8_t sig[64],
- const uint8_t pk[32]);
+ const uint8_t pk[32],
+ const uint8_t domain_sep[], size_t domain_sep_len);
}
diff --git a/src/lib/pubkey/ed25519/ed25519_key.cpp b/src/lib/pubkey/ed25519/ed25519_key.cpp
index 1de24aa26..c4b260c4c 100644
--- a/src/lib/pubkey/ed25519/ed25519_key.cpp
+++ b/src/lib/pubkey/ed25519/ed25519_key.cpp
@@ -122,7 +122,7 @@ class Ed25519_Pure_Verify_Operation final : public PK_Ops::Verification
const std::vector<uint8_t>& pub_key = m_key.get_public_key();
BOTAN_ASSERT_EQUAL(pub_key.size(), 32, "Expected size");
- const bool ok = ed25519_verify(m_msg.data(), m_msg.size(), sig, pub_key.data());
+ const bool ok = ed25519_verify(m_msg.data(), m_msg.size(), sig, pub_key.data(), nullptr, 0);
m_msg.clear();
return ok;
}
@@ -138,9 +138,18 @@ class Ed25519_Pure_Verify_Operation final : public PK_Ops::Verification
class Ed25519_Hashed_Verify_Operation final : public PK_Ops::Verification
{
public:
- Ed25519_Hashed_Verify_Operation(const Ed25519_PublicKey& key, const std::string& hash) : m_key(key)
+ Ed25519_Hashed_Verify_Operation(const Ed25519_PublicKey& key, const std::string& hash, bool rfc8032) :
+ m_key(key)
{
m_hash = HashFunction::create_or_throw(hash);
+
+ if(rfc8032)
+ {
+ m_domain_sep = {
+ 0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E, 0x6F, 0x20, 0x45, 0x64,
+ 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F, 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73,
+ 0x01, 0x00 };
+ }
}
void update(const uint8_t msg[], size_t msg_len) override
@@ -157,12 +166,13 @@ class Ed25519_Hashed_Verify_Operation final : public PK_Ops::Verification
const std::vector<uint8_t>& pub_key = m_key.get_public_key();
BOTAN_ASSERT_EQUAL(pub_key.size(), 32, "Expected size");
- return ed25519_verify(msg_hash.data(), msg_hash.size(), sig, pub_key.data());
+ return ed25519_verify(msg_hash.data(), msg_hash.size(), sig, pub_key.data(), m_domain_sep.data(), m_domain_sep.size());
}
private:
std::unique_ptr<HashFunction> m_hash;
const Ed25519_PublicKey& m_key;
+ std::vector<uint8_t> m_domain_sep;
};
/**
@@ -183,7 +193,7 @@ class Ed25519_Pure_Sign_Operation final : public PK_Ops::Signature
secure_vector<uint8_t> sign(RandomNumberGenerator&) override
{
secure_vector<uint8_t> sig(64);
- ed25519_sign(sig.data(), m_msg.data(), m_msg.size(), m_key.get_private_key().data());
+ ed25519_sign(sig.data(), m_msg.data(), m_msg.size(), m_key.get_private_key().data(), nullptr, 0);
m_msg.clear();
return sig;
}
@@ -201,9 +211,18 @@ class Ed25519_Pure_Sign_Operation final : public PK_Ops::Signature
class Ed25519_Hashed_Sign_Operation final : public PK_Ops::Signature
{
public:
- Ed25519_Hashed_Sign_Operation(const Ed25519_PrivateKey& key, const std::string& hash) : m_key(key)
+ Ed25519_Hashed_Sign_Operation(const Ed25519_PrivateKey& key, const std::string& hash, bool rfc8032) :
+ m_key(key)
{
m_hash = HashFunction::create_or_throw(hash);
+
+ if(rfc8032)
+ {
+ m_domain_sep = std::vector<uint8_t>{
+ 0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E, 0x6F, 0x20, 0x45, 0x64,
+ 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F, 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73,
+ 0x01, 0x00 };
+ }
}
size_t signature_length() const override { return 64; }
@@ -218,13 +237,17 @@ class Ed25519_Hashed_Sign_Operation final : public PK_Ops::Signature
secure_vector<uint8_t> sig(64);
std::vector<uint8_t> msg_hash(m_hash->output_length());
m_hash->final(msg_hash.data());
- ed25519_sign(sig.data(), msg_hash.data(), msg_hash.size(), m_key.get_private_key().data());
+ ed25519_sign(sig.data(),
+ msg_hash.data(), msg_hash.size(),
+ m_key.get_private_key().data(),
+ m_domain_sep.data(), m_domain_sep.size());
return sig;
}
private:
std::unique_ptr<HashFunction> m_hash;
const Ed25519_PrivateKey& m_key;
+ std::vector<uint8_t> m_domain_sep;
};
}
@@ -237,8 +260,10 @@ Ed25519_PublicKey::create_verification_op(const std::string& params,
{
if(params == "" || params == "Identity" || params == "Pure")
return std::unique_ptr<PK_Ops::Verification>(new Ed25519_Pure_Verify_Operation(*this));
+ else if(params == "Ed25519ph")
+ return std::unique_ptr<PK_Ops::Verification>(new Ed25519_Hashed_Verify_Operation(*this, "SHA-512", true));
else
- return std::unique_ptr<PK_Ops::Verification>(new Ed25519_Hashed_Verify_Operation(*this, params));
+ return std::unique_ptr<PK_Ops::Verification>(new Ed25519_Hashed_Verify_Operation(*this, params, false));
}
throw Provider_Not_Found(algo_name(), provider);
}
@@ -252,8 +277,10 @@ Ed25519_PrivateKey::create_signature_op(RandomNumberGenerator&,
{
if(params == "" || params == "Identity" || params == "Pure")
return std::unique_ptr<PK_Ops::Signature>(new Ed25519_Pure_Sign_Operation(*this));
+ else if(params == "Ed25519ph")
+ return std::unique_ptr<PK_Ops::Signature>(new Ed25519_Hashed_Sign_Operation(*this, "SHA-512", true));
else
- return std::unique_ptr<PK_Ops::Signature>(new Ed25519_Hashed_Sign_Operation(*this, params));
+ return std::unique_ptr<PK_Ops::Signature>(new Ed25519_Hashed_Sign_Operation(*this, params, false));
}
throw Provider_Not_Found(algo_name(), provider);
}
diff --git a/src/tests/data/pubkey/ed25519.vec b/src/tests/data/pubkey/ed25519.vec
index da328259b..aa56015f5 100644
--- a/src/tests/data/pubkey/ed25519.vec
+++ b/src/tests/data/pubkey/ed25519.vec
@@ -3306,8 +3306,16 @@ Pubkey = 3f098994bdd916ed4053197934e4a87c80733a1280d62f8010992e43ee3b2406
Msg = f6220a3f757814f4c2176ffbb68b00249cd4ccdc059c4b34ad871f30b1740280
Signature = 56f90cca98e2102637bd983fdb16c131dfd27ed82bf4dde5606e0d756aed3366d09c4fa11527f038e0f57f2201d82f2ea2c9033265fa6ceb489e854bae61b404
+[Ed25519ph]
+# From RFC 8032 section 7.3
+Privkey = 833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42
+Pubkey = ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf
+Msg = 616263
+Signature = 98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae4131f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406
+
# From Wycheproof
+[Pure]
# Test 1
Privkey = add4bb8103785baf9ac534258e8aaf65f5f1adb5ef5f3df19bb80ab989c4d64b
Pubkey = 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa
diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp
index 80b95b70b..3d2526a78 100644
--- a/src/tests/test_pubkey.cpp
+++ b/src/tests/test_pubkey.cpp
@@ -142,12 +142,6 @@ PK_Signature_Generation_Test::run_one_test(const std::string& pad_hdr, const Var
for(auto const& sign_provider : possible_providers(algo_name()))
{
- std::unique_ptr<Botan::RandomNumberGenerator> rng;
- if(vars.has_key("Nonce"))
- {
- rng.reset(test_rng(vars.get_req_bin("Nonce")));
- }
-
std::unique_ptr<Botan::PK_Signer> signer;
std::vector<uint8_t> generated_signature;
@@ -156,7 +150,15 @@ PK_Signature_Generation_Test::run_one_test(const std::string& pad_hdr, const Var
{
signer.reset(new Botan::PK_Signer(*privkey, Test::rng(), padding, Botan::IEEE_1363, sign_provider));
- generated_signature = signer->sign_message(message, rng ? *rng : Test::rng());
+ if(vars.has_key("Nonce"))
+ {
+ std::unique_ptr<Botan::RandomNumberGenerator> rng(test_rng(vars.get_req_bin("Nonce")));
+ generated_signature = signer->sign_message(message, *rng);
+ }
+ else
+ {
+ generated_signature = signer->sign_message(message, Test::rng());
+ }
result.test_lte("Generated signature within announced bound",
generated_signature.size(), signer->signature_length());