github.com/lbryio/lbcd@v0.22.119/btcec/signature_test.go (about)

     1  // Copyright (c) 2013-2017 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package btcec
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/rand"
    10  	"crypto/sha256"
    11  	"encoding/hex"
    12  	"fmt"
    13  	"math/big"
    14  	"reflect"
    15  	"testing"
    16  )
    17  
    18  type signatureTest struct {
    19  	name    string
    20  	sig     []byte
    21  	der     bool
    22  	isValid bool
    23  }
    24  
    25  // decodeHex decodes the passed hex string and returns the resulting bytes.  It
    26  // panics if an error occurs.  This is only used in the tests as a helper since
    27  // the only way it can fail is if there is an error in the test source code.
    28  func decodeHex(hexStr string) []byte {
    29  	b, err := hex.DecodeString(hexStr)
    30  	if err != nil {
    31  		panic("invalid hex string in test source: err " + err.Error() +
    32  			", hex: " + hexStr)
    33  	}
    34  
    35  	return b
    36  }
    37  
    38  var signatureTests = []signatureTest{
    39  	// signatures from bitcoin blockchain tx
    40  	// 0437cd7f8525ceed2324359c2d0ba26006d92d85
    41  	{
    42  		name: "valid signature.",
    43  		sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
    44  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
    45  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
    46  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
    47  			0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
    48  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
    49  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
    50  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
    51  		},
    52  		der:     true,
    53  		isValid: true,
    54  	},
    55  	{
    56  		name:    "empty.",
    57  		sig:     []byte{},
    58  		isValid: false,
    59  	},
    60  	{
    61  		name: "bad magic.",
    62  		sig: []byte{0x31, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
    63  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
    64  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
    65  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
    66  			0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
    67  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
    68  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
    69  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
    70  		},
    71  		der:     true,
    72  		isValid: false,
    73  	},
    74  	{
    75  		name: "bad 1st int marker magic.",
    76  		sig: []byte{0x30, 0x44, 0x03, 0x20, 0x4e, 0x45, 0xe1, 0x69,
    77  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
    78  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
    79  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
    80  			0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
    81  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
    82  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
    83  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
    84  		},
    85  		der:     true,
    86  		isValid: false,
    87  	},
    88  	{
    89  		name: "bad 2nd int marker.",
    90  		sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
    91  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
    92  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
    93  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
    94  			0x41, 0x03, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
    95  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
    96  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
    97  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
    98  		},
    99  		der:     true,
   100  		isValid: false,
   101  	},
   102  	{
   103  		name: "short len",
   104  		sig: []byte{0x30, 0x43, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   105  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   106  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   107  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   108  			0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
   109  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
   110  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
   111  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
   112  		},
   113  		der:     true,
   114  		isValid: false,
   115  	},
   116  	{
   117  		name:    "invalid message length",
   118  		sig:     []byte{0x30, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00},
   119  		der:     false,
   120  		isValid: false,
   121  	},
   122  	{
   123  		name: "long len",
   124  		sig: []byte{0x30, 0x45, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   125  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   126  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   127  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   128  			0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
   129  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
   130  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
   131  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
   132  		},
   133  		der:     true,
   134  		isValid: false,
   135  	},
   136  	{
   137  		name: "long X",
   138  		sig: []byte{0x30, 0x44, 0x02, 0x42, 0x4e, 0x45, 0xe1, 0x69,
   139  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   140  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   141  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   142  			0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
   143  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
   144  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
   145  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
   146  		},
   147  		der:     true,
   148  		isValid: false,
   149  	},
   150  	{
   151  		name: "long Y",
   152  		sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   153  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   154  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   155  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   156  			0x41, 0x02, 0x21, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
   157  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
   158  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
   159  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
   160  		},
   161  		der:     true,
   162  		isValid: false,
   163  	},
   164  	{
   165  		name: "short Y",
   166  		sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   167  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   168  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   169  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   170  			0x41, 0x02, 0x19, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
   171  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
   172  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
   173  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
   174  		},
   175  		der:     true,
   176  		isValid: false,
   177  	},
   178  	{
   179  		name: "trailing crap.",
   180  		sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   181  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   182  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   183  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   184  			0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
   185  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
   186  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
   187  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01,
   188  		},
   189  		der: true,
   190  
   191  		// This test is now passing (used to be failing) because there
   192  		// are signatures in the blockchain that have trailing zero
   193  		// bytes before the hashtype. So ParseSignature was fixed to
   194  		// permit buffers with trailing nonsense after the actual
   195  		// signature.
   196  		isValid: true,
   197  	},
   198  	{
   199  		name: "X == N ",
   200  		sig: []byte{0x30, 0x44, 0x02, 0x20, 0xFF, 0xFF, 0xFF, 0xFF,
   201  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   202  			0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48,
   203  			0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41,
   204  			0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
   205  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
   206  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
   207  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
   208  		},
   209  		der:     true,
   210  		isValid: false,
   211  	},
   212  	{
   213  		name: "X == N ",
   214  		sig: []byte{0x30, 0x44, 0x02, 0x20, 0xFF, 0xFF, 0xFF, 0xFF,
   215  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   216  			0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48,
   217  			0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41,
   218  			0x42, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
   219  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
   220  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
   221  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
   222  		},
   223  		der:     false,
   224  		isValid: false,
   225  	},
   226  	{
   227  		name: "Y == N",
   228  		sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   229  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   230  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   231  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   232  			0x41, 0x02, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   233  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   234  			0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
   235  			0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41,
   236  		},
   237  		der:     true,
   238  		isValid: false,
   239  	},
   240  	{
   241  		name: "Y > N",
   242  		sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   243  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   244  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   245  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   246  			0x41, 0x02, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   247  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   248  			0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
   249  			0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x42,
   250  		},
   251  		der:     false,
   252  		isValid: false,
   253  	},
   254  	{
   255  		name: "0 len X.",
   256  		sig: []byte{0x30, 0x24, 0x02, 0x00, 0x02, 0x20, 0x18, 0x15,
   257  			0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60, 0xa4,
   258  			0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, 0xc5, 0x6c,
   259  			0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, 0x21, 0xa8, 0x76,
   260  			0x8d, 0x1d, 0x09,
   261  		},
   262  		der:     true,
   263  		isValid: false,
   264  	},
   265  	{
   266  		name: "0 len Y.",
   267  		sig: []byte{0x30, 0x24, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   268  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   269  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   270  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   271  			0x41, 0x02, 0x00,
   272  		},
   273  		der:     true,
   274  		isValid: false,
   275  	},
   276  	{
   277  		name: "extra R padding.",
   278  		sig: []byte{0x30, 0x45, 0x02, 0x21, 0x00, 0x4e, 0x45, 0xe1, 0x69,
   279  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   280  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   281  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   282  			0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
   283  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
   284  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
   285  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
   286  		},
   287  		der:     true,
   288  		isValid: false,
   289  	},
   290  	{
   291  		name: "extra S padding.",
   292  		sig: []byte{0x30, 0x45, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   293  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   294  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   295  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   296  			0x41, 0x02, 0x21, 0x00, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
   297  			0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
   298  			0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
   299  			0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
   300  		},
   301  		der:     true,
   302  		isValid: false,
   303  	},
   304  	// Standard checks (in BER format, without checking for 'canonical' DER
   305  	// signatures) don't test for negative numbers here because there isn't
   306  	// a way that is the same between openssl and go that will mark a number
   307  	// as negative. The Go ASN.1 parser marks numbers as negative when
   308  	// openssl does not (it doesn't handle negative numbers that I can tell
   309  	// at all. When not parsing DER signatures, which is done by by bitcoind
   310  	// when accepting transactions into its mempool, we otherwise only check
   311  	// for the coordinates being zero.
   312  	{
   313  		name: "X == 0",
   314  		sig: []byte{0x30, 0x25, 0x02, 0x01, 0x00, 0x02, 0x20, 0x18,
   315  			0x15, 0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60,
   316  			0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, 0xc5,
   317  			0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, 0x21, 0xa8,
   318  			0x76, 0x8d, 0x1d, 0x09,
   319  		},
   320  		der:     false,
   321  		isValid: false,
   322  	},
   323  	{
   324  		name: "Y == 0.",
   325  		sig: []byte{0x30, 0x25, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   326  			0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
   327  			0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
   328  			0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
   329  			0x41, 0x02, 0x01, 0x00,
   330  		},
   331  		der:     false,
   332  		isValid: false,
   333  	},
   334  }
   335  
   336  func TestSignatures(t *testing.T) {
   337  	for _, test := range signatureTests {
   338  		var err error
   339  		if test.der {
   340  			_, err = ParseDERSignature(test.sig, S256())
   341  		} else {
   342  			_, err = ParseSignature(test.sig, S256())
   343  		}
   344  		if err != nil {
   345  			if test.isValid {
   346  				t.Errorf("%s signature failed when shouldn't %v",
   347  					test.name, err)
   348  			} /* else {
   349  				t.Errorf("%s got error %v", test.name, err)
   350  			} */
   351  			continue
   352  		}
   353  		if !test.isValid {
   354  			t.Errorf("%s counted as valid when it should fail",
   355  				test.name)
   356  		}
   357  	}
   358  }
   359  
   360  // TestSignatureSerialize ensures that serializing signatures works as expected.
   361  func TestSignatureSerialize(t *testing.T) {
   362  	tests := []struct {
   363  		name     string
   364  		ecsig    *Signature
   365  		expected []byte
   366  	}{
   367  		// signature from bitcoin blockchain tx
   368  		// 0437cd7f8525ceed2324359c2d0ba26006d92d85
   369  		{
   370  			"valid 1 - r and s most significant bits are zero",
   371  			&Signature{
   372  				R: fromHex("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"),
   373  				S: fromHex("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"),
   374  			},
   375  			[]byte{
   376  				0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
   377  				0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3,
   378  				0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32,
   379  				0xe9, 0xd6, 0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab,
   380  				0x5f, 0xb8, 0xcd, 0x41, 0x02, 0x20, 0x18, 0x15,
   381  				0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60,
   382  				0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c,
   383  				0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22,
   384  				0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
   385  			},
   386  		},
   387  		// signature from bitcoin blockchain tx
   388  		// cb00f8a0573b18faa8c4f467b049f5d202bf1101d9ef2633bc611be70376a4b4
   389  		{
   390  			"valid 2 - r most significant bit is one",
   391  			&Signature{
   392  				R: fromHex("0082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"),
   393  				S: fromHex("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"),
   394  			},
   395  			[]byte{
   396  				0x30, 0x45, 0x02, 0x21, 0x00, 0x82, 0x23, 0x5e,
   397  				0x21, 0xa2, 0x30, 0x00, 0x22, 0x73, 0x8d, 0xab,
   398  				0xb8, 0xe1, 0xbb, 0xd9, 0xd1, 0x9c, 0xfb, 0x1e,
   399  				0x7a, 0xb8, 0xc3, 0x0a, 0x23, 0xb0, 0xaf, 0xbb,
   400  				0x8d, 0x17, 0x8a, 0xbc, 0xf3, 0x02, 0x20, 0x24,
   401  				0xbf, 0x68, 0xe2, 0x56, 0xc5, 0x34, 0xdd, 0xfa,
   402  				0xf9, 0x66, 0xbf, 0x90, 0x8d, 0xeb, 0x94, 0x43,
   403  				0x05, 0x59, 0x6f, 0x7b, 0xdc, 0xc3, 0x8d, 0x69,
   404  				0xac, 0xad, 0x7f, 0x9c, 0x86, 0x87, 0x24,
   405  			},
   406  		},
   407  		// signature from bitcoin blockchain tx
   408  		// fda204502a3345e08afd6af27377c052e77f1fefeaeb31bdd45f1e1237ca5470
   409  		{
   410  			"valid 3 - s most significant bit is one",
   411  			&Signature{
   412  				R: fromHex("1cadddc2838598fee7dc35a12b340c6bde8b389f7bfd19a1252a17c4b5ed2d71"),
   413  				S: new(big.Int).Add(fromHex("00c1a251bbecb14b058a8bd77f65de87e51c47e95904f4c0e9d52eddc21c1415ac"), S256().N),
   414  			},
   415  			[]byte{
   416  				0x30, 0x45, 0x02, 0x20, 0x1c, 0xad, 0xdd, 0xc2,
   417  				0x83, 0x85, 0x98, 0xfe, 0xe7, 0xdc, 0x35, 0xa1,
   418  				0x2b, 0x34, 0x0c, 0x6b, 0xde, 0x8b, 0x38, 0x9f,
   419  				0x7b, 0xfd, 0x19, 0xa1, 0x25, 0x2a, 0x17, 0xc4,
   420  				0xb5, 0xed, 0x2d, 0x71, 0x02, 0x21, 0x00, 0xc1,
   421  				0xa2, 0x51, 0xbb, 0xec, 0xb1, 0x4b, 0x05, 0x8a,
   422  				0x8b, 0xd7, 0x7f, 0x65, 0xde, 0x87, 0xe5, 0x1c,
   423  				0x47, 0xe9, 0x59, 0x04, 0xf4, 0xc0, 0xe9, 0xd5,
   424  				0x2e, 0xdd, 0xc2, 0x1c, 0x14, 0x15, 0xac,
   425  			},
   426  		},
   427  		{
   428  			"valid 4 - s is bigger than half order",
   429  			&Signature{
   430  				R: fromHex("a196ed0e7ebcbe7b63fe1d8eecbdbde03a67ceba4fc8f6482bdcb9606a911404"),
   431  				S: fromHex("971729c7fa944b465b35250c6570a2f31acbb14b13d1565fab7330dcb2b3dfb1"),
   432  			},
   433  			[]byte{
   434  				0x30, 0x45, 0x02, 0x21, 0x00, 0xa1, 0x96, 0xed,
   435  				0x0e, 0x7e, 0xbc, 0xbe, 0x7b, 0x63, 0xfe, 0x1d,
   436  				0x8e, 0xec, 0xbd, 0xbd, 0xe0, 0x3a, 0x67, 0xce,
   437  				0xba, 0x4f, 0xc8, 0xf6, 0x48, 0x2b, 0xdc, 0xb9,
   438  				0x60, 0x6a, 0x91, 0x14, 0x04, 0x02, 0x20, 0x68,
   439  				0xe8, 0xd6, 0x38, 0x05, 0x6b, 0xb4, 0xb9, 0xa4,
   440  				0xca, 0xda, 0xf3, 0x9a, 0x8f, 0x5d, 0x0b, 0x9f,
   441  				0xe3, 0x2b, 0x9b, 0x9b, 0x77, 0x49, 0xdc, 0x14,
   442  				0x5f, 0x2d, 0xb0, 0x1d, 0x82, 0x61, 0x90,
   443  			},
   444  		},
   445  		{
   446  			"zero signature",
   447  			&Signature{
   448  				R: big.NewInt(0),
   449  				S: big.NewInt(0),
   450  			},
   451  			[]byte{0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00},
   452  		},
   453  	}
   454  
   455  	for i, test := range tests {
   456  		result := test.ecsig.Serialize()
   457  		if !bytes.Equal(result, test.expected) {
   458  			t.Errorf("Serialize #%d (%s) unexpected result:\n"+
   459  				"got:  %x\nwant: %x", i, test.name, result,
   460  				test.expected)
   461  		}
   462  	}
   463  }
   464  
   465  func testSignCompact(t *testing.T, tag string, curve *KoblitzCurve,
   466  	data []byte, isCompressed bool) {
   467  	priv, _ := NewPrivateKey(curve)
   468  
   469  	hashed := []byte("testing")
   470  	sig, err := SignCompact(curve, priv, hashed, isCompressed)
   471  	if err != nil {
   472  		t.Errorf("%s: error signing: %s", tag, err)
   473  		return
   474  	}
   475  
   476  	pk, wasCompressed, err := RecoverCompact(curve, sig, hashed)
   477  	if err != nil {
   478  		t.Errorf("%s: error recovering: %s", tag, err)
   479  		return
   480  	}
   481  	if pk.X.Cmp(priv.X) != 0 || pk.Y.Cmp(priv.Y) != 0 {
   482  		t.Errorf("%s: recovered pubkey doesn't match original "+
   483  			"(%v,%v) vs (%v,%v) ", tag, pk.X, pk.Y, priv.X, priv.Y)
   484  		return
   485  	}
   486  	if wasCompressed != isCompressed {
   487  		t.Errorf("%s: recovered pubkey doesn't match compressed state "+
   488  			"(%v vs %v)", tag, isCompressed, wasCompressed)
   489  		return
   490  	}
   491  
   492  	// If we change the compressed bit we should get the same key back,
   493  	// but the compressed flag should be reversed.
   494  	if isCompressed {
   495  		sig[0] -= 4
   496  	} else {
   497  		sig[0] += 4
   498  	}
   499  
   500  	pk, wasCompressed, err = RecoverCompact(curve, sig, hashed)
   501  	if err != nil {
   502  		t.Errorf("%s: error recovering (2): %s", tag, err)
   503  		return
   504  	}
   505  	if pk.X.Cmp(priv.X) != 0 || pk.Y.Cmp(priv.Y) != 0 {
   506  		t.Errorf("%s: recovered pubkey (2) doesn't match original "+
   507  			"(%v,%v) vs (%v,%v) ", tag, pk.X, pk.Y, priv.X, priv.Y)
   508  		return
   509  	}
   510  	if wasCompressed == isCompressed {
   511  		t.Errorf("%s: recovered pubkey doesn't match reversed "+
   512  			"compressed state (%v vs %v)", tag, isCompressed,
   513  			wasCompressed)
   514  		return
   515  	}
   516  }
   517  
   518  func TestSignCompact(t *testing.T) {
   519  	for i := 0; i < 256; i++ {
   520  		name := fmt.Sprintf("test %d", i)
   521  		data := make([]byte, 32)
   522  		_, err := rand.Read(data)
   523  		if err != nil {
   524  			t.Errorf("failed to read random data for %s", name)
   525  			continue
   526  		}
   527  		compressed := i%2 != 0
   528  		testSignCompact(t, name, S256(), data, compressed)
   529  	}
   530  }
   531  
   532  // recoveryTests assert basic tests for public key recovery from signatures.
   533  // The cases are borrowed from github.com/fjl/btcec-issue.
   534  var recoveryTests = []struct {
   535  	msg string
   536  	sig string
   537  	pub string
   538  	err error
   539  }{
   540  	{
   541  		// Valid curve point recovered.
   542  		msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008",
   543  		sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93",
   544  		pub: "04E32DF42865E97135ACFB65F3BAE71BDC86F4D49150AD6A440B6F15878109880A0A2B2667F7E725CEEA70C673093BF67663E0312623C8E091B13CF2C0F11EF652",
   545  	},
   546  	{
   547  		// Invalid curve point recovered.
   548  		msg: "00c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c",
   549  		sig: "0100b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f00b940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
   550  		err: fmt.Errorf("invalid square root"),
   551  	},
   552  	{
   553  		// Point at infinity recovered
   554  		msg: "6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9",
   555  		sig: "0079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9",
   556  		err: fmt.Errorf("point (Qx, Qy) equals the point at infinity"),
   557  	},
   558  	{
   559  		// Low R and S values.
   560  		msg: "ba09edc1275a285fb27bfe82c4eea240a907a0dbaf9e55764b8f318c37d5974f",
   561  		sig: "00000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000004",
   562  		pub: "04A7640409AA2083FDAD38B2D8DE1263B2251799591D840653FB02DBBA503D7745FCB83D80E08A1E02896BE691EA6AFFB8A35939A646F1FC79052A744B1C82EDC3",
   563  	},
   564  	{
   565  		// Zero R value
   566  		//
   567  		// Test case contributed by Ethereum Swarm: GH-1651
   568  		msg: "3060d2c77c1e192d62ad712fb400e04e6f779914a6876328ff3b213fa85d2012",
   569  		sig: "65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037a3",
   570  		err: fmt.Errorf("signature R is 0"),
   571  	},
   572  	{
   573  		// Zero R value
   574  		//
   575  		// Test case contributed by Ethereum Swarm: GH-1651
   576  		msg: "2bcebac60d8a78e520ae81c2ad586792df495ed429bd730dcd897b301932d054",
   577  		sig: "060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007c",
   578  		err: fmt.Errorf("signature R is 0"),
   579  	},
   580  	{
   581  		// R = N (curve order of secp256k1)
   582  		msg: "2bcebac60d8a78e520ae81c2ad586792df495ed429bd730dcd897b301932d054",
   583  		sig: "65fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414100000000000000000000000000000000000000000000000000000000000037a3",
   584  		err: fmt.Errorf("signature R is >= curve order"),
   585  	},
   586  	{
   587  		// Zero S value
   588  		msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008",
   589  		sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549980000000000000000000000000000000000000000000000000000000000000000",
   590  		err: fmt.Errorf("signature S is 0"),
   591  	},
   592  	{
   593  		// S = N (curve order of secp256k1)
   594  		msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008",
   595  		sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e54998fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
   596  		err: fmt.Errorf("signature S is >= curve order"),
   597  	},
   598  }
   599  
   600  func TestRecoverCompact(t *testing.T) {
   601  	for i, test := range recoveryTests {
   602  		msg := decodeHex(test.msg)
   603  		sig := decodeHex(test.sig)
   604  
   605  		// Magic DER constant.
   606  		sig[0] += 27
   607  
   608  		pub, _, err := RecoverCompact(S256(), sig, msg)
   609  
   610  		// Verify that returned error matches as expected.
   611  		if !reflect.DeepEqual(test.err, err) {
   612  			t.Errorf("unexpected error returned from pubkey "+
   613  				"recovery #%d: wanted %v, got %v",
   614  				i, test.err, err)
   615  			continue
   616  		}
   617  
   618  		// If check succeeded because a proper error was returned, we
   619  		// ignore the returned pubkey.
   620  		if err != nil {
   621  			continue
   622  		}
   623  
   624  		// Otherwise, ensure the correct public key was recovered.
   625  		exPub, _ := ParsePubKey(decodeHex(test.pub), S256())
   626  		if !exPub.IsEqual(pub) {
   627  			t.Errorf("unexpected recovered public key #%d: "+
   628  				"want %v, got %v", i, exPub, pub)
   629  		}
   630  	}
   631  }
   632  
   633  func TestRFC6979(t *testing.T) {
   634  	// Test vectors matching Trezor and CoreBitcoin implementations.
   635  	// - https://github.com/trezor/trezor-crypto/blob/9fea8f8ab377dc514e40c6fd1f7c89a74c1d8dc6/tests.c#L432-L453
   636  	// - https://github.com/oleganza/CoreBitcoin/blob/e93dd71207861b5bf044415db5fa72405e7d8fbc/CoreBitcoin/BTCKey%2BTests.m#L23-L49
   637  	tests := []struct {
   638  		key       string
   639  		msg       string
   640  		nonce     string
   641  		signature string
   642  	}{
   643  		{
   644  			"cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50",
   645  			"sample",
   646  			"2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3",
   647  			"3045022100af340daf02cc15c8d5d08d7735dfe6b98a474ed373bdb5fbecf7571be52b384202205009fb27f37034a9b24b707b7c6b79ca23ddef9e25f7282e8a797efe53a8f124",
   648  		},
   649  		{
   650  			// This signature hits the case when S is higher than halforder.
   651  			// If S is not canonicalized (lowered by halforder), this test will fail.
   652  			"0000000000000000000000000000000000000000000000000000000000000001",
   653  			"Satoshi Nakamoto",
   654  			"8f8a276c19f4149656b280621e358cce24f5f52542772691ee69063b74f15d15",
   655  			"3045022100934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d802202442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5",
   656  		},
   657  		{
   658  			"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
   659  			"Satoshi Nakamoto",
   660  			"33a19b60e25fb6f4435af53a3d42d493644827367e6453928554f43e49aa6f90",
   661  			"3045022100fd567d121db66e382991534ada77a6bd3106f0a1098c231e47993447cd6af2d002206b39cd0eb1bc8603e159ef5c20a5c8ad685a45b06ce9bebed3f153d10d93bed5",
   662  		},
   663  		{
   664  			"f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181",
   665  			"Alan Turing",
   666  			"525a82b70e67874398067543fd84c83d30c175fdc45fdeee082fe13b1d7cfdf1",
   667  			"304402207063ae83e7f62bbb171798131b4a0564b956930092b33b07b395615d9ec7e15c022058dfcc1e00a35e1572f366ffe34ba0fc47db1e7189759b9fb233c5b05ab388ea",
   668  		},
   669  		{
   670  			"0000000000000000000000000000000000000000000000000000000000000001",
   671  			"All those moments will be lost in time, like tears in rain. Time to die...",
   672  			"38aa22d72376b4dbc472e06c3ba403ee0a394da63fc58d88686c611aba98d6b3",
   673  			"30450221008600dbd41e348fe5c9465ab92d23e3db8b98b873beecd930736488696438cb6b0220547fe64427496db33bf66019dacbf0039c04199abb0122918601db38a72cfc21",
   674  		},
   675  		{
   676  			"e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2",
   677  			"There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!",
   678  			"1f4b84c23a86a221d233f2521be018d9318639d5b8bbd6374a8a59232d16ad3d",
   679  			"3045022100b552edd27580141f3b2a5463048cb7cd3e047b97c9f98076c32dbdf85a68718b0220279fa72dd19bfae05577e06c7c0c1900c371fcd5893f7e1d56a37d30174671f6",
   680  		},
   681  	}
   682  
   683  	for i, test := range tests {
   684  		privKey, _ := PrivKeyFromBytes(S256(), decodeHex(test.key))
   685  		hash := sha256.Sum256([]byte(test.msg))
   686  
   687  		// Ensure deterministically generated nonce is the expected value.
   688  		gotNonce := nonceRFC6979(privKey.D, hash[:]).Bytes()
   689  		wantNonce := decodeHex(test.nonce)
   690  		if !bytes.Equal(gotNonce, wantNonce) {
   691  			t.Errorf("NonceRFC6979 #%d (%s): Nonce is incorrect: "+
   692  				"%x (expected %x)", i, test.msg, gotNonce,
   693  				wantNonce)
   694  			continue
   695  		}
   696  
   697  		// Ensure deterministically generated signature is the expected value.
   698  		gotSig, err := privKey.Sign(hash[:])
   699  		if err != nil {
   700  			t.Errorf("Sign #%d (%s): unexpected error: %v", i,
   701  				test.msg, err)
   702  			continue
   703  		}
   704  		gotSigBytes := gotSig.Serialize()
   705  		wantSigBytes := decodeHex(test.signature)
   706  		if !bytes.Equal(gotSigBytes, wantSigBytes) {
   707  			t.Errorf("Sign #%d (%s): mismatched signature: %x "+
   708  				"(expected %x)", i, test.msg, gotSigBytes,
   709  				wantSigBytes)
   710  			continue
   711  		}
   712  	}
   713  }
   714  
   715  func TestSignatureIsEqual(t *testing.T) {
   716  	sig1 := &Signature{
   717  		R: fromHex("0082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"),
   718  		S: fromHex("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"),
   719  	}
   720  	sig2 := &Signature{
   721  		R: fromHex("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"),
   722  		S: fromHex("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"),
   723  	}
   724  
   725  	if !sig1.IsEqual(sig1) {
   726  		t.Fatalf("value of IsEqual is incorrect, %v is "+
   727  			"equal to %v", sig1, sig1)
   728  	}
   729  
   730  	if sig1.IsEqual(sig2) {
   731  		t.Fatalf("value of IsEqual is incorrect, %v is not "+
   732  			"equal to %v", sig1, sig2)
   733  	}
   734  }