2013-06-13 20:27:23 +02:00
|
|
|
// Copyright (c) 2013 Conformal Systems LLC.
|
|
|
|
// Use of this source code is governed by an ISC
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package btcec
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/elliptic"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"math/big"
|
|
|
|
)
|
|
|
|
|
2013-10-24 22:13:27 +02:00
|
|
|
// Errors returned by canonicalPadding.
|
|
|
|
var (
|
|
|
|
errNegativeValue = errors.New("value may be interpreted as negative")
|
|
|
|
errExcessivelyPaddedValue = errors.New("value is excessively padded")
|
|
|
|
)
|
|
|
|
|
2013-08-06 19:22:16 +02:00
|
|
|
// Signature is a type representing an ecdsa signature.
|
2013-06-13 20:27:23 +02:00
|
|
|
type Signature struct {
|
|
|
|
R *big.Int
|
|
|
|
S *big.Int
|
|
|
|
}
|
|
|
|
|
2013-12-23 17:56:00 +01:00
|
|
|
// Serialize returns the ECDSA signature in the more strict DER format. Note
|
|
|
|
// that the serialized bytes returned do not include the appended hash type
|
|
|
|
// used in Bitcoin signature scripts.
|
|
|
|
//
|
|
|
|
// encoding/asn1 is broken so we hand roll this output:
|
|
|
|
//
|
|
|
|
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
|
|
|
|
func (sig *Signature) Serialize() []byte {
|
|
|
|
// Ensure the encoded bytes for the r and s values are canonical and
|
|
|
|
// thus suitable for DER encoding.
|
|
|
|
rb := canonicalizeInt(sig.R)
|
|
|
|
sb := canonicalizeInt(sig.S)
|
|
|
|
|
|
|
|
// total length of returned signature is 1 byte for each magic and
|
|
|
|
// length (6 total), plus lengths of r and s
|
|
|
|
length := 6 + len(rb) + len(sb)
|
|
|
|
b := make([]byte, length, length)
|
|
|
|
|
|
|
|
b[0] = 0x30
|
|
|
|
b[1] = byte(length - 2)
|
|
|
|
b[2] = 0x02
|
|
|
|
b[3] = byte(len(rb))
|
|
|
|
offset := copy(b[4:], rb) + 4
|
|
|
|
b[offset] = 0x02
|
|
|
|
b[offset+1] = byte(len(sb))
|
|
|
|
copy(b[offset+2:], sb)
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2013-10-24 22:13:27 +02:00
|
|
|
func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) {
|
2013-06-13 20:27:23 +02:00
|
|
|
// Originally this code used encoding/asn1 in order to parse the
|
|
|
|
// signature, but a number of problems were found with this approach.
|
|
|
|
// Despite the fact that signatures are stored as DER, the difference
|
|
|
|
// between go's idea of a bignum (and that they have sign) doesn't agree
|
|
|
|
// with the openssl one (where they do not). The above is true as of
|
|
|
|
// Go 1.1. In the end it was simpler to rewrite the code to explicitly
|
|
|
|
// understand the format which is this:
|
|
|
|
// 0x30 <length of whole message> <0x02> <length of R> <R> 0x2
|
|
|
|
// <length of S> <S>.
|
|
|
|
|
|
|
|
signature := &Signature{}
|
|
|
|
|
|
|
|
// minimal message is when both numbers are 1 bytes. adding up to:
|
|
|
|
// 0x30 + len + 0x02 + 0x01 + <byte> + 0x2 + 0x01 + <byte>
|
|
|
|
if len(sigStr) < 8 {
|
|
|
|
return nil, errors.New("malformed signature: too short")
|
|
|
|
}
|
|
|
|
// 0x30
|
|
|
|
index := 0
|
|
|
|
if sigStr[index] != 0x30 {
|
|
|
|
return nil, errors.New("malformed signature: no header magic")
|
|
|
|
}
|
|
|
|
index++
|
|
|
|
// length of remaining message
|
|
|
|
siglen := sigStr[index]
|
|
|
|
index++
|
2013-06-24 19:06:01 +02:00
|
|
|
if int(siglen+2) > len(sigStr) {
|
2013-06-17 18:38:16 +02:00
|
|
|
return nil, errors.New("malformed signature: bad length")
|
|
|
|
}
|
2013-06-13 20:27:23 +02:00
|
|
|
// trim the slice we're working on so we only look at what matters.
|
|
|
|
sigStr = sigStr[:siglen+2]
|
|
|
|
|
|
|
|
// 0x02
|
|
|
|
if sigStr[index] != 0x02 {
|
|
|
|
return nil,
|
|
|
|
errors.New("malformed signature: no 1st int marker")
|
|
|
|
}
|
|
|
|
index++
|
|
|
|
|
|
|
|
// Length of signature R.
|
|
|
|
rLen := int(sigStr[index])
|
2013-06-17 17:18:27 +02:00
|
|
|
// must be positive, must be able to fit in another 0x2, <len> <s>
|
|
|
|
// hence the -3. We assume that the length must be at least one byte.
|
|
|
|
index++
|
|
|
|
if rLen <= 0 || rLen > len(sigStr)-index-3 {
|
2013-06-13 20:27:23 +02:00
|
|
|
return nil, errors.New("malformed signature: bogus R length")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Then R itself.
|
2013-10-24 22:13:27 +02:00
|
|
|
rBytes := sigStr[index : index+rLen]
|
|
|
|
if der {
|
|
|
|
switch err := canonicalPadding(rBytes); err {
|
|
|
|
case errNegativeValue:
|
|
|
|
return nil, errors.New("signature R is negative")
|
|
|
|
case errExcessivelyPaddedValue:
|
|
|
|
return nil, errors.New("signature R is excessively padded")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
signature.R = new(big.Int).SetBytes(rBytes)
|
2013-06-13 20:27:23 +02:00
|
|
|
index += rLen
|
2013-06-17 17:18:27 +02:00
|
|
|
// 0x02. length already checked in previous if.
|
2013-06-13 20:27:23 +02:00
|
|
|
if sigStr[index] != 0x02 {
|
|
|
|
return nil, errors.New("malformed signature: no 2nd int marker")
|
|
|
|
}
|
|
|
|
index++
|
|
|
|
|
|
|
|
// Length of signature S.
|
|
|
|
sLen := int(sigStr[index])
|
2013-06-17 17:18:27 +02:00
|
|
|
index++
|
|
|
|
// S should be the rest of the string.
|
|
|
|
if sLen <= 0 || sLen > len(sigStr)-index {
|
2013-06-13 20:27:23 +02:00
|
|
|
return nil, errors.New("malformed signature: bogus S length")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Then S itself.
|
2013-10-24 22:13:27 +02:00
|
|
|
sBytes := sigStr[index : index+sLen]
|
|
|
|
if der {
|
|
|
|
switch err := canonicalPadding(sBytes); err {
|
|
|
|
case errNegativeValue:
|
|
|
|
return nil, errors.New("signature S is negative")
|
|
|
|
case errExcessivelyPaddedValue:
|
|
|
|
return nil, errors.New("signature S is excessively padded")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
signature.S = new(big.Int).SetBytes(sBytes)
|
2013-06-13 20:27:23 +02:00
|
|
|
index += sLen
|
|
|
|
|
|
|
|
// sanity check length parsing
|
|
|
|
if index != len(sigStr) {
|
|
|
|
return nil, fmt.Errorf("malformed signature: bad final length %v != %v",
|
|
|
|
index, len(sigStr))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify also checks this, but we can be more sure that we parsed
|
|
|
|
// correctly if we verify here too.
|
|
|
|
// FWIW the ecdsa spec states that R and S must be | 1, N - 1 |
|
|
|
|
// but crypto/ecdsa only checks for Sign != 0. Mirror that.
|
|
|
|
if signature.R.Sign() != 1 {
|
2013-10-01 00:20:46 +02:00
|
|
|
return nil, errors.New("signature R isn't 1 or more")
|
2013-06-13 20:27:23 +02:00
|
|
|
}
|
|
|
|
if signature.S.Sign() != 1 {
|
2013-10-01 00:20:46 +02:00
|
|
|
return nil, errors.New("signature S isn't 1 or more")
|
2013-06-13 20:27:23 +02:00
|
|
|
}
|
|
|
|
if signature.R.Cmp(curve.Params().N) >= 0 {
|
2013-10-01 00:20:46 +02:00
|
|
|
return nil, errors.New("signature R is >= curve.N")
|
2013-06-13 20:27:23 +02:00
|
|
|
}
|
|
|
|
if signature.S.Cmp(curve.Params().N) >= 0 {
|
2013-10-01 00:20:46 +02:00
|
|
|
return nil, errors.New("signature S is >= curve.N")
|
2013-06-13 20:27:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return signature, nil
|
|
|
|
}
|
2013-10-24 22:13:27 +02:00
|
|
|
|
|
|
|
// ParseSignature parses a signature in BER format for the curve type `curve'
|
|
|
|
// into a Signature type, perfoming some basic sanity checks. If parsing
|
|
|
|
// according to the more strict DER format is needed, use ParseDERSignature.
|
|
|
|
func ParseSignature(sigStr []byte, curve elliptic.Curve) (*Signature, error) {
|
|
|
|
return parseSig(sigStr, curve, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ParseDERSignature parses a signature in DER format for the curve type
|
|
|
|
// `curve` into a Signature type. If parsing according to the less strict
|
|
|
|
// BER format is needed, use ParseSignature.
|
|
|
|
func ParseDERSignature(sigStr []byte, curve elliptic.Curve) (*Signature, error) {
|
|
|
|
return parseSig(sigStr, curve, true)
|
|
|
|
}
|
|
|
|
|
2013-12-23 17:56:00 +01:00
|
|
|
// canonicalizeInt returns the bytes for the passed big integer adjusted as
|
|
|
|
// necessary to ensure that a big-endian encoded integer can't possibly be
|
|
|
|
// misinterpreted as a negative number. This can happen when the most
|
|
|
|
// significant bit is set, so it is padded by a leading zero byte in this case.
|
|
|
|
// Also, the returned bytes will have at least a single byte when the passed
|
|
|
|
// value is 0. This is required for DER encoding.
|
|
|
|
func canonicalizeInt(val *big.Int) []byte {
|
|
|
|
b := val.Bytes()
|
|
|
|
if len(b) == 0 {
|
|
|
|
b = []byte{0x00}
|
|
|
|
}
|
|
|
|
if b[0]&0x80 != 0 {
|
|
|
|
paddedBytes := make([]byte, len(b)+1)
|
|
|
|
copy(paddedBytes[1:], b)
|
|
|
|
b = paddedBytes
|
|
|
|
}
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2013-10-24 22:13:27 +02:00
|
|
|
// canonicalPadding checks whether a big-endian encoded integer could
|
|
|
|
// possibly be misinterpreted as a negative number (even though OpenSSL
|
|
|
|
// treats all numbers as unsigned), or if there is any unnecessary
|
|
|
|
// leading zero padding.
|
|
|
|
func canonicalPadding(b []byte) error {
|
|
|
|
switch {
|
|
|
|
case b[0]&0x80 == 0x80:
|
|
|
|
return errNegativeValue
|
|
|
|
case len(b) > 1 && b[0] == 0x00 && b[1]&0x80 != 0x80:
|
|
|
|
return errExcessivelyPaddedValue
|
|
|
|
default:
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|