From mboxrd@z Thu Jan  1 00:00:00 1970
Received: from sog-mx-2.v43.ch3.sourceforge.com ([172.29.43.192]
	helo=mx.sourceforge.net)
	by sfs-ml-1.v29.ch3.sourceforge.com with esmtp (Exim 4.76)
	(envelope-from <david.vorick@gmail.com>) id 1YE8CG-00012b-3b
	for bitcoin-development@lists.sourceforge.net;
	Thu, 22 Jan 2015 03:12:40 +0000
Received-SPF: pass (sog-mx-2.v43.ch3.sourceforge.com: domain of gmail.com
	designates 209.85.212.169 as permitted sender)
	client-ip=209.85.212.169; envelope-from=david.vorick@gmail.com;
	helo=mail-wi0-f169.google.com; 
Received: from mail-wi0-f169.google.com ([209.85.212.169])
	by sog-mx-2.v43.ch3.sourceforge.com with esmtps (TLSv1:RC4-SHA:128)
	(Exim 4.76) id 1YE8CD-0003Ua-5L
	for bitcoin-development@lists.sourceforge.net;
	Thu, 22 Jan 2015 03:12:40 +0000
Received: by mail-wi0-f169.google.com with SMTP id bs8so37581119wib.0
	for <bitcoin-development@lists.sourceforge.net>;
	Wed, 21 Jan 2015 19:12:31 -0800 (PST)
MIME-Version: 1.0
X-Received: by 10.180.8.169 with SMTP id s9mr694361wia.72.1421896351174; Wed,
	21 Jan 2015 19:12:31 -0800 (PST)
Received: by 10.27.10.12 with HTTP; Wed, 21 Jan 2015 19:12:31 -0800 (PST)
In-Reply-To: <87egqnwt7g.fsf@rustcorp.com.au>
References: <CAPg+sBhk7F2OHT64i2LNSjv8DR5tD3RJkLJGzPGZW8OPQTCjQw@mail.gmail.com>
	<87egqnwt7g.fsf@rustcorp.com.au>
Date: Wed, 21 Jan 2015 22:12:31 -0500
Message-ID: <CAFVRnyqhU1aLvj_WxFPY2Vu2mEwhm7jiuKrdbnwJWqvCqPVxGQ@mail.gmail.com>
From: David Vorick <david.vorick@gmail.com>
Cc: Bitcoin Dev <bitcoin-development@lists.sourceforge.net>
Content-Type: multipart/alternative; boundary=f46d04430682eb53f0050d350a13
X-Spam-Score: 2.9 (++)
X-Spam-Report: Spam Filtering performed by mx.sourceforge.net.
	See http://spamassassin.org/tag/ for more details.
	-1.5 SPF_CHECK_PASS SPF reports sender host as permitted sender for
	sender-domain
	0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider
	(david.vorick[at]gmail.com)
	-0.0 SPF_PASS               SPF: sender matches SPF record
	1.2 MISSING_HEADERS        Missing To: header
	1.0 HTML_MESSAGE           BODY: HTML included in message
	-0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from
	author's domain
	0.1 DKIM_SIGNED            Message has a DKIM or DK signature,
	not necessarily valid
	-0.1 DKIM_VALID Message has at least one valid DKIM or DK signature
	2.2 MALFORMED_FREEMAIL Bad headers on message from free email service
X-Headers-End: 1YE8CD-0003Ua-5L
Subject: Re: [Bitcoin-development] [softfork proposal] Strict DER signatures
X-BeenThere: bitcoin-development@lists.sourceforge.net
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: <bitcoin-development.lists.sourceforge.net>
List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/bitcoin-development>,
	<mailto:bitcoin-development-request@lists.sourceforge.net?subject=unsubscribe>
List-Archive: <http://sourceforge.net/mailarchive/forum.php?forum_name=bitcoin-development>
List-Post: <mailto:bitcoin-development@lists.sourceforge.net>
List-Help: <mailto:bitcoin-development-request@lists.sourceforge.net?subject=help>
List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/bitcoin-development>,
	<mailto:bitcoin-development-request@lists.sourceforge.net?subject=subscribe>
X-List-Received-Date: Thu, 22 Jan 2015 03:12:40 -0000

--f46d04430682eb53f0050d350a13
Content-Type: text/plain; charset=UTF-8

Seems like a good change to me.

On Wed, Jan 21, 2015 at 7:32 PM, Rusty Russell <rusty@rustcorp.com.au>
wrote:

> Pieter Wuille <pieter.wuille@gmail.com> writes:
> > Hello everyone,
> >
> > We've been aware of the risk of depending on OpenSSL for consensus
> > rules for a while, and were trying to get rid of this as part of BIP
> > 62 (malleability protection), which was however postponed due to
> > unforeseen complexities. The recent evens (see the thread titled
> > "OpenSSL 1.0.0p / 1.0.1k incompatible, causes blockchain rejection."
> > on this mailing list) have made it clear that the problem is very
> > real, however, and I would prefer to have a fundamental solution for
> > it sooner rather than later.
>
> OK, I worked up a clearer (but more verbose) version with fewer
> magic numbers.  More importantly, feel free to steal the test cases.
>
> One weirdness is the restriction on maximum total length, rather than a
> 32 byte (33 with 0-prepad) limit on signatures themselves.
>
> Apologies for my babytalk C++.  Am sure there's a neater way.
>
> /* Licensed under Creative Commons zero (public domain). */
> #include <vector>
> #include <cstdlib>
> #include <cassert>
>
> #ifdef CLARIFY
> bool ConsumeByte(const std::vector<unsigned char> &sig, size_t &off,
>                  unsigned int &val)
> {
>     if (off >= sig.size()) return false;
>
>     val = sig[off++];
>     return true;
> }
>
> bool ConsumeTypeByte(const std::vector<unsigned char> &sig, size_t &off,
>                      unsigned int t)
> {
>     unsigned int type;
>     if (!ConsumeByte(sig, off, type)) return false;
>
>     return (type == t);
> }
>
> bool ConsumeNonZeroLength(const std::vector<unsigned char> &sig, size_t
> &off,
>                           unsigned int &len)
> {
>     if (!ConsumeByte(sig, off, len)) return false;
>
>     // Zero-length integers are not allowed.
>     return (len != 0);
> }
>
> bool ConsumeNumber(const std::vector<unsigned char> &sig, size_t &off,
>                    unsigned int len)
> {
>     // Length of number should be within signature.
>     if (off + len > sig.size()) return false;
>
>     // Negative numbers are not allowed.
>     if (sig[off] & 0x80) return false;
>
>     // Zero bytes at the start are not allowed, unless it would
>     // otherwise be interpreted as a negative number.
>     if (len > 1 && (sig[off] == 0x00) && !(sig[off+1] & 0x80)) return
> false;
>
>     // Consume number itself.
>     off += len;
>     return true;
> }
>
> // Consume a DER encoded integer, update off if successful.
> bool ConsumeDERInteger(const std::vector<unsigned char> &sig, size_t &off)
> {
>     unsigned int len;
>
>     // Type byte must be "integer"
>     if (!ConsumeTypeByte(sig, off, 0x02)) return false;
>     if (!ConsumeNonZeroLength(sig, off, len)) return false;
>     // Now the BE encoded value itself.
>     if (!ConsumeNumber(sig, off, len)) return false;
>
>     return true;
> }
>
> bool IsValidSignatureEncoding(const std::vector<unsigned char> &sig) {
>     // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
> [sighash]
>     // * total-length: 1-byte length descriptor of everything that follows,
>     //     excluding the sighash byte.
>     // * R-length: 1-byte length descriptor of the R value that follows.
>     // * R: arbitrary-length big-endian encoded R value. It cannot start
> with any
>     //     null bytes, unless the first byte that follows is 0x80 or
> higher, in which
>     //     case a single null byte is required.
>     // * S-length: 1-byte length descriptor of the S value that follows.
>     // * S: arbitrary-length big-endian encoded S value. The same rules
> apply.
>     // * sighash: 1-byte value indicating what data is hashed.
>
>     // Accept empty signature as correctly encoded (but invalid) signature,
>     // even though it is not strictly DER.
>     if (sig.size() == 0) return true;
>
>     // Maximum size constraint.
>     if (sig.size() > 73) return false;
>
>     size_t off = 0;
>
>     // A signature is of type "compound".
>     if (!ConsumeTypeByte(sig, off, 0x30)) return false;
>
>     unsigned int len;
>     if (!ConsumeNonZeroLength(sig, off, len)) return false;
>
>     // Make sure the length covers the rest (except sighash).
>     if (len + 1 != sig.size() - off) return false;
>
>     // Check R value.
>     if (!ConsumeDERInteger(sig, off)) return false;
>
>     // Check S value.
>     if (!ConsumeDERInteger(sig, off)) return false;
>
>     // There should exactly one byte left (the sighash).
>     return off + 1 == sig.size() ? true : false;
> }
> #else
> bool IsValidSignatureEncoding(const std::vector<unsigned char> &sig) {
>     // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
> [sighash]
>     // * total-length: 1-byte length descriptor of everything that follows,
>     //     excluding the sighash byte.
>     // * R-length: 1-byte length descriptor of the R value that follows.
>     // * R: arbitrary-length big-endian encoded R value. It must use the
> shortest
>     //     possible encoding for a positive integers (which means no null
> bytes at
>     //     the start, except a single one when the next byte has its
> highest bit set).
>     // * S-length: 1-byte length descriptor of the S value that follows.
>     // * S: arbitrary-length big-endian encoded S value. The same rules
> apply.
>     // * sighash: 1-byte value indicating what data is hashed (not part of
> the DER
>     //     signature)
>
>     // Accept empty signature as correctly encoded (but invalid) signature,
>     // even though it is not strictly DER. This avoids needing full DER
> signatures
>     // in places where any invalid signature would do. Given that the
> empty string is
>     // always invalid as signature, this is safe.
>     if (sig.size() == 0) return true;
>
>     // Minimum and maximum size constraints.
>     if (sig.size() < 9) return false;
>     if (sig.size() > 73) return false;
>
>     // A signature is of type 0x30 (compound).
>     if (sig[0] != 0x30) return false;
>
>     // Make sure the length covers the entire signature.
>     if (sig[1] != sig.size() - 3) return false;
>
>     // Extract the length of the R element.
>     unsigned int lenR = sig[3];
>
>     // Make sure the length of the S element is still inside the signature.
>     if (5 + lenR >= sig.size()) return false;
>
>     // Extract the length of the S element.
>     unsigned int lenS = sig[5 + lenR];
>
>     // Verify that the length of the signature matches the sum of the
> length
>     // of the elements.
>     if ((size_t)(lenR + lenS + 7) != sig.size()) return false;
>
>     // Check whether the R element is an integer.
>     if (sig[2] != 0x02) return false;
>
>     // Zero-length integers are not allowed for R.
>     if (lenR == 0) return false;
>
>     // Negative numbers are not allowed for R.
>     if (sig[4] & 0x80) return false;
>
>     // Null bytes at the start of R are not allowed, unless R would
>     // otherwise be interpreted as a negative number.
>     if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) return false;
>
>     // Check whether the S element is an integer.
>     if (sig[lenR + 4] != 0x02) return false;
>
>     // Zero-length integers are not allowed for S.
>     if (lenS == 0) return false;
>
>     // Negative numbers are not allowed for S.
>     if (sig[lenR + 6] & 0x80) return false;
>
>     // Null bytes at the start of S are not allowed, unless S would
> otherwise be
>     // interpreted as a negative number.
>     if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80))
> return false;
>
>     return true;
> }
> #endif
>
> #define COMPOUND 0x30
> #define NOT_COMPOUND 0x31
>
> // Len gets adjusted by check() to be actual length with this offset.
> #define LEN_OK 0
> #define LEN_TOO_BIG 1
> #define LEN_TOO_SMALL 0xff
>
> #define INT 0x02
> #define NOT_INT 0x03
>
> #define MINIMAL_SIGLEN 1
> #define MINIMAL_SIGVAL 0x0
>
> #define NORMAL_SIGLEN 32
> #define NORMAL_SIGVAL(S) S, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
>         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,              \
>         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,              \
>         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
>
> // 33 bytes is possible, with 0 prepended.
> #define MAXIMAL_SIGLEN 33
> #define MAXIMAL_SIGVAL(S) NORMAL_SIGVAL(S), 0x20
>
> #define OVERSIZE_SIGLEN 34
> #define OVERSIZE_SIGVAL(S) MAXIMAL_SIGVAL(S), 0x21
>
> #define ZEROPAD_SIGLEN (1 + NORMAL_SIGLEN)
> #define ZEROPAD_SIGVAL(S) 00, NORMAL_SIGVAL(S)
>
> #define SIGHASH 0xf0
>
> static bool check(const std::vector<unsigned char> &sig)
> {
>     std::vector<unsigned char> fixed = sig;
>
>     // Fixup length
>     if (fixed.size() > 1)
>         fixed[1] += fixed.size() - 3;
>     return IsValidSignatureEncoding(fixed);
> }
>
> #define good(arr) assert(check(std::vector<unsigned char>(arr,
> arr+sizeof(arr))))
> #define bad(arr) assert(!check(std::vector<unsigned char>(arr,
> arr+sizeof(arr))))
>
> // The OK cases.
> static unsigned char zerolen[] = { };
> static unsigned char normal[] = { COMPOUND, LEN_OK,
>                                   INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x1),
>                                   INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x2),
>                                   SIGHASH };
> static unsigned char min_r[] = { COMPOUND, LEN_OK,
>                                  INT, MINIMAL_SIGLEN, MINIMAL_SIGVAL,
>                                  INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x2),
>                                  SIGHASH };
> static unsigned char min_s[] = { COMPOUND, LEN_OK,
>                                  INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x1),
>                                  INT, MINIMAL_SIGLEN, MINIMAL_SIGVAL,
>                                  SIGHASH };
> static unsigned char max_r[] = { COMPOUND, LEN_OK,
>                                  INT, MAXIMAL_SIGLEN, MAXIMAL_SIGVAL(0x1),
>                                  INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x2),
>                                  SIGHASH };
> static unsigned char max_s[] = { COMPOUND, LEN_OK,
>                                  INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x1),
>                                  INT, MAXIMAL_SIGLEN, MAXIMAL_SIGVAL(0x2),
>                                  SIGHASH };
> // As long as total size doesn't go over, a single sig is allowed > 33
> bytes
> static unsigned char wierd_s_len[] = { COMPOUND, LEN_OK,
>                                        INT, OVERSIZE_SIGLEN,
> OVERSIZE_SIGVAL(0x1),
>                                        INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                        SIGHASH };
> static unsigned char wierd_r_len[] = { COMPOUND, LEN_OK,
>                                        INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                        INT, OVERSIZE_SIGLEN,
> OVERSIZE_SIGVAL(0x2),
>                                        SIGHASH };
> static unsigned char zeropad_s[] = { COMPOUND, LEN_OK,
>                                      INT, ZEROPAD_SIGLEN,
> ZEROPAD_SIGVAL(0x81),
>                                      INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                      SIGHASH };
> static unsigned char zeropad_r[] = { COMPOUND, LEN_OK,
>                                      INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                      INT, ZEROPAD_SIGLEN,
> ZEROPAD_SIGVAL(0x82),
>                                      SIGHASH };
>
>
> // The fail cases.
> static unsigned char not_compound[] = { NOT_COMPOUND, LEN_OK,
>                                         INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                         INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                         SIGHASH };
> static unsigned char short_len[] = { COMPOUND, LEN_TOO_SMALL,
>                                      INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                      INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                      SIGHASH };
> static unsigned char long_len[] = { COMPOUND, LEN_TOO_BIG,
>                                     INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x1),
>                                     INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x2),
>                                     SIGHASH };
> static unsigned char r_notint[] = { COMPOUND, LEN_OK,
>                                     NOT_INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                     INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x2),
>                                     SIGHASH };
> static unsigned char s_notint[] = { COMPOUND, LEN_OK,
>                                     INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x1),
>                                     NOT_INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                     SIGHASH };
> static unsigned char s_oversig[] = { COMPOUND, LEN_OK,
>                                      INT, OVERSIZE_SIGLEN,
> OVERSIZE_SIGVAL(0x1),
>                                      INT, MAXIMAL_SIGLEN,
> MAXIMAL_SIGVAL(0x2),
>                                      SIGHASH };
> static unsigned char r_oversig[] = { COMPOUND, LEN_OK,
>                                      INT, MAXIMAL_SIGLEN,
> MAXIMAL_SIGVAL(0x1),
>                                      INT, OVERSIZE_SIGLEN,
> OVERSIZE_SIGVAL(0x2),
>                                      SIGHASH };
> static unsigned char s_negative[] = { COMPOUND, LEN_OK,
>                                       INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x81),
>                                       INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                       SIGHASH };
> static unsigned char r_negative[] = { COMPOUND, LEN_OK,
>                                       INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                       INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x82),
>                                       SIGHASH };
> static unsigned char zeropad_bad_s[] = { COMPOUND, LEN_OK,
>                                          INT, ZEROPAD_SIGLEN,
> ZEROPAD_SIGVAL(0x1),
>                                          INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                          SIGHASH };
> static unsigned char zeropad_bad_r[] = { COMPOUND, LEN_OK,
>                                          INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                          INT, ZEROPAD_SIGLEN,
> ZEROPAD_SIGVAL(0x2),
>                                          SIGHASH };
> static unsigned char missing_sighash[] = { COMPOUND, LEN_OK,
>                                            INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                            INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2) };
> static unsigned char extra_byte[] = { COMPOUND, LEN_OK,
>                                       INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                       INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                       SIGHASH, 0 };
>
> // Bad signature lengths
> static unsigned char zerolen_r[] = { COMPOUND, LEN_OK,
>                                      INT, 0,
>                                      INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                      SIGHASH };
> static unsigned char zerolen_s[] = { COMPOUND, LEN_OK,
>                                      INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                      INT, 0,
>                                      SIGHASH };
> static unsigned char overlen_r_by_1[] = { COMPOUND, LEN_OK,
>                                           INT, NORMAL_SIGLEN + 1 + 1 +
> NORMAL_SIGLEN + 1 + 1, NORMAL_SIGVAL(0x1),
>                                           INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                           SIGHASH };
> static unsigned char overlen_s_by_1[] = { COMPOUND, LEN_OK,
>                                           INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                           INT, NORMAL_SIGLEN+1+1,
> NORMAL_SIGVAL(0x2),
>                                           SIGHASH };
> static unsigned char underlen_r_by_1[] = { COMPOUND, LEN_OK,
>                                            INT, NORMAL_SIGLEN-1,
> NORMAL_SIGVAL(0x1),
>                                            INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x2),
>                                            SIGHASH };
> static unsigned char underlen_s_by_1[] = { COMPOUND, LEN_OK,
>                                            INT, NORMAL_SIGLEN,
> NORMAL_SIGVAL(0x1),
>                                            INT, NORMAL_SIGLEN-1,
> NORMAL_SIGVAL(0x2),
>                                            SIGHASH };
>
> int main()
> {
>     good(zerolen);
>     good(normal);
>     good(min_r);
>     good(min_s);
>     good(max_r);
>     good(max_s);
>     good(wierd_s_len);
>     good(wierd_r_len);
>     good(zeropad_s);
>     good(zeropad_r);
>
>     // Try different amounts of truncation.
>     for (size_t i = 1; i < sizeof(normal)-1; i++)
>         assert(!check(std::vector<unsigned char>(normal, normal+i)));
>
>     bad(not_compound);
>     bad(short_len);
>     bad(long_len);
>     bad(r_notint);
>     bad(s_notint);
>     bad(s_oversig);
>     bad(r_oversig);
>     bad(s_negative);
>     bad(r_negative);
>     bad(s_negative);
>     bad(r_negative);
>     bad(zeropad_bad_s);
>     bad(zeropad_bad_r);
>     bad(zerolen_r);
>     bad(zerolen_s);
>     bad(overlen_r_by_1);
>     bad(overlen_s_by_1);
>     bad(underlen_r_by_1);
>     bad(underlen_s_by_1);
>     bad(missing_sighash);
>     bad(extra_byte);
>
>     return 0;
> }
>
>
>
>
> ------------------------------------------------------------------------------
> New Year. New Location. New Benefits. New Data Center in Ashburn, VA.
> GigeNET is offering a free month of service with a new server in Ashburn.
> Choose from 2 high performing configs, both with 100TB of bandwidth.
> Higher redundancy.Lower latency.Increased capacity.Completely compliant.
> http://p.sf.net/sfu/gigenet
> _______________________________________________
> Bitcoin-development mailing list
> Bitcoin-development@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/bitcoin-development
>

--f46d04430682eb53f0050d350a13
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Seems like a good change to me.<br></div><div class=3D"gma=
il_extra"><br><div class=3D"gmail_quote">On Wed, Jan 21, 2015 at 7:32 PM, R=
usty Russell <span dir=3D"ltr">&lt;<a href=3D"mailto:rusty@rustcorp.com.au"=
 target=3D"_blank">rusty@rustcorp.com.au</a>&gt;</span> wrote:<br><blockquo=
te class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc so=
lid;padding-left:1ex"><span class=3D"">Pieter Wuille &lt;<a href=3D"mailto:=
pieter.wuille@gmail.com">pieter.wuille@gmail.com</a>&gt; writes:<br>
&gt; Hello everyone,<br>
&gt;<br>
&gt; We&#39;ve been aware of the risk of depending on OpenSSL for consensus=
<br>
&gt; rules for a while, and were trying to get rid of this as part of BIP<b=
r>
&gt; 62 (malleability protection), which was however postponed due to<br>
&gt; unforeseen complexities. The recent evens (see the thread titled<br>
&gt; &quot;OpenSSL 1.0.0p / 1.0.1k incompatible, causes blockchain rejectio=
n.&quot;<br>
&gt; on this mailing list) have made it clear that the problem is very<br>
&gt; real, however, and I would prefer to have a fundamental solution for<b=
r>
&gt; it sooner rather than later.<br>
<br>
</span>OK, I worked up a clearer (but more verbose) version with fewer<br>
magic numbers.=C2=A0 More importantly, feel free to steal the test cases.<b=
r>
<br>
One weirdness is the restriction on maximum total length, rather than a<br>
32 byte (33 with 0-prepad) limit on signatures themselves.<br>
<br>
Apologies for my babytalk C++.=C2=A0 Am sure there&#39;s a neater way.<br>
<br>
/* Licensed under Creative Commons zero (public domain). */<br>
#include &lt;vector&gt;<br>
#include &lt;cstdlib&gt;<br>
#include &lt;cassert&gt;<br>
<br>
#ifdef CLARIFY<br>
bool ConsumeByte(const std::vector&lt;unsigned char&gt; &amp;sig, size_t &a=
mp;off,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned int =
&amp;val)<br>
{<br>
=C2=A0 =C2=A0 if (off &gt;=3D sig.size()) return false;<br>
<br>
=C2=A0 =C2=A0 val =3D sig[off++];<br>
=C2=A0 =C2=A0 return true;<br>
}<br>
<br>
bool ConsumeTypeByte(const std::vector&lt;unsigned char&gt; &amp;sig, size_=
t &amp;off,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0unsigned int t)<br>
{<br>
=C2=A0 =C2=A0 unsigned int type;<br>
=C2=A0 =C2=A0 if (!ConsumeByte(sig, off, type)) return false;<br>
<br>
=C2=A0 =C2=A0 return (type =3D=3D t);<br>
}<br>
<br>
bool ConsumeNonZeroLength(const std::vector&lt;unsigned char&gt; &amp;sig, =
size_t &amp;off,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 unsigned int &amp;len)<br>
{<br>
=C2=A0 =C2=A0 if (!ConsumeByte(sig, off, len)) return false;<br>
<br>
=C2=A0 =C2=A0 // Zero-length integers are not allowed.<br>
=C2=A0 =C2=A0 return (len !=3D 0);<br>
}<br>
<br>
bool ConsumeNumber(const std::vector&lt;unsigned char&gt; &amp;sig, size_t =
&amp;off,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0unsign=
ed int len)<br>
{<br>
=C2=A0 =C2=A0 // Length of number should be within signature.<br>
=C2=A0 =C2=A0 if (off + len &gt; sig.size()) return false;<br>
<br>
=C2=A0 =C2=A0 // Negative numbers are not allowed.<br>
=C2=A0 =C2=A0 if (sig[off] &amp; 0x80) return false;<br>
<br>
=C2=A0 =C2=A0 // Zero bytes at the start are not allowed, unless it would<b=
r>
=C2=A0 =C2=A0 // otherwise be interpreted as a negative number.<br>
=C2=A0 =C2=A0 if (len &gt; 1 &amp;&amp; (sig[off] =3D=3D 0x00) &amp;&amp; !=
(sig[off+1] &amp; 0x80)) return false;<br>
<br>
=C2=A0 =C2=A0 // Consume number itself.<br>
=C2=A0 =C2=A0 off +=3D len;<br>
=C2=A0 =C2=A0 return true;<br>
}<br>
<br>
// Consume a DER encoded integer, update off if successful.<br>
bool ConsumeDERInteger(const std::vector&lt;unsigned char&gt; &amp;sig, siz=
e_t &amp;off) {<br>
=C2=A0 =C2=A0 unsigned int len;<br>
<br>
=C2=A0 =C2=A0 // Type byte must be &quot;integer&quot;<br>
=C2=A0 =C2=A0 if (!ConsumeTypeByte(sig, off, 0x02)) return false;<br>
=C2=A0 =C2=A0 if (!ConsumeNonZeroLength(sig, off, len)) return false;<br>
=C2=A0 =C2=A0 // Now the BE encoded value itself.<br>
=C2=A0 =C2=A0 if (!ConsumeNumber(sig, off, len)) return false;<br>
<br>
=C2=A0 =C2=A0 return true;<br>
}<br>
<br>
bool IsValidSignatureEncoding(const std::vector&lt;unsigned char&gt; &amp;s=
ig) {<br>
=C2=A0 =C2=A0 // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-le=
ngth] [S] [sighash]<br>
=C2=A0 =C2=A0 // * total-length: 1-byte length descriptor of everything tha=
t follows,<br>
=C2=A0 =C2=A0 //=C2=A0 =C2=A0 =C2=A0excluding the sighash byte.<br>
=C2=A0 =C2=A0 // * R-length: 1-byte length descriptor of the R value that f=
ollows.<br>
=C2=A0 =C2=A0 // * R: arbitrary-length big-endian encoded R value. It canno=
t start with any<br>
=C2=A0 =C2=A0 //=C2=A0 =C2=A0 =C2=A0null bytes, unless the first byte that =
follows is 0x80 or higher, in which<br>
=C2=A0 =C2=A0 //=C2=A0 =C2=A0 =C2=A0case a single null byte is required.<br=
>
=C2=A0 =C2=A0 // * S-length: 1-byte length descriptor of the S value that f=
ollows.<br>
=C2=A0 =C2=A0 // * S: arbitrary-length big-endian encoded S value. The same=
 rules apply.<br>
=C2=A0 =C2=A0 // * sighash: 1-byte value indicating what data is hashed.<br=
>
<br>
=C2=A0 =C2=A0 // Accept empty signature as correctly encoded (but invalid) =
signature,<br>
=C2=A0 =C2=A0 // even though it is not strictly DER.<br>
=C2=A0 =C2=A0 if (sig.size() =3D=3D 0) return true;<br>
<br>
=C2=A0 =C2=A0 // Maximum size constraint.<br>
=C2=A0 =C2=A0 if (sig.size() &gt; 73) return false;<br>
<br>
=C2=A0 =C2=A0 size_t off =3D 0;<br>
<br>
=C2=A0 =C2=A0 // A signature is of type &quot;compound&quot;.<br>
=C2=A0 =C2=A0 if (!ConsumeTypeByte(sig, off, 0x30)) return false;<br>
<br>
=C2=A0 =C2=A0 unsigned int len;<br>
=C2=A0 =C2=A0 if (!ConsumeNonZeroLength(sig, off, len)) return false;<br>
<br>
=C2=A0 =C2=A0 // Make sure the length covers the rest (except sighash).<br>
=C2=A0 =C2=A0 if (len + 1 !=3D sig.size() - off) return false;<br>
<br>
=C2=A0 =C2=A0 // Check R value.<br>
=C2=A0 =C2=A0 if (!ConsumeDERInteger(sig, off)) return false;<br>
<br>
=C2=A0 =C2=A0 // Check S value.<br>
=C2=A0 =C2=A0 if (!ConsumeDERInteger(sig, off)) return false;<br>
<br>
=C2=A0 =C2=A0 // There should exactly one byte left (the sighash).<br>
=C2=A0 =C2=A0 return off + 1 =3D=3D sig.size() ? true : false;<br>
}<br>
#else<br>
bool IsValidSignatureEncoding(const std::vector&lt;unsigned char&gt; &amp;s=
ig) {<br>
=C2=A0 =C2=A0 // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-le=
ngth] [S] [sighash]<br>
=C2=A0 =C2=A0 // * total-length: 1-byte length descriptor of everything tha=
t follows,<br>
=C2=A0 =C2=A0 //=C2=A0 =C2=A0 =C2=A0excluding the sighash byte.<br>
=C2=A0 =C2=A0 // * R-length: 1-byte length descriptor of the R value that f=
ollows.<br>
=C2=A0 =C2=A0 // * R: arbitrary-length big-endian encoded R value. It must =
use the shortest<br>
=C2=A0 =C2=A0 //=C2=A0 =C2=A0 =C2=A0possible encoding for a positive intege=
rs (which means no null bytes at<br>
=C2=A0 =C2=A0 //=C2=A0 =C2=A0 =C2=A0the start, except a single one when the=
 next byte has its highest bit set).<br>
=C2=A0 =C2=A0 // * S-length: 1-byte length descriptor of the S value that f=
ollows.<br>
=C2=A0 =C2=A0 // * S: arbitrary-length big-endian encoded S value. The same=
 rules apply.<br>
=C2=A0 =C2=A0 // * sighash: 1-byte value indicating what data is hashed (no=
t part of the DER<br>
=C2=A0 =C2=A0 //=C2=A0 =C2=A0 =C2=A0signature)<br>
<br>
=C2=A0 =C2=A0 // Accept empty signature as correctly encoded (but invalid) =
signature,<br>
=C2=A0 =C2=A0 // even though it is not strictly DER. This avoids needing fu=
ll DER signatures<br>
=C2=A0 =C2=A0 // in places where any invalid signature would do. Given that=
 the empty string is<br>
=C2=A0 =C2=A0 // always invalid as signature, this is safe.<br>
=C2=A0 =C2=A0 if (sig.size() =3D=3D 0) return true;<br>
<br>
=C2=A0 =C2=A0 // Minimum and maximum size constraints.<br>
=C2=A0 =C2=A0 if (sig.size() &lt; 9) return false;<br>
=C2=A0 =C2=A0 if (sig.size() &gt; 73) return false;<br>
<br>
=C2=A0 =C2=A0 // A signature is of type 0x30 (compound).<br>
=C2=A0 =C2=A0 if (sig[0] !=3D 0x30) return false;<br>
<br>
=C2=A0 =C2=A0 // Make sure the length covers the entire signature.<br>
=C2=A0 =C2=A0 if (sig[1] !=3D sig.size() - 3) return false;<br>
<br>
=C2=A0 =C2=A0 // Extract the length of the R element.<br>
=C2=A0 =C2=A0 unsigned int lenR =3D sig[3];<br>
<br>
=C2=A0 =C2=A0 // Make sure the length of the S element is still inside the =
signature.<br>
=C2=A0 =C2=A0 if (5 + lenR &gt;=3D sig.size()) return false;<br>
<br>
=C2=A0 =C2=A0 // Extract the length of the S element.<br>
=C2=A0 =C2=A0 unsigned int lenS =3D sig[5 + lenR];<br>
<br>
=C2=A0 =C2=A0 // Verify that the length of the signature matches the sum of=
 the length<br>
=C2=A0 =C2=A0 // of the elements.<br>
=C2=A0 =C2=A0 if ((size_t)(lenR + lenS + 7) !=3D sig.size()) return false;<=
br>
<br>
=C2=A0 =C2=A0 // Check whether the R element is an integer.<br>
=C2=A0 =C2=A0 if (sig[2] !=3D 0x02) return false;<br>
<br>
=C2=A0 =C2=A0 // Zero-length integers are not allowed for R.<br>
=C2=A0 =C2=A0 if (lenR =3D=3D 0) return false;<br>
<br>
=C2=A0 =C2=A0 // Negative numbers are not allowed for R.<br>
=C2=A0 =C2=A0 if (sig[4] &amp; 0x80) return false;<br>
<br>
=C2=A0 =C2=A0 // Null bytes at the start of R are not allowed, unless R wou=
ld<br>
=C2=A0 =C2=A0 // otherwise be interpreted as a negative number.<br>
=C2=A0 =C2=A0 if (lenR &gt; 1 &amp;&amp; (sig[4] =3D=3D 0x00) &amp;&amp; !(=
sig[5] &amp; 0x80)) return false;<br>
<br>
=C2=A0 =C2=A0 // Check whether the S element is an integer.<br>
=C2=A0 =C2=A0 if (sig[lenR + 4] !=3D 0x02) return false;<br>
<br>
=C2=A0 =C2=A0 // Zero-length integers are not allowed for S.<br>
=C2=A0 =C2=A0 if (lenS =3D=3D 0) return false;<br>
<br>
=C2=A0 =C2=A0 // Negative numbers are not allowed for S.<br>
=C2=A0 =C2=A0 if (sig[lenR + 6] &amp; 0x80) return false;<br>
<br>
=C2=A0 =C2=A0 // Null bytes at the start of S are not allowed, unless S wou=
ld otherwise be<br>
<span class=3D"">=C2=A0 =C2=A0 // interpreted as a negative number.<br>
=C2=A0 =C2=A0 if (lenS &gt; 1 &amp;&amp; (sig[lenR + 6] =3D=3D 0x00) &amp;&=
amp; !(sig[lenR + 7] &amp; 0x80)) return false;<br>
<br>
</span>=C2=A0 =C2=A0 return true;<br>
}<br>
#endif<br>
<br>
#define COMPOUND 0x30<br>
#define NOT_COMPOUND 0x31<br>
<br>
// Len gets adjusted by check() to be actual length with this offset.<br>
#define LEN_OK 0<br>
#define LEN_TOO_BIG 1<br>
#define LEN_TOO_SMALL 0xff<br>
<br>
#define INT 0x02<br>
#define NOT_INT 0x03<br>
<br>
#define MINIMAL_SIGLEN 1<br>
#define MINIMAL_SIGVAL 0x0<br>
<br>
#define NORMAL_SIGLEN 32<br>
#define NORMAL_SIGVAL(S) S, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 \<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 \<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f<=
br>
<br>
// 33 bytes is possible, with 0 prepended.<br>
#define MAXIMAL_SIGLEN 33<br>
#define MAXIMAL_SIGVAL(S) NORMAL_SIGVAL(S), 0x20<br>
<br>
#define OVERSIZE_SIGLEN 34<br>
#define OVERSIZE_SIGVAL(S) MAXIMAL_SIGVAL(S), 0x21<br>
<br>
#define ZEROPAD_SIGLEN (1 + NORMAL_SIGLEN)<br>
#define ZEROPAD_SIGVAL(S) 00, NORMAL_SIGVAL(S)<br>
<br>
#define SIGHASH 0xf0<br>
<br>
static bool check(const std::vector&lt;unsigned char&gt; &amp;sig)<br>
{<br>
=C2=A0 =C2=A0 std::vector&lt;unsigned char&gt; fixed =3D sig;<br>
<br>
=C2=A0 =C2=A0 // Fixup length<br>
=C2=A0 =C2=A0 if (fixed.size() &gt; 1)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 fixed[1] +=3D fixed.size() - 3;<br>
=C2=A0 =C2=A0 return IsValidSignatureEncoding(fixed);<br>
}<br>
<br>
#define good(arr) assert(check(std::vector&lt;unsigned char&gt;(arr, arr+si=
zeof(arr))))<br>
#define bad(arr) assert(!check(std::vector&lt;unsigned char&gt;(arr, arr+si=
zeof(arr))))<br>
<br>
// The OK cases.<br>
static unsigned char zerolen[] =3D { };<br>
static unsigned char normal[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIGLEN, NORMAL_SI=
GVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIGLEN, NORMAL_SI=
GVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SIGHASH };<br>
static unsigned char min_r[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, MINIMAL_SIGLEN, MINIMAL_S=
IGVAL,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORMAL_SIGLEN, NORMAL_SIG=
VAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
static unsigned char min_s[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORMAL_SIGLEN, NORMAL_SIG=
VAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, MINIMAL_SIGLEN, MINIMAL_S=
IGVAL,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
static unsigned char max_r[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, MAXIMAL_SIGLEN, MAXIMAL_S=
IGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORMAL_SIGLEN, NORMAL_SIG=
VAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
static unsigned char max_s[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORMAL_SIGLEN, NORMAL_SIG=
VAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, MAXIMAL_SIGLEN, MAXIMAL_S=
IGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
// As long as total size doesn&#39;t go over, a single sig is allowed &gt; =
33 bytes<br>
static unsigned char wierd_s_len[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, OVER=
SIZE_SIGLEN, OVERSIZE_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORM=
AL_SIGLEN, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH }=
;<br>
static unsigned char wierd_r_len[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORM=
AL_SIGLEN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, OVER=
SIZE_SIGLEN, OVERSIZE_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH }=
;<br>
static unsigned char zeropad_s[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, ZEROPAD_SIG=
LEN, ZEROPAD_SIGVAL(0x81),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORMAL_SIGL=
EN, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
static unsigned char zeropad_r[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORMAL_SIGL=
EN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, ZEROPAD_SIG=
LEN, ZEROPAD_SIGVAL(0x82),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
<br>
<br>
// The fail cases.<br>
static unsigned char not_compound[] =3D { NOT_COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NOR=
MAL_SIGLEN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NOR=
MAL_SIGLEN, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SIGHASH =
};<br>
static unsigned char short_len[] =3D { COMPOUND, LEN_TOO_SMALL,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORMAL_SIGL=
EN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORMAL_SIGL=
EN, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
static unsigned char long_len[] =3D { COMPOUND, LEN_TOO_BIG,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIGLEN, NO=
RMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIGLEN, NO=
RMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SIGHASH };<br>
static unsigned char r_notint[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NOT_INT, NORMAL_SIGLEN=
, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIGLEN, NO=
RMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SIGHASH };<br>
static unsigned char s_notint[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIGLEN, NO=
RMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NOT_INT, NORMAL_SIGLEN=
, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SIGHASH };<br>
static unsigned char s_oversig[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, OVERSIZE_SI=
GLEN, OVERSIZE_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, MAXIMAL_SIG=
LEN, MAXIMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
static unsigned char r_oversig[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, MAXIMAL_SIG=
LEN, MAXIMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, OVERSIZE_SI=
GLEN, OVERSIZE_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
static unsigned char s_negative[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIG=
LEN, NORMAL_SIGVAL(0x81),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIG=
LEN, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SIGHASH };<br>
static unsigned char r_negative[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIG=
LEN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIG=
LEN, NORMAL_SIGVAL(0x82),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SIGHASH };<br>
static unsigned char zeropad_bad_s[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0IN=
T, ZEROPAD_SIGLEN, ZEROPAD_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0IN=
T, NORMAL_SIGLEN, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SI=
GHASH };<br>
static unsigned char zeropad_bad_r[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0IN=
T, NORMAL_SIGLEN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0IN=
T, ZEROPAD_SIGLEN, ZEROPAD_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SI=
GHASH };<br>
static unsigned char missing_sighash[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x2) };<br>
static unsigned char extra_byte[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIG=
LEN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 INT, NORMAL_SIG=
LEN, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SIGHASH, 0 };<b=
r>
<br>
// Bad signature lengths<br>
static unsigned char zerolen_r[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, 0,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORMAL_SIGL=
EN, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
static unsigned char zerolen_s[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, NORMAL_SIGL=
EN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0INT, 0,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SIGHASH };<br>
static unsigned char overlen_r_by_1[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 I=
NT, NORMAL_SIGLEN + 1 + 1 + NORMAL_SIGLEN + 1 + 1, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 I=
NT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 S=
IGHASH };<br>
static unsigned char overlen_s_by_1[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 I=
NT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 I=
NT, NORMAL_SIGLEN+1+1, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 S=
IGHASH };<br>
static unsigned char underlen_r_by_1[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0INT, NORMAL_SIGLEN-1, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0SIGHASH };<br>
static unsigned char underlen_s_by_1[] =3D { COMPOUND, LEN_OK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0INT, NORMAL_SIGLEN, NORMAL_SIGVAL(0x1),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0INT, NORMAL_SIGLEN-1, NORMAL_SIGVAL(0x2),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0SIGHASH };<br>
<br>
int main()<br>
{<br>
=C2=A0 =C2=A0 good(zerolen);<br>
=C2=A0 =C2=A0 good(normal);<br>
=C2=A0 =C2=A0 good(min_r);<br>
=C2=A0 =C2=A0 good(min_s);<br>
=C2=A0 =C2=A0 good(max_r);<br>
=C2=A0 =C2=A0 good(max_s);<br>
=C2=A0 =C2=A0 good(wierd_s_len);<br>
=C2=A0 =C2=A0 good(wierd_r_len);<br>
=C2=A0 =C2=A0 good(zeropad_s);<br>
=C2=A0 =C2=A0 good(zeropad_r);<br>
<br>
=C2=A0 =C2=A0 // Try different amounts of truncation.<br>
=C2=A0 =C2=A0 for (size_t i =3D 1; i &lt; sizeof(normal)-1; i++)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 assert(!check(std::vector&lt;unsigned char&gt;(=
normal, normal+i)));<br>
<br>
=C2=A0 =C2=A0 bad(not_compound);<br>
=C2=A0 =C2=A0 bad(short_len);<br>
=C2=A0 =C2=A0 bad(long_len);<br>
=C2=A0 =C2=A0 bad(r_notint);<br>
=C2=A0 =C2=A0 bad(s_notint);<br>
=C2=A0 =C2=A0 bad(s_oversig);<br>
=C2=A0 =C2=A0 bad(r_oversig);<br>
=C2=A0 =C2=A0 bad(s_negative);<br>
=C2=A0 =C2=A0 bad(r_negative);<br>
=C2=A0 =C2=A0 bad(s_negative);<br>
=C2=A0 =C2=A0 bad(r_negative);<br>
=C2=A0 =C2=A0 bad(zeropad_bad_s);<br>
=C2=A0 =C2=A0 bad(zeropad_bad_r);<br>
=C2=A0 =C2=A0 bad(zerolen_r);<br>
=C2=A0 =C2=A0 bad(zerolen_s);<br>
=C2=A0 =C2=A0 bad(overlen_r_by_1);<br>
=C2=A0 =C2=A0 bad(overlen_s_by_1);<br>
=C2=A0 =C2=A0 bad(underlen_r_by_1);<br>
=C2=A0 =C2=A0 bad(underlen_s_by_1);<br>
=C2=A0 =C2=A0 bad(missing_sighash);<br>
=C2=A0 =C2=A0 bad(extra_byte);<br>
<br>
=C2=A0 =C2=A0 return 0;<br>
<div class=3D"HOEnZb"><div class=3D"h5">}<br>
<br>
<br>
<br>
---------------------------------------------------------------------------=
---<br>
New Year. New Location. New Benefits. New Data Center in Ashburn, VA.<br>
GigeNET is offering a free month of service with a new server in Ashburn.<b=
r>
Choose from 2 high performing configs, both with 100TB of bandwidth.<br>
Higher redundancy.Lower latency.Increased capacity.Completely compliant.<br=
>
<a href=3D"http://p.sf.net/sfu/gigenet" target=3D"_blank">http://p.sf.net/s=
fu/gigenet</a><br>
_______________________________________________<br>
Bitcoin-development mailing list<br>
<a href=3D"mailto:Bitcoin-development@lists.sourceforge.net">Bitcoin-develo=
pment@lists.sourceforge.net</a><br>
<a href=3D"https://lists.sourceforge.net/lists/listinfo/bitcoin-development=
" target=3D"_blank">https://lists.sourceforge.net/lists/listinfo/bitcoin-de=
velopment</a><br>
</div></div></blockquote></div><br></div>

--f46d04430682eb53f0050d350a13--