Bitcoin ABC 0.30.5
P2P Digital Currency
sigencoding.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2016 The Bitcoin Core developers
3// Copyright (c) 2017-2019 The Bitcoin developers
4// Distributed under the MIT software license, see the accompanying
5// file COPYING or http://www.opensource.org/licenses/mit-license.php.
6
8
9#include <pubkey.h>
10#include <script/script_flags.h>
11
12#include <boost/range/adaptor/sliced.hpp>
13
14typedef boost::sliced_range<const valtype> slicedvaltype;
15
28 // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
29 // * total-length: 1-byte length descriptor of everything that follows,
30 // excluding the sighash byte.
31 // * R-length: 1-byte length descriptor of the R value that follows.
32 // * R: arbitrary-length big-endian encoded R value. It must use the
33 // shortest possible encoding for a positive integer (which means no null
34 // bytes at the start, except a single one when the next byte has its
35 // highest bit set).
36 // * S-length: 1-byte length descriptor of the S value that follows.
37 // * S: arbitrary-length big-endian encoded S value. The same rules apply.
38
39 // Minimum and maximum size constraints.
40 if (sig.size() < 8 || sig.size() > 72) {
41 return false;
42 }
43
44 //
45 // Check that the signature is a compound structure of proper size.
46 //
47
48 // A signature is of type 0x30 (compound).
49 if (sig[0] != 0x30) {
50 return false;
51 }
52
53 // Make sure the length covers the entire signature.
54 // Remove:
55 // * 1 byte for the coupound type.
56 // * 1 byte for the length of the signature.
57 if (sig[1] != sig.size() - 2) {
58 return false;
59 }
60
61 //
62 // Check that R is an positive integer of sensible size.
63 //
64
65 // Check whether the R element is an integer.
66 if (sig[2] != 0x02) {
67 return false;
68 }
69
70 // Extract the length of the R element.
71 const uint32_t lenR = sig[3];
72
73 // Zero-length integers are not allowed for R.
74 if (lenR == 0) {
75 return false;
76 }
77
78 // Negative numbers are not allowed for R.
79 if (sig[4] & 0x80) {
80 return false;
81 }
82
83 // Make sure the length of the R element is consistent with the signature
84 // size.
85 // Remove:
86 // * 1 byte for the coumpound type.
87 // * 1 byte for the length of the signature.
88 // * 2 bytes for the integer type of R and S.
89 // * 2 bytes for the size of R and S.
90 // * 1 byte for S itself.
91 if (lenR > (sig.size() - 7)) {
92 return false;
93 }
94
95 // Null bytes at the start of R are not allowed, unless R would otherwise be
96 // interpreted as a negative number.
97 //
98 // /!\ This check can only be performed after we checked that lenR is
99 // consistent with the size of the signature or we risk to access out of
100 // bound elements.
101 if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) {
102 return false;
103 }
104
105 //
106 // Check that S is an positive integer of sensible size.
107 //
108
109 // S's definition starts after R's definition:
110 // * 1 byte for the coumpound type.
111 // * 1 byte for the length of the signature.
112 // * 1 byte for the size of R.
113 // * lenR bytes for R itself.
114 // * 1 byte to get to S.
115 const uint32_t startS = lenR + 4;
116
117 // Check whether the S element is an integer.
118 if (sig[startS] != 0x02) {
119 return false;
120 }
121
122 // Extract the length of the S element.
123 const uint32_t lenS = sig[startS + 1];
124
125 // Zero-length integers are not allowed for S.
126 if (lenS == 0) {
127 return false;
128 }
129
130 // Negative numbers are not allowed for S.
131 if (sig[startS + 2] & 0x80) {
132 return false;
133 }
134
135 // Verify that the length of S is consistent with the size of the signature
136 // including metadatas:
137 // * 1 byte for the integer type of S.
138 // * 1 byte for the size of S.
139 if (size_t(startS + lenS + 2) != sig.size()) {
140 return false;
141 }
142
143 // Null bytes at the start of S are not allowed, unless S would otherwise be
144 // interpreted as a negative number.
145 //
146 // /!\ This check can only be performed after we checked that lenR and lenS
147 // are consistent with the size of the signature or we risk to access
148 // out of bound elements.
149 if (lenS > 1 && (sig[startS + 2] == 0x00) && !(sig[startS + 3] & 0x80)) {
150 return false;
151 }
152
153 return true;
154}
155
156static bool IsSchnorrSig(const slicedvaltype &sig) {
157 return sig.size() == 64;
158}
159
161 uint32_t flags,
162 ScriptError *serror) {
163 if (IsSchnorrSig(sig)) {
164 // In an ECDSA-only context, 64-byte signatures are forbidden.
165 return set_error(serror, ScriptError::SIG_BADLENGTH);
166 }
167 // https://bitcoin.stackexchange.com/a/12556:
171 return set_error(serror, ScriptError::SIG_DER);
172 }
173 // If the S value is above the order of the curve divided by two, its
174 // complement modulo the order could have been used instead, which is
175 // one byte shorter when encoded correctly.
177 return set_error(serror, ScriptError::SIG_HIGH_S);
178 }
179
180 return true;
181}
182
184 uint32_t flags,
185 ScriptError *serror) {
186 if (IsSchnorrSig(sig)) {
187 return true;
188 }
189 return set_error(serror, ScriptError::SIG_NONSCHNORR);
190}
191
193 ScriptError *serror) {
194 if (IsSchnorrSig(sig)) {
195 // In a generic-signature context, 64-byte signatures are interpreted
196 // as Schnorr signatures (always correctly encoded).
197 return true;
198 }
200}
201
202bool CheckDataSignatureEncoding(const valtype &vchSig, uint32_t flags,
203 ScriptError *serror) {
204 // Empty signature. Not strictly DER encoded, but allowed to provide a
205 // compact way to provide an invalid signature for use with CHECK(MULTI)SIG
206 if (vchSig.size() == 0) {
207 return true;
208 }
209
211 vchSig | boost::adaptors::sliced(0, vchSig.size()), flags, serror);
212}
213
214static bool CheckSighashEncoding(const valtype &vchSig, uint32_t flags,
215 ScriptError *serror) {
217 if (!GetHashType(vchSig).isDefined()) {
218 return set_error(serror, ScriptError::SIG_HASHTYPE);
219 }
220
221 bool usesForkId = GetHashType(vchSig).hasForkId();
222 bool forkIdEnabled = flags & SCRIPT_ENABLE_SIGHASH_FORKID;
223 if (!forkIdEnabled && usesForkId) {
224 return set_error(serror, ScriptError::ILLEGAL_FORKID);
225 }
226
227 if (forkIdEnabled && !usesForkId) {
228 return set_error(serror, ScriptError::MUST_USE_FORKID);
229 }
230 }
231
232 return true;
233}
234
235template <typename F>
237 uint32_t flags,
238 ScriptError *serror, F fun) {
239 // Empty signature. Not strictly DER encoded, but allowed to provide a
240 // compact way to provide an invalid signature for use with CHECK(MULTI)SIG
241 if (vchSig.size() == 0) {
242 return true;
243 }
244
245 if (!fun(vchSig | boost::adaptors::sliced(0, vchSig.size() - 1), flags,
246 serror)) {
247 // serror is set
248 return false;
249 }
250
251 return CheckSighashEncoding(vchSig, flags, serror);
252}
253
255 ScriptError *serror) {
257 vchSig, flags, serror,
258 [](const slicedvaltype &templateSig, uint32_t templateFlags,
259 ScriptError *templateSerror) {
260 return CheckRawSignatureEncoding(templateSig, templateFlags,
261 templateSerror);
262 });
263}
264
266 uint32_t flags,
267 ScriptError *serror) {
269 vchSig, flags, serror,
270 [](const slicedvaltype &templateSig, uint32_t templateFlags,
271 ScriptError *templateSerror) {
272 return CheckRawECDSASignatureEncoding(templateSig, templateFlags,
273 templateSerror);
274 });
275}
276
278 uint32_t flags,
279 ScriptError *serror) {
281 vchSig, flags, serror,
282 [](const slicedvaltype &templateSig, uint32_t templateFlags,
283 ScriptError *templateSerror) {
284 return CheckRawSchnorrSignatureEncoding(templateSig, templateFlags,
285 templateSerror);
286 });
287}
288
289static bool IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) {
290 switch (vchPubKey.size()) {
292 // Compressed public key: must start with 0x02 or 0x03.
293 return vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03;
294
295 case CPubKey::SIZE:
296 // Non-compressed public key: must start with 0x04.
297 return vchPubKey[0] == 0x04;
298
299 default:
300 // Non-canonical public key: invalid size.
301 return false;
302 }
303}
304
305bool CheckPubKeyEncoding(const valtype &vchPubKey, uint32_t flags,
306 ScriptError *serror) {
309 return set_error(serror, ScriptError::PUBKEYTYPE);
310 }
311 return true;
312}
int flags
Definition: bitcoin-tx.cpp:541
static constexpr unsigned int COMPRESSED_SIZE
Definition: pubkey.h:37
static constexpr unsigned int SIZE
secp256k1:
Definition: pubkey.h:36
static bool CheckLowS(const boost::sliced_range< const std::vector< uint8_t > > &vchSig)
Check whether a DER-serialized ECDSA signature is normalized (lower-S).
Definition: pubkey.cpp:341
SchnorrSig sig
Definition: processor.cpp:498
ScriptError
Definition: script_error.h:11
@ SCRIPT_VERIFY_LOW_S
Definition: script_flags.h:31
@ SCRIPT_VERIFY_STRICTENC
Definition: script_flags.h:22
@ SCRIPT_VERIFY_DERSIG
Definition: script_flags.h:26
@ SCRIPT_ENABLE_SIGHASH_FORKID
Definition: script_flags.h:85
bool CheckTransactionSchnorrSignatureEncoding(const valtype &vchSig, uint32_t flags, ScriptError *serror)
Check that the signature provided to authentify a transaction is properly encoded Schnorr signature (...
bool CheckDataSignatureEncoding(const valtype &vchSig, uint32_t flags, ScriptError *serror)
Check that the signature provided on some data is properly encoded.
static bool CheckTransactionSignatureEncodingImpl(const valtype &vchSig, uint32_t flags, ScriptError *serror, F fun)
static bool CheckRawSignatureEncoding(const slicedvaltype &sig, uint32_t flags, ScriptError *serror)
bool CheckTransactionECDSASignatureEncoding(const valtype &vchSig, uint32_t flags, ScriptError *serror)
Check that the signature provided to authentify a transaction is properly encoded ECDSA signature.
static bool IsValidDERSignatureEncoding(const slicedvaltype &sig)
A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> , where R and S are n...
Definition: sigencoding.cpp:27
static bool CheckRawECDSASignatureEncoding(const slicedvaltype &sig, uint32_t flags, ScriptError *serror)
static bool IsCompressedOrUncompressedPubKey(const valtype &vchPubKey)
static bool IsSchnorrSig(const slicedvaltype &sig)
bool CheckTransactionSignatureEncoding(const valtype &vchSig, uint32_t flags, ScriptError *serror)
Check that the signature provided to authentify a transaction is properly encoded.
static bool CheckSighashEncoding(const valtype &vchSig, uint32_t flags, ScriptError *serror)
bool CheckPubKeyEncoding(const valtype &vchPubKey, uint32_t flags, ScriptError *serror)
Check that a public key is encoded properly.
boost::sliced_range< const valtype > slicedvaltype
Definition: sigencoding.cpp:14
static bool CheckRawSchnorrSignatureEncoding(const slicedvaltype &sig, uint32_t flags, ScriptError *serror)
std::vector< uint8_t > valtype
Definition: sigencoding.h:16