From 3dfd6e84a175653ca5d2a2c4390ee16c9d9cefaf Mon Sep 17 00:00:00 2001 From: Scott Walters Date: Sun, 15 Feb 2015 15:54:15 -0500 Subject: [PATCH] conicalize DER encoded signitures bitcoind was permissive with how DER encoding was done, which lead to the transaction malliability problem. the exact same transaction could be written multiple ways, signed, and then sent out to confuse people. part of the fix was conicalizing DER encoded signitures. DER encoded numbers now have all leading 0 bytes (0x00 hex) removed from the beginning *except* if the first byte would have its 8th bit, which would indicate that it's negative, which s and r are never in ecdsa signitures, in which case it gets exactly one 0x00 byte stuck on to the front. --- ecdsa.pm | 19 ++++++--- test/ecdsa | 115 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 79 insertions(+), 55 deletions(-) diff --git a/ecdsa.pm b/ecdsa.pm index 962b6a7..9368b28 100644 --- a/ecdsa.pm +++ b/ecdsa.pm @@ -213,20 +213,29 @@ sub pub_decode { sub hash_decode { my ($hash) = @_; - - my $s = length ($hash) * 8 - $EC_SIZE; + my $s = length ($hash) * 8 - $EC_SIZE; my $e = i_decode ($hash); $e = $e->brsft ($s) if $s > 0; return $e; } +sub ber_hex { + # like i_encode() but doesn't attempt to pad it out to any length and makes sure there is a leading null if otherwise the first high bit would be set (which would indicate negative, but these are never neg) + # standardizing on exactly this formatting of numbers was the main part of the "canonicalization" fix for the transaction mutability bug + my $i = shift; + my $bin = $i->as_hex; + $bin =~ s/^0x// or die $i; + $bin = '00' . $bin if hex( substr($bin, 0, 2) ) >= 0x80; + return pack 'H*', $bin; +} + sub sig_encode { my ($sig) = @_; my ($r, $s) = @$sig; - return pack 'C w/a', 0x30, - pack ('C w/a', 0x02, i_encode ($r)) . - pack ('C w/a', 0x02, i_encode ($s)); + return pack 'C C/a', 0x30, + pack ('C C/a', 0x02, ber_hex($r) ) . + pack ('C C/a', 0x02, ber_hex($s) ); } sub sig_decode { diff --git a/test/ecdsa b/test/ecdsa index c4cbac7..05406ef 100644 --- a/test/ecdsa +++ b/test/ecdsa @@ -1,50 +1,65 @@ -#! /usr/bin/perl -l -BEGIN { chdir '..' } - -use warnings; -use strict; - -use ecdsa; - -$ecdsa::PROB_VERIFY = 1; - -print ecdsa::version; - -ecdsa::p_oncurve ([ - ecdsa::i '0x11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c', - ecdsa::i '0xb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3', -]) or die; -print "ok 1"; - -ecdsa::ec_verify ([ - ecdsa::i '0x11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c', - ecdsa::i '0xb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3', -], ecdsa::hash_decode (pack 'H*', - '7a05c6145f10101e9d6325494245adf1297d80f8f38d4d576d57cdba220bcb19', -), [ - ecdsa::i '0x4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41', - ecdsa::i '0x181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09', -]) or die; -print "ok 2"; - -my $k = ecdsa::GenKey (); -my $h = 123; -my $s = ecdsa::Sign ($k, $h); -ecdsa::Verify ($k, $h, $s) or die; -print "ok 3"; - -while () { - my ($p, $h, $s) = /(\S+) (\S+) (\S+)/ or die; - $_ = pack 'H*', $_ for $p, $h, $s; - ecdsa::Verify ({ pub => $p }, $h, $s) or die $_; - print "ok"; -} - -__DATA__ -04c22551f7ada4ff0652684301e2a96748b6ab3371ee0cf574734f81a46cb43ca524a75b25c8e63243d46da91c9086dd5a7fc52112ae3853f7950a3f1e17fb664f a194083fee9582252f32bd8dabd226785725d1e7e178c1c5dd702bc8500a4bd5 304502202f9ef0928d14d3e8d8d38b84789dfee5fb2ad22d55e4198e9d3521c8cfe5a911022100f72915c2093025ae9e74da59bb9582476519b014bef9f9afa8e7892db0df701a -04e663fe1050fa91973f961c5f4c0602addb0264880a2246fdbfb5bce665687106b22fed361329c5cffad52b2efd543c5bcc6e7d8d41f4c8b7771c42d3a155eb36 303a1e60c51be64119b696ad10d03070ebfff2738133e5cd3df0e23faf899a8a 3045022100bcf1743c11fcd45a1e997c248719d38420c78017c770c2ce572d9df49b7721f402203cf012836205c60cbf32cff63781deb48cb4dbcc08a5d5a1b13c4c09351211e8 -04d8cd505bd4211bf09b419c0751b05e19877e1b49ee7d6dbd572eac7645c16c0316f5eb2cf2f74c533e8954cc2a6436889bbe81f9fff5570357eafa9537f88cc2 496dc279152521900ecc6dd25726bfbcbdd8602681209930c4f39ca21d330018 3045022100bd7a7fc3439fe8a949e957ccfffb657559d7fa8246d5c82dfd0d2b67fbd1ef170220188a2d3a3efec9cb60b0d2b873bedb6a80ed2b5ae24d03e2320ac856cb5a5141 -0452075f5c1e75fab286b37cafb30618ef108214b31ae42e4536977a7018d1551921d845ac69b0276236b3a70d64c65127413b8153c760f13bb22331af7671b73e 3380547d4eefdf3eaacfda0814afc8666771de21627905352f69b8437fd33d63 3046022100b44df2447333b183389314cb515d838f3e6660c500db5704f9e1c9773b0e2f4e022100da5aa03be11b7a49efaad6ccd94e2bd34e1907408ce78a9be7df8c2085fe81cd -04fe89ab4c34918953794aeade72310a52f653d33d38be8c7d552a06626ba3d97b17600383a2f7f9d38da16d29430e730944daebff34b1643fb453d7cc777554f6 48d27ba16fb410099ddb15ee6bbd04cecbd537e906d885f560fc8ab49aa06826 30450220290880d98d82f6a084d30e79724057d0a75225e45afd711c236346709eb56cdb022100ec91216b99fdbd66b9d501a7985801f545f8f90bbbb8e5e9393f120f12d643c0 -049bb20bd89b275d654c8a3bde8262b7b98b939f93a76929332c090ed0606661c90697c0f910206ef9caa136f9557122f5229e1e028324bc69197f6ba6f9c4603a 9a240baddbc2297e63c59cd273b8412e83e27da9aa90d7bbbf31a2338d208d67 30450220044944a8bd3c6a252ad2c50b66b66b32a7bd736d433eaff44c13b9f850d15b93022100fa300df45dd00ab84a743210d41704e0a23705fbbd95fb103cfdc98c2e9b5137 -04987df80fccecc297c66f84821279648f0868ca30beea4231eb7bf189071055abbf61a75469d379ae09245ebb39d584d9f67a83130ee95c45bd76b5d9e01aa7aa 17e5410cd8db696e37aaae85d3e687852305ac9540d553dc414fd362bdaf2dd6 3045022038d52df4f8a494be36aee617ca5fb28e585895190fa58e5aba199ccf1c90371b022100bb2960426f8e196d9a42fb02579f85ae26ab9956918241bd77f02bb6dfab3a6a +#! /usr/bin/perl -l +BEGIN { chdir '..' } + +use warnings; +use strict; + +use ecdsa; + +$ecdsa::PROB_VERIFY = 1; + +print ecdsa::version; + +ecdsa::p_oncurve ([ + ecdsa::i '0x11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c', + ecdsa::i '0xb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3', +]) or die; +print "ok 1"; + +ecdsa::ec_verify ([ + ecdsa::i '0x11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c', + ecdsa::i '0xb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3', +], ecdsa::hash_decode (pack 'H*', + '7a05c6145f10101e9d6325494245adf1297d80f8f38d4d576d57cdba220bcb19', +), [ + ecdsa::i '0x4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41', + ecdsa::i '0x181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09', +]) or die; +print "ok 2"; + +my $k = ecdsa::GenKey (); +my $h = 123; + +use Data::Dumper; +# warn Dumper $k; + +my $s = ecdsa::Sign ($k, $h); +ecdsa::Verify ($k, $h, $s) or die; +print "ok 3"; + +# test that DER encoded strings are correctly conicalized when generating ASN.1 encoded signitures + +$k = { priv => from_hex('313032373533323531323539343134313833383035303734333633333334323835323731373732313039363835353931393535383338383833343439313231383132383635343632323238343132') }; +$h = from_hex('3939363234303634303238353836333033343037373931303937393038383131303238343535373730383533333735323730343932343437383735303330383235333634313733373734343532'); +$s = ecdsa::Sign( $k, $h ); +print "ok 4" if $s eq from_hex('30460221009bb961c94162063af38f24fc058f66144d723f16a1896612151f763984e8e8750221009c8b8aa577b5a72b5e32114983c0c0bd02a788ea70c91fb49138b44945a99b00'); + +while () { + my ($p, $h, $s) = /(\S+) (\S+) (\S+)/ or die; + $_ = pack 'H*', $_ for $p, $h, $s; + ecdsa::Verify ({ pub => $p }, $h, $s) or die $_; + print "ok"; +} + +sub from_hex { + pack( "H*", $_[0] ); +} + +__DATA__ +04c22551f7ada4ff0652684301e2a96748b6ab3371ee0cf574734f81a46cb43ca524a75b25c8e63243d46da91c9086dd5a7fc52112ae3853f7950a3f1e17fb664f a194083fee9582252f32bd8dabd226785725d1e7e178c1c5dd702bc8500a4bd5 304502202f9ef0928d14d3e8d8d38b84789dfee5fb2ad22d55e4198e9d3521c8cfe5a911022100f72915c2093025ae9e74da59bb9582476519b014bef9f9afa8e7892db0df701a +04e663fe1050fa91973f961c5f4c0602addb0264880a2246fdbfb5bce665687106b22fed361329c5cffad52b2efd543c5bcc6e7d8d41f4c8b7771c42d3a155eb36 303a1e60c51be64119b696ad10d03070ebfff2738133e5cd3df0e23faf899a8a 3045022100bcf1743c11fcd45a1e997c248719d38420c78017c770c2ce572d9df49b7721f402203cf012836205c60cbf32cff63781deb48cb4dbcc08a5d5a1b13c4c09351211e8 +04d8cd505bd4211bf09b419c0751b05e19877e1b49ee7d6dbd572eac7645c16c0316f5eb2cf2f74c533e8954cc2a6436889bbe81f9fff5570357eafa9537f88cc2 496dc279152521900ecc6dd25726bfbcbdd8602681209930c4f39ca21d330018 3045022100bd7a7fc3439fe8a949e957ccfffb657559d7fa8246d5c82dfd0d2b67fbd1ef170220188a2d3a3efec9cb60b0d2b873bedb6a80ed2b5ae24d03e2320ac856cb5a5141 +0452075f5c1e75fab286b37cafb30618ef108214b31ae42e4536977a7018d1551921d845ac69b0276236b3a70d64c65127413b8153c760f13bb22331af7671b73e 3380547d4eefdf3eaacfda0814afc8666771de21627905352f69b8437fd33d63 3046022100b44df2447333b183389314cb515d838f3e6660c500db5704f9e1c9773b0e2f4e022100da5aa03be11b7a49efaad6ccd94e2bd34e1907408ce78a9be7df8c2085fe81cd +04fe89ab4c34918953794aeade72310a52f653d33d38be8c7d552a06626ba3d97b17600383a2f7f9d38da16d29430e730944daebff34b1643fb453d7cc777554f6 48d27ba16fb410099ddb15ee6bbd04cecbd537e906d885f560fc8ab49aa06826 30450220290880d98d82f6a084d30e79724057d0a75225e45afd711c236346709eb56cdb022100ec91216b99fdbd66b9d501a7985801f545f8f90bbbb8e5e9393f120f12d643c0 +049bb20bd89b275d654c8a3bde8262b7b98b939f93a76929332c090ed0606661c90697c0f910206ef9caa136f9557122f5229e1e028324bc69197f6ba6f9c4603a 9a240baddbc2297e63c59cd273b8412e83e27da9aa90d7bbbf31a2338d208d67 30450220044944a8bd3c6a252ad2c50b66b66b32a7bd736d433eaff44c13b9f850d15b93022100fa300df45dd00ab84a743210d41704e0a23705fbbd95fb103cfdc98c2e9b5137 +04987df80fccecc297c66f84821279648f0868ca30beea4231eb7bf189071055abbf61a75469d379ae09245ebb39d584d9f67a83130ee95c45bd76b5d9e01aa7aa 17e5410cd8db696e37aaae85d3e687852305ac9540d553dc414fd362bdaf2dd6 3045022038d52df4f8a494be36aee617ca5fb28e585895190fa58e5aba199ccf1c90371b022100bb2960426f8e196d9a42fb02579f85ae26ab9956918241bd77f02bb6dfab3a6a