mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Refactor ECDSA canonical checks:
* Add signature canonicalization unit tests * Tidy up into new classes and functions
This commit is contained in:
committed by
Vinnie Falco
parent
a4a7dd4314
commit
d447a1db39
@@ -18,6 +18,8 @@
|
||||
//==============================================================================
|
||||
|
||||
#include "../../../beast/beast/unit_test/suite.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -28,24 +30,31 @@ namespace detail {
|
||||
{
|
||||
BIGNUM* num;
|
||||
|
||||
BigNum (BigNum const&) = delete;
|
||||
BigNum& operator=(BigNum const&) = delete;
|
||||
|
||||
BigNum (const char *hex)
|
||||
BigNum ()
|
||||
: num (BN_new ())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BigNum (const char *hex)
|
||||
: num (BN_new ())
|
||||
{
|
||||
num = BN_new ();
|
||||
BN_hex2bn (&num, hex);
|
||||
}
|
||||
|
||||
BigNum ()
|
||||
BigNum (unsigned char const* ptr, size_t len)
|
||||
: num (BN_new ())
|
||||
{
|
||||
num = BN_new ();
|
||||
set (ptr, len);
|
||||
}
|
||||
|
||||
BigNum (unsigned char const* ptr, size_t len)
|
||||
BigNum (BigNum const& other)
|
||||
: num (BN_new ())
|
||||
{
|
||||
num = BN_new ();
|
||||
BN_bin2bn (ptr, len, num);
|
||||
if (BN_copy (num, other.num) == nullptr)
|
||||
BN_clear (num);
|
||||
}
|
||||
|
||||
~BigNum ()
|
||||
@@ -57,77 +66,171 @@ namespace detail {
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
operator BIGNUM const* () const
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
bool set (unsigned char const* ptr, size_t len)
|
||||
{
|
||||
if (BN_bin2bn (ptr, len, num) == nullptr)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class SignaturePart
|
||||
{
|
||||
private:
|
||||
size_t m_skip;
|
||||
BigNum m_bn;
|
||||
|
||||
public:
|
||||
SignaturePart (unsigned char const* sig, size_t len)
|
||||
: m_skip (0)
|
||||
{
|
||||
// The format is: <02> <len> <sig>
|
||||
if ((sig[0] != 0x02) || (len < 3))
|
||||
return;
|
||||
|
||||
size_t sigLen = sig[1];
|
||||
|
||||
// Can't be longer than the data we have and must
|
||||
// be between 1 and 33 bytes.
|
||||
if ((sigLen > len) || (sigLen < 2) || (sigLen > 33))
|
||||
return;
|
||||
|
||||
// The signature can't be negative
|
||||
if ((sig[2] & 0x80) != 0)
|
||||
return;
|
||||
|
||||
// It can't be zero
|
||||
if ((sig[2] == 0) && (len == 1))
|
||||
return;
|
||||
|
||||
// And it can't be padded
|
||||
if ((sig[2] == 0) && ((sig[3] & 0x80) == 0))
|
||||
return;
|
||||
|
||||
// Load the signature but skip the marker prefix and length
|
||||
if (m_bn.set (sig + 2, sigLen))
|
||||
m_skip = sigLen + 2;
|
||||
}
|
||||
|
||||
bool valid () const
|
||||
{
|
||||
return m_skip != 0;
|
||||
}
|
||||
|
||||
// The signature as a BIGNUM
|
||||
BigNum getBigNum () const
|
||||
{
|
||||
return m_bn;
|
||||
}
|
||||
|
||||
// Returns the number of bytes to skip for this signature part
|
||||
size_t skip () const
|
||||
{
|
||||
return m_skip;
|
||||
}
|
||||
};
|
||||
|
||||
// The SECp256k1 modulus
|
||||
static BigNum modulus ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
|
||||
static BigNum const modulus (
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
|
||||
}
|
||||
|
||||
/** Determine whether a signature is canonical.
|
||||
Canonical signatures are important to protect against signature morphing
|
||||
attacks.
|
||||
@param vSig the signature data
|
||||
@param sigLen the length of the signature
|
||||
@param strict_param whether to enforce strictly canonical semantics
|
||||
|
||||
@note For more details please see:
|
||||
https://ripple.com/wiki/Transaction_Malleability
|
||||
https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
|
||||
https://github.com/sipa/bitcoin/commit/58bc86e37fda1aec270bccb3df6c20fbd2a6591c
|
||||
*/
|
||||
bool isCanonicalECDSASig (void const* vSig, size_t sigLen, ECDSA strict_param)
|
||||
{
|
||||
// Make sure signature is canonical
|
||||
// To protect against signature morphing attacks
|
||||
// See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
|
||||
// and https://github.com/sipa/bitcoin/commit/58bc86e37fda1aec270bccb3df6c20fbd2a6591c
|
||||
|
||||
// Signature should be:
|
||||
// The format of a signature should be:
|
||||
// <30> <len> [ <02> <lenR> <R> ] [ <02> <lenS> <S> ]
|
||||
|
||||
const bool strict = strict_param == ECDSA::strict;
|
||||
|
||||
unsigned char const* sig = reinterpret_cast<unsigned char const*> (vSig);
|
||||
|
||||
if ((sigLen < 10) || (sigLen > 74))
|
||||
if ((sigLen < 10) || (sigLen > 72))
|
||||
return false;
|
||||
|
||||
if ((sig[0] != 0x30) || (sig[1] != (sigLen - 2)))
|
||||
return false;
|
||||
|
||||
// The first two bytes are verified. Eat them.
|
||||
sig += 2;
|
||||
sigLen -= 2;
|
||||
|
||||
// Find R and check its length
|
||||
int rPos = 4, rLen = sig[3];
|
||||
if ((rLen < 2) || ((rLen + 6) > sigLen))
|
||||
// Verify the R signature
|
||||
detail::SignaturePart sigR (sig, sigLen);
|
||||
|
||||
if (!sigR.valid ())
|
||||
return false;
|
||||
|
||||
// Find S and check its length
|
||||
int sPos = rLen + 6, sLen = sig [rLen + 5];
|
||||
if ((sLen < 2) || ((rLen + sLen + 6) != sigLen))
|
||||
// Eat the number of bytes we consumed
|
||||
sig += sigR.skip ();
|
||||
sigLen -= sigR.skip ();
|
||||
|
||||
// Verify the S signature
|
||||
detail::SignaturePart sigS (sig, sigLen);
|
||||
|
||||
if (!sigS.valid ())
|
||||
return false;
|
||||
|
||||
// Eat the number of bytes we consumed
|
||||
sig += sigS.skip ();
|
||||
sigLen -= sigS.skip ();
|
||||
|
||||
// Nothing should remain at this point.
|
||||
if (sigLen != 0)
|
||||
return false;
|
||||
|
||||
if ((sig[rPos - 2] != 0x02) || (sig[sPos - 2] != 0x02))
|
||||
return false; // R or S have wrong type
|
||||
// Check whether R or S are greater than the modulus.
|
||||
auto bnR (sigR.getBigNum ());
|
||||
auto bnS (sigS.getBigNum ());
|
||||
|
||||
if ((sig[rPos] & 0x80) != 0)
|
||||
return false; // R is negative
|
||||
if (BN_cmp (bnR, detail::modulus) != -1)
|
||||
return false;
|
||||
|
||||
if ((sig[rPos] == 0) && ((sig[rPos + 1] & 0x80) == 0))
|
||||
return false; // R is padded
|
||||
if (BN_cmp (bnS, detail::modulus) != -1)
|
||||
return false;
|
||||
|
||||
if ((sig[sPos] & 0x80) != 0)
|
||||
return false; // S is negative
|
||||
// For a given signature, (R,S), the signature (R, N-S) is also valid. For
|
||||
// a signature to be fully-canonical, the smaller of these two values must
|
||||
// be specified. If operating in strict mode, check that as well.
|
||||
if (strict_param == ECDSA::strict)
|
||||
{
|
||||
detail::BigNum mS;
|
||||
|
||||
if ((sig[sPos] == 0) && ((sig[sPos + 1] & 0x80) == 0))
|
||||
return false; // S is padded
|
||||
if (BN_sub (mS, detail::modulus, bnS) == 0)
|
||||
return false;
|
||||
|
||||
detail::BigNum bnR (&sig[rPos], rLen);
|
||||
detail::BigNum bnS (&sig[sPos], sLen);
|
||||
if ((BN_cmp (bnR, detail::modulus) != -1) || (BN_cmp (bnS, detail::modulus) != -1))
|
||||
return false; // R or S greater than modulus
|
||||
if (BN_cmp (bnS, mS) == 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!strict)
|
||||
return true;
|
||||
|
||||
detail::BigNum mS;
|
||||
BN_sub (mS, detail::modulus, bnS);
|
||||
return BN_cmp (bnS, mS) != 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Returns true if original signature was alread canonical
|
||||
/** Convert a signature into strictly canonical form.
|
||||
Given the signature (R, S) then (R, G-S) is also valid. For a signature
|
||||
to be canonical, the smaller of { S, G-S } must be specified.
|
||||
@param vSig the signature we wish to convert
|
||||
@param sigLen the length of the signature
|
||||
@returns true if the signature was already canonical, false otherwise
|
||||
*/
|
||||
bool makeCanonicalECDSASig (void* vSig, size_t& sigLen)
|
||||
{
|
||||
// Signature is (r,s) where 0 < s < g
|
||||
// If (g-s)<g, replace signature with (r,g-s)
|
||||
|
||||
unsigned char * sig = reinterpret_cast<unsigned char *> (vSig);
|
||||
bool ret = false;
|
||||
|
||||
@@ -201,92 +304,280 @@ void hex_to_binary (FwdIter first, FwdIter last, Container& out)
|
||||
class ECDSACanonical_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
bool isCanonical (std::string const& hex)
|
||||
Blob loadSignature (std::string const& hex)
|
||||
{
|
||||
Blob j;
|
||||
hex_to_binary (hex.begin(), hex.end(), j);
|
||||
Blob b;
|
||||
hex_to_binary (hex.begin (), hex.end (), b);
|
||||
return b;
|
||||
}
|
||||
|
||||
/** Verifies that a signature is valid.
|
||||
Valid signatures may not be canonical
|
||||
*/
|
||||
bool isValid (std::string const& hex)
|
||||
{
|
||||
Blob j (loadSignature(hex));
|
||||
return isCanonicalECDSASig (&j[0], j.size(), ECDSA::not_strict);
|
||||
}
|
||||
|
||||
void run ()
|
||||
/** Verifies that a signature is canonical.
|
||||
Canonical signatures are valid.
|
||||
*/
|
||||
bool isStrictlyCanonical (std::string const& hex)
|
||||
{
|
||||
expect (isCanonical("304402203932c892e2e550f3af8ee4ce9c215a87f9bb"
|
||||
"831dcac87b2838e2c2eaa891df0c022030b61dd36543125d56b9f9f3a1f"
|
||||
"53189e5af33cdda8d77a5209aec03978fa001"), "canonical signature");
|
||||
Blob j (loadSignature(hex));
|
||||
return isCanonicalECDSASig (&j[0], j.size (), ECDSA::strict);
|
||||
}
|
||||
|
||||
expect (isCanonical("30450220076045be6f9eca28ff1ec606b833d0b87e70b"
|
||||
"2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688"
|
||||
"eca1d2ba7f6b180620eaa03488e6585db6ba01"), "canonical signature");
|
||||
/** Verify that we correctly identify strictly canonical signatures */
|
||||
void testStrictlyCanonicalSignatures ()
|
||||
{
|
||||
testcase ("Strictly canonical signature checks", abort_on_fail);
|
||||
|
||||
expect (isCanonical("3046022100876045be6f9eca28ff1ec606b833d0b87e7"
|
||||
"0b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c"
|
||||
"2eca1d2ba7f6b180620eaa03488e6585db6ba"), "canonical signature");
|
||||
expect (isStrictlyCanonical("3045"
|
||||
"022100FF478110D1D4294471EC76E0157540C2181F47DEBD25D7F9E7DDCCCD47EEE905"
|
||||
"0220078F07CDAE6C240855D084AD91D1479609533C147C93B0AEF19BC9724D003F28"),
|
||||
"Strictly canonical signature");
|
||||
|
||||
expect (isStrictlyCanonical("3045"
|
||||
"0221009218248292F1762D8A51BE80F8A7F2CD288D810CE781D5955700DA1684DF1D2D"
|
||||
"022041A1EE1746BFD72C9760CC93A7AAA8047D52C8833A03A20EAAE92EA19717B454"),
|
||||
"Strictly canonical signature");
|
||||
|
||||
expect (isStrictlyCanonical("3044"
|
||||
"02206A9E43775F73B6D1EC420E4DDD222A80D4C6DF5D1BEECC431A91B63C928B7581"
|
||||
"022023E9CC2D61DDA6F73EAA6BCB12688BEB0F434769276B3127E4044ED895C9D96B"),
|
||||
"Strictly canonical signature");
|
||||
|
||||
expect (!isCanonical("3005" "0201FF" "0200"), "tooshort");
|
||||
expect (isStrictlyCanonical("3044"
|
||||
"022056E720007221F3CD4EFBB6352741D8E5A0968D48D8D032C2FBC4F6304AD1D04E"
|
||||
"02201F39EB392C20D7801C3E8D81D487E742FA84A1665E923225BD6323847C71879F"),
|
||||
"Strictly canonical signature");
|
||||
|
||||
expect (!isCanonical("3047"
|
||||
expect (isStrictlyCanonical("3045"
|
||||
"022100FDFD5AD05518CEA0017A2DCB5C4DF61E7C73B6D3A38E7AE93210A1564E8C2F12"
|
||||
"0220214FF061CCC123C81D0BB9D0EDEA04CD40D96BF1425D311DA62A7096BB18EA18"),
|
||||
"Strictly canonical signature");
|
||||
|
||||
// These are canonical signatures, but *not* strictly canonical.
|
||||
expect (!isStrictlyCanonical ("3046"
|
||||
"022100F477B3FA6F31C7CB3A0D1AD94A231FDD24B8D78862EE334CEA7CD08F6CBC0A1B"
|
||||
"022100928E6BCF1ED2684679730C5414AEC48FD62282B090041C41453C1D064AF597A1"),
|
||||
"Not strictly canonical signature");
|
||||
|
||||
expect (!isStrictlyCanonical ("3045"
|
||||
"022063E7C7CA93CB2400E413A342C027D00665F8BAB9C22EF0A7B8AE3AAF092230B6"
|
||||
"0221008F2E8BB7D09521ABBC277717B14B93170AE6465C5A1B36561099319C4BEB254C"),
|
||||
"Not strictly canonical signature");
|
||||
|
||||
expect (!isStrictlyCanonical ("3046"
|
||||
"02210099DCA1188663DDEA506A06A7B20C2B7D8C26AFF41DECE69D6C5F7C967D32625F"
|
||||
"022100897658A6B1F9EEE5D140D7A332DA0BD73BB98974EA53F6201B01C1B594F286EA"),
|
||||
"Not strictly canonical signature");
|
||||
|
||||
expect (!isStrictlyCanonical ("3045"
|
||||
"02200855DE366E4E323AA2CE2A25674401A7D11F72EC432770D07F7B57DF7387AEC0"
|
||||
"022100DA4C6ADDEA14888858DE2AC5B91ED9050D6972BB388DEF582628CEE32869AE35"),
|
||||
"Not strictly canonical signature");
|
||||
}
|
||||
|
||||
/** Verify that we correctly identify valid signatures */
|
||||
void testValidSignatures ()
|
||||
{
|
||||
testcase ("Canonical signature checks", abort_on_fail);
|
||||
|
||||
expect (isValid ("3044"
|
||||
"02203932c892e2e550f3af8ee4ce9c215a87f9bb831dcac87b2838e2c2eaa891df0c"
|
||||
"022030b61dd36543125d56b9f9f3a1f53189e5af33cdda8d77a5209aec03978fa001"),
|
||||
"Canonical signature");
|
||||
|
||||
expect (isValid ("3045"
|
||||
"0220076045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a"
|
||||
"0221008fffd599910eefe00bc803c688eca1d2ba7f6b180620eaa03488e6585db6ba01"),
|
||||
"Canonical signature");
|
||||
|
||||
expect (isValid("3046"
|
||||
"022100876045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a"
|
||||
"0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba"),
|
||||
"Canonical signature");
|
||||
|
||||
expect (isStrictlyCanonical("3045"
|
||||
"022100FF478110D1D4294471EC76E0157540C2181F47DEBD25D7F9E7DDCCCD47EEE905"
|
||||
"0220078F07CDAE6C240855D084AD91D1479609533C147C93B0AEF19BC9724D003F28"),
|
||||
"Canonical signature");
|
||||
|
||||
expect (isStrictlyCanonical("3045"
|
||||
"0221009218248292F1762D8A51BE80F8A7F2CD288D810CE781D5955700DA1684DF1D2D"
|
||||
"022041A1EE1746BFD72C9760CC93A7AAA8047D52C8833A03A20EAAE92EA19717B454"),
|
||||
"Canonical signature");
|
||||
|
||||
expect (isStrictlyCanonical("3044"
|
||||
"02206A9E43775F73B6D1EC420E4DDD222A80D4C6DF5D1BEECC431A91B63C928B7581"
|
||||
"022023E9CC2D61DDA6F73EAA6BCB12688BEB0F434769276B3127E4044ED895C9D96B"),
|
||||
"Canonical signature");
|
||||
|
||||
expect (isStrictlyCanonical("3044"
|
||||
"022056E720007221F3CD4EFBB6352741D8E5A0968D48D8D032C2FBC4F6304AD1D04E"
|
||||
"02201F39EB392C20D7801C3E8D81D487E742FA84A1665E923225BD6323847C71879F"),
|
||||
"Canonical signature");
|
||||
|
||||
expect (isStrictlyCanonical("3045"
|
||||
"022100FDFD5AD05518CEA0017A2DCB5C4DF61E7C73B6D3A38E7AE93210A1564E8C2F12"
|
||||
"0220214FF061CCC123C81D0BB9D0EDEA04CD40D96BF1425D311DA62A7096BB18EA18"),
|
||||
"Canonical signature");
|
||||
}
|
||||
|
||||
/** Verify that we correctly identify malformed or invalid signatures */
|
||||
void testMalformedSignatures ()
|
||||
{
|
||||
testcase ("Non-canonical signature checks", abort_on_fail);
|
||||
|
||||
expect (!isValid("3005"
|
||||
"0201FF"
|
||||
"0200"),
|
||||
"tooshort");
|
||||
|
||||
expect (!isValid("3047"
|
||||
"0221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"022200002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"),
|
||||
"toolong");
|
||||
|
||||
expect (!isCanonical("3144"
|
||||
expect (!isValid("3144"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"),
|
||||
"type");
|
||||
|
||||
expect (!isCanonical("3045"
|
||||
expect (!isValid("3045"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"),
|
||||
"totallength");
|
||||
|
||||
expect (!isCanonical(
|
||||
"301F" "01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1"),
|
||||
expect (!isValid("301F"
|
||||
"01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1"),
|
||||
"Slenoob");
|
||||
|
||||
expect (!isCanonical("3045"
|
||||
expect (!isValid("3045"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed00"),
|
||||
"R+S");
|
||||
|
||||
expect (!isCanonical("3044"
|
||||
expect (!isValid("3044"
|
||||
"01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"),
|
||||
"Rtype");
|
||||
|
||||
expect (!isCanonical("3024" "0200"
|
||||
expect (!isValid("3024"
|
||||
"0200"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"),
|
||||
"Rlen=0");
|
||||
|
||||
expect (!isCanonical("3044"
|
||||
expect (!isValid("3044"
|
||||
"02208990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"),
|
||||
"R<0");
|
||||
|
||||
expect (!isCanonical("3045"
|
||||
expect (!isValid("3045"
|
||||
"0221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"),
|
||||
"Rpadded");
|
||||
|
||||
expect (!isCanonical("3044"
|
||||
expect (!isValid("3044"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105012"
|
||||
"02d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"),
|
||||
"Stype");
|
||||
|
||||
expect (!isCanonical("3024"
|
||||
expect (!isValid("3024"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"0200"),
|
||||
"Slen=0");
|
||||
|
||||
expect (!isCanonical("3044"
|
||||
expect (!isValid("3044"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"0220fd5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"),
|
||||
"S<0");
|
||||
|
||||
expect (!isCanonical("3045"
|
||||
expect (!isValid("3045"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"0221002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"),
|
||||
"Spadded");
|
||||
}
|
||||
|
||||
void convertNonCanonical(std::string const& hex, std::string const& canonHex)
|
||||
{
|
||||
Blob b (loadSignature(hex));
|
||||
|
||||
// The signature ought to at least be valid before we begin.
|
||||
expect (isValid (hex), "invalid signature");
|
||||
|
||||
size_t len = b.size ();
|
||||
|
||||
expect (!makeCanonicalECDSASig (&b[0], len),
|
||||
"non-canonical signature was already canonical");
|
||||
|
||||
expect (b.size () >= len,
|
||||
"canonicalized signature length longer than non-canonical");
|
||||
|
||||
b.resize (len);
|
||||
|
||||
expect (isCanonicalECDSASig (&b[0], len, ECDSA::strict),
|
||||
"canonicalized signature is not strictly canonical");
|
||||
|
||||
Blob canonicalForm (loadSignature (canonHex));
|
||||
|
||||
expect (b.size () == canonicalForm.size (),
|
||||
"canonicalized signature doesn't have the expected length");
|
||||
|
||||
expect (std::equal (b.begin (), b.end (), canonicalForm.begin ()),
|
||||
"canonicalized signature isn't what we expected");
|
||||
}
|
||||
|
||||
/** Verifies correctness of non-canonical to canonical conversion */
|
||||
void testCanonicalConversions()
|
||||
{
|
||||
testcase ("Non-canonical signature canonicalization", abort_on_fail);
|
||||
|
||||
convertNonCanonical (
|
||||
"3046"
|
||||
"022100F477B3FA6F31C7CB3A0D1AD94A231FDD24B8D78862EE334CEA7CD08F6CBC0A1B"
|
||||
"022100928E6BCF1ED2684679730C5414AEC48FD62282B090041C41453C1D064AF597A1",
|
||||
"3045"
|
||||
"022100F477B3FA6F31C7CB3A0D1AD94A231FDD24B8D78862EE334CEA7CD08F6CBC0A1B"
|
||||
"02206D719430E12D97B9868CF3ABEB513B6EE48C5A361F4483FA7A9641868540A9A0");
|
||||
|
||||
convertNonCanonical (
|
||||
"3045"
|
||||
"022063E7C7CA93CB2400E413A342C027D00665F8BAB9C22EF0A7B8AE3AAF092230B6"
|
||||
"0221008F2E8BB7D09521ABBC277717B14B93170AE6465C5A1B36561099319C4BEB254C",
|
||||
"3044"
|
||||
"022063E7C7CA93CB2400E413A342C027D00665F8BAB9C22EF0A7B8AE3AAF092230B6"
|
||||
"022070D174482F6ADE5443D888E84EB46CE7AFC8968A552D69E5AF392CF0844B1BF5");
|
||||
|
||||
convertNonCanonical (
|
||||
"3046"
|
||||
"02210099DCA1188663DDEA506A06A7B20C2B7D8C26AFF41DECE69D6C5F7C967D32625F"
|
||||
"022100897658A6B1F9EEE5D140D7A332DA0BD73BB98974EA53F6201B01C1B594F286EA",
|
||||
"3045"
|
||||
"02210099DCA1188663DDEA506A06A7B20C2B7D8C26AFF41DECE69D6C5F7C967D32625F"
|
||||
"02207689A7594E06111A2EBF285CCD25F4277EF55371C4F4AA1BA4D09CD73B43BA57");
|
||||
|
||||
convertNonCanonical (
|
||||
"3045"
|
||||
"02200855DE366E4E323AA2CE2A25674401A7D11F72EC432770D07F7B57DF7387AEC0"
|
||||
"022100DA4C6ADDEA14888858DE2AC5B91ED9050D6972BB388DEF582628CEE32869AE35",
|
||||
"3044"
|
||||
"02200855DE366E4E323AA2CE2A25674401A7D11F72EC432770D07F7B57DF7387AEC0"
|
||||
"022025B3952215EB7777A721D53A46E126F9AD456A2B76BAB0E399A98FA9A7CC930C");
|
||||
}
|
||||
|
||||
void run ()
|
||||
{
|
||||
testValidSignatures ();
|
||||
|
||||
testStrictlyCanonicalSignatures ();
|
||||
|
||||
testMalformedSignatures ();
|
||||
|
||||
testCanonicalConversions ();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user