bitcoin_script_analyzer/util/
checksig.rs

1pub const SIGHASH_DEFAULT: u8 = 0;
2pub const SIGHASH_ALL: u8 = 1;
3pub const SIGHASH_NONE: u8 = 2;
4pub const SIGHASH_SINGLE: u8 = 3;
5pub const SIGHASH_ANYONECANPAY: u8 = 128;
6
7/// hash types that can appear at the end of a signature (SIGHASH_DEFAULT can't)
8pub const SIG_HASH_TYPES: [u8; 6] = [
9    SIGHASH_ALL,
10    SIGHASH_NONE,
11    SIGHASH_SINGLE,
12    SIGHASH_ALL | SIGHASH_ANYONECANPAY,
13    SIGHASH_NONE | SIGHASH_ANYONECANPAY,
14    SIGHASH_SINGLE | SIGHASH_ANYONECANPAY,
15];
16
17pub enum PubKeyCheckResult {
18    Invalid,
19    Valid { compressed: bool },
20}
21
22pub fn check_pub_key(pub_key: &[u8]) -> PubKeyCheckResult {
23    if pub_key.len() == 33 && (pub_key[0] == 0x02 || pub_key[0] == 0x03) {
24        PubKeyCheckResult::Valid { compressed: true }
25    } else if pub_key.len() == 65 && pub_key[0] == 0x04 {
26        PubKeyCheckResult::Valid { compressed: false }
27    } else {
28        PubKeyCheckResult::Invalid
29    }
30}
31
32// The following function was copied from the Bitcoin Core source code, src/script/interpreter (lines 97-170) at b92d609fb25637ccda000e182da854d4b762eee9
33// Edited for use in this software
34
35// Orignal Bitcoin Core copyright header:
36// Copyright (c) 2009-2010 Satoshi Nakamoto
37// Copyright (c) 2009-2022 The Bitcoin Core developers
38// Distributed under the MIT software license, see the accompanying
39// file COPYING or http://www.opensource.org/licenses/mit-license.php.
40
41/// A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype>
42/// Where R and S are not negative (their first byte has its highest bit not set), and not
43/// excessively padded (do not start with a 0 byte, unless an otherwise negative number follows,
44/// in which case a single 0 byte is necessary and even required).
45///
46/// See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
47///
48/// This function is consensus-critical since BIP66.
49pub fn is_valid_signature_encoding(sig: &[u8]) -> bool {
50    // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]
51    // * total-length: 1-byte length descriptor of everything that follows,
52    //   excluding the sighash byte.
53    // * R-length: 1-byte length descriptor of the R value that follows.
54    // * R: arbitrary-length big-endian encoded R value. It must use the shortest
55    //   possible encoding for a positive integer (which means no null bytes at
56    //   the start, except a single one when the next byte has its highest bit set).
57    // * S-length: 1-byte length descriptor of the S value that follows.
58    // * S: arbitrary-length big-endian encoded S value. The same rules apply.
59    // * sighash: 1-byte value indicating what data is hashed (not part of the DER
60    //   signature)
61
62    // Minimum and maximum size constraints.
63    if sig.len() < 9 {
64        return false;
65    }
66    if sig.len() > 73 {
67        return false;
68    }
69
70    // A signature is of type 0x30 (compound).
71    if sig[0] != 0x30 {
72        return false;
73    }
74
75    // Make sure the length covers the entire signature.
76    if sig[1] != sig.len() as u8 - 3 {
77        return false;
78    }
79
80    // Extract the length of the R element.
81    let len_r = sig[3] as usize;
82
83    // Make sure the length of the S element is still inside the signature.
84    if 5 + len_r >= sig.len() {
85        return false;
86    }
87
88    // Extract the length of the S element.
89    let len_s = sig[5 + len_r] as usize;
90
91    // Verify that the length of the signature matches the sum of the length
92    // of the elements.
93    if len_r + len_s + 7 != sig.len() {
94        return false;
95    }
96
97    // Check whether the R element is an integer.
98    if sig[2] != 0x02 {
99        return false;
100    }
101
102    // Zero-length integers are not allowed for R.
103    if len_r == 0 {
104        return false;
105    }
106
107    // Negative numbers are not allowed for R.
108    if (sig[4] & 0x80) != 0 {
109        return false;
110    }
111
112    // Null bytes at the start of R are not allowed, unless R would
113    // otherwise be interpreted as a negative number.
114    if len_r > 1 && sig[4] == 0x00 && (sig[5] & 0x80) == 0 {
115        return false;
116    }
117
118    // Check whether the S element is an integer.
119    if sig[len_r + 4] != 0x02 {
120        return false;
121    }
122
123    // Zero-length integers are not allowed for S.
124    if len_s == 0 {
125        return false;
126    }
127
128    // Negative numbers are not allowed for S.
129    if (sig[len_r + 6] & 0x80) != 0 {
130        return false;
131    }
132
133    // Null bytes at the start of S are not allowed, unless S would otherwise be
134    // interpreted as a negative number.
135    if len_s > 1 && sig[len_r + 6] == 0x00 && (sig[len_r + 7] & 0x80) == 0 {
136        return false;
137    }
138
139    true
140}