|
25 | 25 | _bchr = lambda x: bytes([x]) |
26 | 26 | _bord = lambda x: x |
27 | 27 |
|
| 28 | +import array |
28 | 29 | import copy |
29 | 30 | import struct |
30 | 31 |
|
@@ -797,6 +798,57 @@ def FindAndDelete(script, sig): |
797 | 798 | r += script[last_sop_idx:] |
798 | 799 | return CScript(r) |
799 | 800 |
|
| 801 | +def IsLowDERSignature(sig): |
| 802 | + """ |
| 803 | + Loosely correlates with IsLowDERSignature() from script/interpreter.cpp |
| 804 | + Verifies that the S value in a DER signature is the lowest possible value. |
| 805 | + Used by BIP62 malleability fixes. |
| 806 | + """ |
| 807 | + length_r = sig[3] |
| 808 | + if isinstance(length_r, str): |
| 809 | + length_r = int(struct.unpack('B', length_r)[0]) |
| 810 | + length_s = sig[5 + length_r] |
| 811 | + if isinstance(length_s, str): |
| 812 | + length_s = int(struct.unpack('B', length_s)[0]) |
| 813 | + s_val = list(struct.unpack(str(length_s) + 'B', sig[6 + length_r:6 + length_r + length_s])) |
| 814 | + |
| 815 | + # If the S value is above the order of the curve divided by two, its |
| 816 | + # complement modulo the order could have been used instead, which is |
| 817 | + # one byte shorter when encoded correctly. |
| 818 | + max_mod_half_order = [ |
| 819 | + 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 820 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 821 | + 0x5d,0x57,0x6e,0x73,0x57,0xa4,0x50,0x1d, |
| 822 | + 0xdf,0xe9,0x2f,0x46,0x68,0x1b,0x20,0xa0] |
| 823 | + |
| 824 | + return CompareBigEndian(s_val, [0]) > 0 and \ |
| 825 | + CompareBigEndian(s_val, max_mod_half_order) <= 0 |
| 826 | + |
| 827 | +def CompareBigEndian(c1, c2): |
| 828 | + """ |
| 829 | + Loosely matches CompareBigEndian() from eccryptoverify.cpp |
| 830 | + Compares two arrays of bytes, and returns a negative value if the first is |
| 831 | + less than the second, 0 if they're equal, and a positive value if the |
| 832 | + first is greater than the second. |
| 833 | + """ |
| 834 | + c1 = list(c1) |
| 835 | + c2 = list(c2) |
| 836 | + |
| 837 | + # Adjust starting positions until remaining lengths of the two arrays match |
| 838 | + while len(c1) > len(c2): |
| 839 | + if c1.pop(0) > 0: |
| 840 | + return 1 |
| 841 | + while len(c2) > len(c1): |
| 842 | + if c2.pop(0) > 0: |
| 843 | + return -1 |
| 844 | + |
| 845 | + while len(c1) > 0: |
| 846 | + diff = c1.pop(0) - c2.pop(0) |
| 847 | + if diff != 0: |
| 848 | + return diff |
| 849 | + |
| 850 | + return 0 |
| 851 | + |
800 | 852 |
|
801 | 853 | def RawSignatureHash(script, txTo, inIdx, hashtype): |
802 | 854 | """Consensus-correct SignatureHash |
@@ -1008,4 +1060,5 @@ def SignatureHash(script, txTo, inIdx, hashtype): |
1008 | 1060 | 'FindAndDelete', |
1009 | 1061 | 'RawSignatureHash', |
1010 | 1062 | 'SignatureHash', |
| 1063 | + 'IsLowDERSignature', |
1011 | 1064 | ) |
0 commit comments