From 69c0f9128cce87f918dc93c5eb4da5e80a2dae02 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Fri, 27 May 2016 13:52:10 -0600 Subject: [PATCH] Enforce that the `S` value of the ed25519 signature is smaller than the group order to prevent malleability attacks. --- src/main.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 7dea59f3c..81d873b36 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -842,7 +842,30 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in +// Taken from +// https://github.com/jedisct1/libsodium/commit/4099618de2cce5099ac2ec5ce8f2d80f4585606e +// which was removed to maintain backwards compatibility in +// https://github.com/jedisct1/libsodium/commit/cb07df046f19ee0d5ad600c579df97aaa4295cc3 +static int +crypto_sign_check_S_lt_l(const unsigned char *S) +{ + static const unsigned char l[32] = + { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; + unsigned char c = 0; + unsigned char n = 1; + unsigned int i = 32; + do { + i--; + c |= ((S[i] - l[i]) >> 8) & n; + n &= ((S[i] ^ l[i]) - 1) >> 8; + } while (i != 0); + + return -(c == 0); +} @@ -977,6 +1000,11 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) REJECT_INVALID, "invalid-joinsplit-signature"); } + if (crypto_sign_check_S_lt_l(&tx.joinSplitSig[32]) != 0) { + return state.DoS(100, error("CheckTransaction(): non-canonical ed25519 signature"), + REJECT_INVALID, "non-canonical-ed25519-signature"); + } + if (state.PerformPourVerification()) { // Ensure that zk-SNARKs verify BOOST_FOREACH(const CPourTx &pour, tx.vpour) {