Add method to push an ECDSA sig + sighash type byte on a witness#989
Conversation
We do this all over the place in rust-lightning, and its probably the most common thing to do with a `Witness` so I figured I'd upstream the util method to do this. It also avoids an allocation compared to the naive approach of `SerializedSignature.to_vec()` with two pushes, which is nice.
| sig[..signature.len()].copy_from_slice(&signature); | ||
| sig[signature.len()] = hash_type as u8; | ||
| self.push(&sig[..signature.len() + 1]); | ||
| } |
There was a problem hiding this comment.
Do we want to protect against a malicious caller? signature.len() returns a value that could have previously been set with signature.set_len(). A malicious call could cause this function to panic. Not sure if that matters?
One solution might be:
pub fn push_bitcoin_signature(&mut self, signature: &ecdsa::SerializedSignature, hash_type: EcdsaSighashType) {
// Note that a maximal length ECDSA signature is 72 bytes, plus the sighash type makes 73
let mut sig = [0; 73];
let len = signature.len();
if len > 72 {
// This can happen if a malicious caller has previously called
// signature.set_len() with a length intentionally too big.
return;
}
sig[..len].copy_from_slice(&signature);
sig[len] = hash_type as u8;
self.push(&sig[..=len]);
}
There was a problem hiding this comment.
Perhaps we should just add a check to set_len instead?
There was a problem hiding this comment.
I'm not sure what is the security model you are thinking of. If the attacker controls any code in the current process, aren't all bets off? they can just read/write random memory locations, including keys and such.
There was a problem hiding this comment.
I don't see a set_len() anywhere in https://docs.rs/secp256k1/latest/secp256k1/ecdsa/struct.SerializedSignature.html? What am I missing?
There was a problem hiding this comment.
It also looks to me like SerializedSignature cannot be coerced into having a longer length. If it were, I'd advocate for a comment describing the panic, but I'm ok with it existing.
There was a problem hiding this comment.
I'm not sure what is the security model you are thinking of
Sorry, I misspoke I should have said 'defensive programming' instead of 'malicious caller', my bad.
I don't see a set_len() anywhere
Its pub (crate) so doesn't show up in those docs
It also looks to me like SerializedSignature cannot be coerced into having a longer length.
Thanks for taking a look.
|
|
||
| /// Pushes a DER-encoded ECDSA signature with a signature hash type as a new element on the | ||
| /// witness, requires an allocation. | ||
| pub fn push_bitcoin_signature(&mut self, signature: &ecdsa::SerializedSignature, hash_type: EcdsaSighashType) { |
There was a problem hiding this comment.
don't we want this for Schnorr too?
or maybe a generic one:
pub fn push_with_hash_type<T: AsRef<[u8]>>(&mut self, new_element: T, hash_type: u8) {There was a problem hiding this comment.
I wasn't sure exactly the format for schnorr so didn't bother. I'd prefer to keep the SerializedSignature here as it makes the API more explicit, but would be happy to add one for schnorr as well. Note that making it generic would be a lot more involved as we wouldn't have a maximum length of the new_element hard-coded.
There was a problem hiding this comment.
+1 to having a totally separate method for schnorr (doesn't need to be in this PR)
Heh I first checked if secp had a constant for this I could use but it also uses 72 so I just stuck with it. |
…+ sighash type byte on a witness 0ab5eea Add method to push an ECDSA sig + sighash type byte on a witness (Matt Corallo) Pull request description: We do this all over the place in rust-lightning, and its probably the most common thing to do with a `Witness` so I figured I'd upstream the util method to do this. It also avoids an allocation compared to the naive approach of `SerializedSignature.to_vec()` with two pushes, which is nice. ACKs for top commit: apoelstra: ACK 0ab5eea tcharding: ACK 0ab5eea dunxen: ACK 0ab5eea Tree-SHA512: d4042eb3f2bc7e6beecd2c17eaeef1fdb7d096b8889a3709924734739557031f338525b685d32ac0dc26404afefd4f2d48defd1753ea8935e54e3a82987feb8c
We do this all over the place in rust-lightning, and its probably
the most common thing to do with a
Witnessso I figured I'dupstream the util method to do this. It also avoids an allocation
compared to the naive approach of
SerializedSignature.to_vec()with two pushes, which is nice.