github.com/palcoin-project/palcd@v1.0.0/btcec/pubkey_test.go (about) 1 // Copyright (c) 2013-2016 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 "testing" 10 11 "github.com/davecgh/go-spew/spew" 12 ) 13 14 type pubKeyTest struct { 15 name string 16 key []byte 17 format byte 18 isValid bool 19 } 20 21 var pubKeyTests = []pubKeyTest{ 22 // pubkey from bitcoin blockchain tx 23 // 0437cd7f8525ceed2324359c2d0ba26006d92d85 24 { 25 name: "uncompressed ok", 26 key: []byte{0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 27 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 28 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 29 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 30 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 31 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 32 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 33 0xb4, 0x12, 0xa3, 34 }, 35 isValid: true, 36 format: pubkeyUncompressed, 37 }, 38 { 39 name: "uncompressed x changed", 40 key: []byte{0x04, 0x15, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 41 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 42 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 43 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 44 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 45 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 46 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 47 0xb4, 0x12, 0xa3, 48 }, 49 isValid: false, 50 }, 51 { 52 name: "uncompressed y changed", 53 key: []byte{0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 54 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 55 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 56 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 57 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 58 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 59 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 60 0xb4, 0x12, 0xa4, 61 }, 62 isValid: false, 63 }, 64 { 65 name: "uncompressed claims compressed", 66 key: []byte{0x03, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 67 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 68 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 69 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 70 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 71 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 72 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 73 0xb4, 0x12, 0xa3, 74 }, 75 isValid: false, 76 }, 77 { 78 name: "uncompressed as hybrid ok", 79 key: []byte{0x07, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 80 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 81 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 82 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 83 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 84 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 85 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 86 0xb4, 0x12, 0xa3, 87 }, 88 isValid: true, 89 format: pubkeyHybrid, 90 }, 91 { 92 name: "uncompressed as hybrid wrong", 93 key: []byte{0x06, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 94 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 95 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 96 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 97 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 98 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 99 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 100 0xb4, 0x12, 0xa3, 101 }, 102 isValid: false, 103 }, 104 // from tx 0b09c51c51ff762f00fb26217269d2a18e77a4fa87d69b3c363ab4df16543f20 105 { 106 name: "compressed ok (ybit = 0)", 107 key: []byte{0x02, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b, 108 0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1, 109 0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21, 110 0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d, 111 }, 112 isValid: true, 113 format: pubkeyCompressed, 114 }, 115 // from tx fdeb8e72524e8dab0da507ddbaf5f88fe4a933eb10a66bc4745bb0aa11ea393c 116 { 117 name: "compressed ok (ybit = 1)", 118 key: []byte{0x03, 0x26, 0x89, 0xc7, 0xc2, 0xda, 0xb1, 0x33, 119 0x09, 0xfb, 0x14, 0x3e, 0x0e, 0x8f, 0xe3, 0x96, 0x34, 120 0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4, 121 0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e, 122 }, 123 isValid: true, 124 format: pubkeyCompressed, 125 }, 126 { 127 name: "compressed claims uncompressed (ybit = 0)", 128 key: []byte{0x04, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b, 129 0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1, 130 0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21, 131 0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d, 132 }, 133 isValid: false, 134 }, 135 { 136 name: "compressed claims uncompressed (ybit = 1)", 137 key: []byte{0x05, 0x26, 0x89, 0xc7, 0xc2, 0xda, 0xb1, 0x33, 138 0x09, 0xfb, 0x14, 0x3e, 0x0e, 0x8f, 0xe3, 0x96, 0x34, 139 0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4, 140 0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e, 141 }, 142 isValid: false, 143 }, 144 { 145 name: "wrong length)", 146 key: []byte{0x05}, 147 isValid: false, 148 }, 149 { 150 name: "X == P", 151 key: []byte{0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 152 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 153 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 154 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F, 0xb2, 0xe0, 155 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 156 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 157 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 158 0xb4, 0x12, 0xa3, 159 }, 160 isValid: false, 161 }, 162 { 163 name: "X > P", 164 key: []byte{0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 165 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 166 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 167 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFD, 0x2F, 0xb2, 0xe0, 168 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 169 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 170 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 171 0xb4, 0x12, 0xa3, 172 }, 173 isValid: false, 174 }, 175 { 176 name: "Y == P", 177 key: []byte{0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 178 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 179 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 180 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xFF, 0xFF, 181 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 182 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 183 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 184 0xFF, 0xFC, 0x2F, 185 }, 186 isValid: false, 187 }, 188 { 189 name: "Y > P", 190 key: []byte{0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 191 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 192 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 193 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xFF, 0xFF, 194 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 195 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 196 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 197 0xFF, 0xFD, 0x2F, 198 }, 199 isValid: false, 200 }, 201 { 202 name: "hybrid", 203 key: []byte{0x06, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 204 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 205 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 206 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a, 207 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 208 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 209 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 210 0x10, 0xd4, 0xb8, 211 }, 212 format: pubkeyHybrid, 213 isValid: true, 214 }, 215 } 216 217 func TestPubKeys(t *testing.T) { 218 for _, test := range pubKeyTests { 219 pk, err := ParsePubKey(test.key, S256()) 220 if err != nil { 221 if test.isValid { 222 t.Errorf("%s pubkey failed when shouldn't %v", 223 test.name, err) 224 } 225 continue 226 } 227 if !test.isValid { 228 t.Errorf("%s counted as valid when it should fail", 229 test.name) 230 continue 231 } 232 var pkStr []byte 233 switch test.format { 234 case pubkeyUncompressed: 235 pkStr = pk.SerializeUncompressed() 236 case pubkeyCompressed: 237 pkStr = pk.SerializeCompressed() 238 case pubkeyHybrid: 239 pkStr = pk.SerializeHybrid() 240 } 241 if !bytes.Equal(test.key, pkStr) { 242 t.Errorf("%s pubkey: serialized keys do not match.", 243 test.name) 244 spew.Dump(test.key) 245 spew.Dump(pkStr) 246 } 247 } 248 } 249 250 func TestPublicKeyIsEqual(t *testing.T) { 251 pubKey1, err := ParsePubKey( 252 []byte{0x03, 0x26, 0x89, 0xc7, 0xc2, 0xda, 0xb1, 0x33, 253 0x09, 0xfb, 0x14, 0x3e, 0x0e, 0x8f, 0xe3, 0x96, 0x34, 254 0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4, 255 0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e, 256 }, 257 S256(), 258 ) 259 if err != nil { 260 t.Fatalf("failed to parse raw bytes for pubKey1: %v", err) 261 } 262 263 pubKey2, err := ParsePubKey( 264 []byte{0x02, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b, 265 0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1, 266 0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21, 267 0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d, 268 }, 269 S256(), 270 ) 271 if err != nil { 272 t.Fatalf("failed to parse raw bytes for pubKey2: %v", err) 273 } 274 275 if !pubKey1.IsEqual(pubKey1) { 276 t.Fatalf("value of IsEqual is incorrect, %v is "+ 277 "equal to %v", pubKey1, pubKey1) 278 } 279 280 if pubKey1.IsEqual(pubKey2) { 281 t.Fatalf("value of IsEqual is incorrect, %v is not "+ 282 "equal to %v", pubKey1, pubKey2) 283 } 284 } 285 286 func TestIsCompressed(t *testing.T) { 287 for _, test := range pubKeyTests { 288 isCompressed := IsCompressedPubKey(test.key) 289 wantCompressed := (test.format == pubkeyCompressed) 290 if isCompressed != wantCompressed { 291 t.Fatalf("%s (%x) pubkey: unexpected compressed result, "+ 292 "got %v, want %v", test.name, test.key, 293 isCompressed, wantCompressed) 294 } 295 } 296 }