lnwire: add new Sig type to handle conversion to/from btcec.Signature

In this commit, we add a new signature type. We’ll use this type to
avoid fully decoding a signature on the wire into a btcec.Signature.
This type is only really needed when we need to do signature
validation, as a result, always encoding it is a waste. Several helper
methods have been added to the new struct in order to ensure that we
can use it in the existing codebase without substantial issues.
This commit is contained in:
Olaoluwa Osuntokun 2018-01-30 19:40:30 -08:00
parent 1afadf4822
commit 0d7b8be11b
No known key found for this signature in database
GPG Key ID: 964EA263DD637C21

@ -6,12 +6,16 @@ import (
"github.com/roasbeef/btcd/btcec"
)
// SerializeSigToWire serializes a *Signature to [64]byte in the format
// specified by the Lightning RFC.
func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
// Sig is a fixed-sized ECDSA signature. Unlike Bitcoin, we use fixed sized
// signatures on the wire, instead of DER encoded signatures. This type
// provides several methods to convert to/from a regular Bitcoin DER encoded
// signature (raw bytes and *btcec.Signature).
type Sig [64]byte
// Serialize the signature with all the checks that entails.
sig := e.Serialize()
// NewSigFromRawSignature returns a Sig from a Bitcoin raw signature encoded in
// the cannonical DER encoding.
func NewSigFromRawSignature(sig []byte) (Sig, error) {
var b Sig
// Extract lengths of R and S. The DER representation is laid out as
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
@ -23,14 +27,14 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
sLen := sig[5+rLen]
// Check to make sure R and S can both fit into their intended buffers.
// We check S first because these code blocks decrement sLen and
// rLen in the case of a 33-byte 0-padded integer returned from
// Serialize() and rLen is used in calculating array indices for
// S. We can track this with additional variables, but it's more
// efficient to just check S first.
// We check S first because these code blocks decrement sLen and rLen
// in the case of a 33-byte 0-padded integer returned from Serialize()
// and rLen is used in calculating array indices for S. We can track
// this with additional variables, but it's more efficient to just
// check S first.
if sLen > 32 {
if (sLen > 33) || (sig[6+rLen] != 0x00) {
return fmt.Errorf("S is over 32 bytes long " +
return b, fmt.Errorf("S is over 32 bytes long " +
"without padding")
}
sLen--
@ -42,7 +46,7 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
// Do the same for R as we did for S
if rLen > 32 {
if (rLen > 33) || (sig[4] != 0x00) {
return fmt.Errorf("R is over 32 bytes long " +
return b, fmt.Errorf("R is over 32 bytes long " +
"without padding")
}
rLen--
@ -50,13 +54,33 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
} else {
copy(b[32-rLen:], sig[4:4+rLen])
}
return nil
return b, nil
}
// DeserializeSigFromWire deserializes a *Signature from [64]byte in the format
// specified by the Lightning RFC.
func DeserializeSigFromWire(e **btcec.Signature, b [64]byte) error {
// NewSigFromSignature creates a new signature as used on the wire, from an
// existing btcec.Signature.
func NewSigFromSignature(e *btcec.Signature) (Sig, error) {
// Serialize the signature with all the checks that entails.
return NewSigFromRawSignature(e.Serialize())
}
// ToSignature converts the fixed-sized signature to a btcec.Signature objects
// which can be used for signature validation checks.
func (b *Sig) ToSignature() (*btcec.Signature, error) {
// Parse the signature with strict checks.
sigBytes := b.ToSignatureBytes()
sig, err := btcec.ParseDERSignature(sigBytes, btcec.S256())
if err != nil {
return nil, err
}
return sig, nil
}
// ToSignatureBytes serializes the target fixed-sized signature into the raw
// bytes of a DER encoding.
func (b *Sig) ToSignatureBytes() []byte {
// Extract canonically-padded bigint representations from buffer
r := extractCanonicalPadding(b[0:32])
s := extractCanonicalPadding(b[32:64])
@ -75,13 +99,7 @@ func DeserializeSigFromWire(e **btcec.Signature, b [64]byte) error {
copy(sigBytes[4:], r) // Copy R
copy(sigBytes[rLen+6:], s) // Copy S
// Parse the signature with strict checks.
sig, err := btcec.ParseDERSignature(sigBytes, btcec.S256())
if err != nil {
return err
}
*e = sig
return nil
return sigBytes
}
// extractCanonicalPadding is a utility function to extract the canonical