github.com/decred/dcrlnd@v0.7.6/channeldb/migration/lnwire21/signature.go (about) 1 package lnwire 2 3 import ( 4 "fmt" 5 6 "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" 7 "github.com/decred/dcrlnd/input" 8 ) 9 10 // Sig is a fixed-sized ECDSA signature. Unlike Bitcoin, we use fixed sized 11 // signatures on the wire, instead of DER encoded signatures. This type 12 // provides several methods to convert to/from a regular Bitcoin DER encoded 13 // signature (raw bytes and *ecdsa.Signature). 14 type Sig [64]byte 15 16 // NewSigFromRawSignature returns a Sig from a Bitcoin raw signature encoded in 17 // the canonical DER encoding. 18 func NewSigFromRawSignature(sig []byte) (Sig, error) { 19 var b Sig 20 21 if len(sig) == 0 { 22 return b, fmt.Errorf("cannot decode empty signature") 23 } 24 25 // Extract lengths of R and S. The DER representation is laid out as 26 // 0x30 <length> 0x02 <length r> r 0x02 <length s> s 27 // which means the length of R is the 4th byte and the length of S 28 // is the second byte after R ends. 0x02 signifies a length-prefixed, 29 // zero-padded, big-endian bigint. 0x30 signifies a DER signature. See 30 // the Serialize() method for ecdsa.Signature for details. 31 rLen := sig[3] 32 sLen := sig[5+rLen] 33 34 // Check to make sure R and S can both fit into their intended buffers. 35 // We check S first because these code blocks decrement sLen and rLen 36 // in the case of a 33-byte 0-padded integer returned from Serialize() 37 // and rLen is used in calculating array indices for S. We can track 38 // this with additional variables, but it's more efficient to just 39 // check S first. 40 if sLen > 32 { 41 if (sLen > 33) || (sig[6+rLen] != 0x00) { 42 return b, fmt.Errorf("S is over 32 bytes long " + 43 "without padding") 44 } 45 sLen-- 46 copy(b[64-sLen:], sig[7+rLen:]) 47 } else { 48 copy(b[64-sLen:], sig[6+rLen:]) 49 } 50 51 // Do the same for R as we did for S 52 if rLen > 32 { 53 if (rLen > 33) || (sig[4] != 0x00) { 54 return b, fmt.Errorf("R is over 32 bytes long " + 55 "without padding") 56 } 57 rLen-- 58 copy(b[32-rLen:], sig[5:5+rLen]) 59 } else { 60 copy(b[32-rLen:], sig[4:4+rLen]) 61 } 62 63 return b, nil 64 } 65 66 // NewSigFromSignature creates a new signature as used on the wire, from an 67 // existing ecdsa.Signature. 68 func NewSigFromSignature(e input.Signature) (Sig, error) { 69 if e == nil { 70 return Sig{}, fmt.Errorf("cannot decode empty signature") 71 } 72 73 // Serialize the signature with all the checks that entails. 74 return NewSigFromRawSignature(e.Serialize()) 75 } 76 77 // ToSignature converts the fixed-sized signature to a ecdsa.Signature objects 78 // which can be used for signature validation checks. 79 func (b *Sig) ToSignature() (*ecdsa.Signature, error) { 80 // Parse the signature with strict checks. 81 sigBytes := b.ToSignatureBytes() 82 sig, err := ecdsa.ParseDERSignature(sigBytes) 83 if err != nil { 84 return nil, err 85 } 86 87 return sig, nil 88 } 89 90 // ToSignatureBytes serializes the target fixed-sized signature into the raw 91 // bytes of a DER encoding. 92 func (b *Sig) ToSignatureBytes() []byte { 93 // Extract canonically-padded bigint representations from buffer 94 r := extractCanonicalPadding(b[0:32]) 95 s := extractCanonicalPadding(b[32:64]) 96 rLen := uint8(len(r)) 97 sLen := uint8(len(s)) 98 99 // Create a canonical serialized signature. DER format is: 100 // 0x30 <length> 0x02 <length r> r 0x02 <length s> s 101 sigBytes := make([]byte, 6+rLen+sLen) 102 sigBytes[0] = 0x30 // DER signature magic value 103 sigBytes[1] = 4 + rLen + sLen // Length of rest of signature 104 sigBytes[2] = 0x02 // Big integer magic value 105 sigBytes[3] = rLen // Length of R 106 sigBytes[rLen+4] = 0x02 // Big integer magic value 107 sigBytes[rLen+5] = sLen // Length of S 108 copy(sigBytes[4:], r) // Copy R 109 copy(sigBytes[rLen+6:], s) // Copy S 110 111 return sigBytes 112 } 113 114 // extractCanonicalPadding is a utility function to extract the canonical 115 // padding of a big-endian integer from the wire encoding (a 0-padded 116 // big-endian integer) such that it passes secp256k1.canonicalPadding test. 117 func extractCanonicalPadding(b []byte) []byte { 118 for i := 0; i < len(b); i++ { 119 // Found first non-zero byte. 120 if b[i] > 0 { 121 // If the MSB is set, we need zero padding. 122 if b[i]&0x80 == 0x80 { 123 return append([]byte{0x00}, b[i:]...) 124 } 125 return b[i:] 126 } 127 } 128 return []byte{0x00} 129 }