1/*- 2 * Copyright 2014 Square Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package jose 18 19import ( 20 "crypto" 21 "crypto/ecdsa" 22 "crypto/elliptic" 23 "crypto/rsa" 24 "crypto/x509" 25 "encoding/base64" 26 "errors" 27 "fmt" 28 "math/big" 29 "reflect" 30 "strings" 31 32 "golang.org/x/crypto/ed25519" 33 34 "gopkg.in/square/go-jose.v2/json" 35) 36 37// rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing. 38type rawJSONWebKey struct { 39 Use string `json:"use,omitempty"` 40 Kty string `json:"kty,omitempty"` 41 Kid string `json:"kid,omitempty"` 42 Crv string `json:"crv,omitempty"` 43 Alg string `json:"alg,omitempty"` 44 K *byteBuffer `json:"k,omitempty"` 45 X *byteBuffer `json:"x,omitempty"` 46 Y *byteBuffer `json:"y,omitempty"` 47 N *byteBuffer `json:"n,omitempty"` 48 E *byteBuffer `json:"e,omitempty"` 49 // -- Following fields are only used for private keys -- 50 // RSA uses D, P and Q, while ECDSA uses only D. Fields Dp, Dq, and Qi are 51 // completely optional. Therefore for RSA/ECDSA, D != nil is a contract that 52 // we have a private key whereas D == nil means we have only a public key. 53 D *byteBuffer `json:"d,omitempty"` 54 P *byteBuffer `json:"p,omitempty"` 55 Q *byteBuffer `json:"q,omitempty"` 56 Dp *byteBuffer `json:"dp,omitempty"` 57 Dq *byteBuffer `json:"dq,omitempty"` 58 Qi *byteBuffer `json:"qi,omitempty"` 59 // Certificates 60 X5c []string `json:"x5c,omitempty"` 61} 62 63// JSONWebKey represents a public or private key in JWK format. 64type JSONWebKey struct { 65 Key interface{} 66 Certificates []*x509.Certificate 67 KeyID string 68 Algorithm string 69 Use string 70} 71 72// MarshalJSON serializes the given key to its JSON representation. 73func (k JSONWebKey) MarshalJSON() ([]byte, error) { 74 var raw *rawJSONWebKey 75 var err error 76 77 switch key := k.Key.(type) { 78 case ed25519.PublicKey: 79 raw = fromEdPublicKey(key) 80 case *ecdsa.PublicKey: 81 raw, err = fromEcPublicKey(key) 82 case *rsa.PublicKey: 83 raw = fromRsaPublicKey(key) 84 case ed25519.PrivateKey: 85 raw, err = fromEdPrivateKey(key) 86 case *ecdsa.PrivateKey: 87 raw, err = fromEcPrivateKey(key) 88 case *rsa.PrivateKey: 89 raw, err = fromRsaPrivateKey(key) 90 case []byte: 91 raw, err = fromSymmetricKey(key) 92 default: 93 return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key)) 94 } 95 96 if err != nil { 97 return nil, err 98 } 99 100 raw.Kid = k.KeyID 101 raw.Alg = k.Algorithm 102 raw.Use = k.Use 103 104 for _, cert := range k.Certificates { 105 raw.X5c = append(raw.X5c, base64.StdEncoding.EncodeToString(cert.Raw)) 106 } 107 108 return json.Marshal(raw) 109} 110 111// UnmarshalJSON reads a key from its JSON representation. 112func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { 113 var raw rawJSONWebKey 114 err = json.Unmarshal(data, &raw) 115 if err != nil { 116 return err 117 } 118 119 var key interface{} 120 switch raw.Kty { 121 case "EC": 122 if raw.D != nil { 123 key, err = raw.ecPrivateKey() 124 } else { 125 key, err = raw.ecPublicKey() 126 } 127 case "RSA": 128 if raw.D != nil { 129 key, err = raw.rsaPrivateKey() 130 } else { 131 key, err = raw.rsaPublicKey() 132 } 133 case "oct": 134 key, err = raw.symmetricKey() 135 case "OKP": 136 if raw.Crv == "Ed25519" && raw.X != nil { 137 if raw.D != nil { 138 key, err = raw.edPrivateKey() 139 } else { 140 key, err = raw.edPublicKey() 141 } 142 } else { 143 err = fmt.Errorf("square/go-jose: unknown curve %s'", raw.Crv) 144 } 145 default: 146 err = fmt.Errorf("square/go-jose: unknown json web key type '%s'", raw.Kty) 147 } 148 149 if err == nil { 150 *k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use} 151 152 k.Certificates, err = parseCertificateChain(raw.X5c) 153 if err != nil { 154 return fmt.Errorf("failed to unmarshal x5c field: %s", err) 155 } 156 } 157 158 return 159} 160 161// JSONWebKeySet represents a JWK Set object. 162type JSONWebKeySet struct { 163 Keys []JSONWebKey `json:"keys"` 164} 165 166// Key convenience method returns keys by key ID. Specification states 167// that a JWK Set "SHOULD" use distinct key IDs, but allows for some 168// cases where they are not distinct. Hence method returns a slice 169// of JSONWebKeys. 170func (s *JSONWebKeySet) Key(kid string) []JSONWebKey { 171 var keys []JSONWebKey 172 for _, key := range s.Keys { 173 if key.KeyID == kid { 174 keys = append(keys, key) 175 } 176 } 177 178 return keys 179} 180 181const rsaThumbprintTemplate = `{"e":"%s","kty":"RSA","n":"%s"}` 182const ecThumbprintTemplate = `{"crv":"%s","kty":"EC","x":"%s","y":"%s"}` 183const edThumbprintTemplate = `{"crv":"%s","kty":"OKP",x":"%s"}` 184 185func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) { 186 coordLength := curveSize(curve) 187 crv, err := curveName(curve) 188 if err != nil { 189 return "", err 190 } 191 192 if len(x.Bytes()) > coordLength || len(y.Bytes()) > coordLength { 193 return "", errors.New("square/go-jose: invalid elliptic key (too large)") 194 } 195 196 return fmt.Sprintf(ecThumbprintTemplate, crv, 197 newFixedSizeBuffer(x.Bytes(), coordLength).base64(), 198 newFixedSizeBuffer(y.Bytes(), coordLength).base64()), nil 199} 200 201func rsaThumbprintInput(n *big.Int, e int) (string, error) { 202 return fmt.Sprintf(rsaThumbprintTemplate, 203 newBufferFromInt(uint64(e)).base64(), 204 newBuffer(n.Bytes()).base64()), nil 205} 206 207func edThumbprintInput(ed ed25519.PublicKey) (string, error) { 208 crv := "Ed25519" 209 if len(ed) > 32 { 210 return "", errors.New("square/go-jose: invalid elliptic key (too large)") 211 } 212 return fmt.Sprintf(edThumbprintTemplate, crv, 213 newFixedSizeBuffer(ed, 32).base64()), nil 214} 215 216// Thumbprint computes the JWK Thumbprint of a key using the 217// indicated hash algorithm. 218func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) { 219 var input string 220 var err error 221 switch key := k.Key.(type) { 222 case ed25519.PublicKey: 223 input, err = edThumbprintInput(key) 224 case *ecdsa.PublicKey: 225 input, err = ecThumbprintInput(key.Curve, key.X, key.Y) 226 case *ecdsa.PrivateKey: 227 input, err = ecThumbprintInput(key.Curve, key.X, key.Y) 228 case *rsa.PublicKey: 229 input, err = rsaThumbprintInput(key.N, key.E) 230 case *rsa.PrivateKey: 231 input, err = rsaThumbprintInput(key.N, key.E) 232 case ed25519.PrivateKey: 233 input, err = edThumbprintInput(ed25519.PublicKey(key[32:])) 234 default: 235 return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key)) 236 } 237 238 if err != nil { 239 return nil, err 240 } 241 242 h := hash.New() 243 h.Write([]byte(input)) 244 return h.Sum(nil), nil 245} 246 247// IsPublic returns true if the JWK represents a public key (not symmetric, not private). 248func (k *JSONWebKey) IsPublic() bool { 249 switch k.Key.(type) { 250 case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey: 251 return true 252 default: 253 return false 254 } 255} 256 257// Public creates JSONWebKey with corresponding publik key if JWK represents asymmetric private key. 258func (k *JSONWebKey) Public() JSONWebKey { 259 if k.IsPublic() { 260 return *k 261 } 262 ret := *k 263 switch key := k.Key.(type) { 264 case *ecdsa.PrivateKey: 265 ret.Key = key.Public() 266 case *rsa.PrivateKey: 267 ret.Key = key.Public() 268 case ed25519.PrivateKey: 269 ret.Key = key.Public() 270 default: 271 return JSONWebKey{} // returning invalid key 272 } 273 return ret 274} 275 276// Valid checks that the key contains the expected parameters. 277func (k *JSONWebKey) Valid() bool { 278 if k.Key == nil { 279 return false 280 } 281 switch key := k.Key.(type) { 282 case *ecdsa.PublicKey: 283 if key.Curve == nil || key.X == nil || key.Y == nil { 284 return false 285 } 286 case *ecdsa.PrivateKey: 287 if key.Curve == nil || key.X == nil || key.Y == nil || key.D == nil { 288 return false 289 } 290 case *rsa.PublicKey: 291 if key.N == nil || key.E == 0 { 292 return false 293 } 294 case *rsa.PrivateKey: 295 if key.N == nil || key.E == 0 || key.D == nil || len(key.Primes) < 2 { 296 return false 297 } 298 case ed25519.PublicKey: 299 if len(key) != 32 { 300 return false 301 } 302 case ed25519.PrivateKey: 303 if len(key) != 64 { 304 return false 305 } 306 default: 307 return false 308 } 309 return true 310} 311 312func (key rawJSONWebKey) rsaPublicKey() (*rsa.PublicKey, error) { 313 if key.N == nil || key.E == nil { 314 return nil, fmt.Errorf("square/go-jose: invalid RSA key, missing n/e values") 315 } 316 317 return &rsa.PublicKey{ 318 N: key.N.bigInt(), 319 E: key.E.toInt(), 320 }, nil 321} 322 323func fromEdPublicKey(pub ed25519.PublicKey) *rawJSONWebKey { 324 return &rawJSONWebKey{ 325 Kty: "OKP", 326 Crv: "Ed25519", 327 X: newBuffer(pub), 328 } 329} 330 331func fromRsaPublicKey(pub *rsa.PublicKey) *rawJSONWebKey { 332 return &rawJSONWebKey{ 333 Kty: "RSA", 334 N: newBuffer(pub.N.Bytes()), 335 E: newBufferFromInt(uint64(pub.E)), 336 } 337} 338 339func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) { 340 var curve elliptic.Curve 341 switch key.Crv { 342 case "P-256": 343 curve = elliptic.P256() 344 case "P-384": 345 curve = elliptic.P384() 346 case "P-521": 347 curve = elliptic.P521() 348 default: 349 return nil, fmt.Errorf("square/go-jose: unsupported elliptic curve '%s'", key.Crv) 350 } 351 352 if key.X == nil || key.Y == nil { 353 return nil, errors.New("square/go-jose: invalid EC key, missing x/y values") 354 } 355 356 // The length of this octet string MUST be the full size of a coordinate for 357 // the curve specified in the "crv" parameter. 358 // https://tools.ietf.org/html/rfc7518#section-6.2.1.2 359 if curveSize(curve) != len(key.X.data) { 360 return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for x") 361 } 362 363 if curveSize(curve) != len(key.Y.data) { 364 return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for y") 365 } 366 367 x := key.X.bigInt() 368 y := key.Y.bigInt() 369 370 if !curve.IsOnCurve(x, y) { 371 return nil, errors.New("square/go-jose: invalid EC key, X/Y are not on declared curve") 372 } 373 374 return &ecdsa.PublicKey{ 375 Curve: curve, 376 X: x, 377 Y: y, 378 }, nil 379} 380 381func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) { 382 if pub == nil || pub.X == nil || pub.Y == nil { 383 return nil, fmt.Errorf("square/go-jose: invalid EC key (nil, or X/Y missing)") 384 } 385 386 name, err := curveName(pub.Curve) 387 if err != nil { 388 return nil, err 389 } 390 391 size := curveSize(pub.Curve) 392 393 xBytes := pub.X.Bytes() 394 yBytes := pub.Y.Bytes() 395 396 if len(xBytes) > size || len(yBytes) > size { 397 return nil, fmt.Errorf("square/go-jose: invalid EC key (X/Y too large)") 398 } 399 400 key := &rawJSONWebKey{ 401 Kty: "EC", 402 Crv: name, 403 X: newFixedSizeBuffer(xBytes, size), 404 Y: newFixedSizeBuffer(yBytes, size), 405 } 406 407 return key, nil 408} 409 410func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) { 411 var missing []string 412 switch { 413 case key.D == nil: 414 missing = append(missing, "D") 415 case key.X == nil: 416 missing = append(missing, "X") 417 } 418 419 if len(missing) > 0 { 420 return nil, fmt.Errorf("square/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", ")) 421 } 422 423 privateKey := make([]byte, ed25519.PrivateKeySize) 424 copy(privateKey[0:32], key.D.bytes()) 425 copy(privateKey[32:], key.X.bytes()) 426 rv := ed25519.PrivateKey(privateKey) 427 return rv, nil 428} 429 430func (key rawJSONWebKey) edPublicKey() (ed25519.PublicKey, error) { 431 if key.X == nil { 432 return nil, fmt.Errorf("square/go-jose: invalid Ed key, missing x value") 433 } 434 publicKey := make([]byte, ed25519.PublicKeySize) 435 copy(publicKey[0:32], key.X.bytes()) 436 rv := ed25519.PublicKey(publicKey) 437 return rv, nil 438} 439 440func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) { 441 var missing []string 442 switch { 443 case key.N == nil: 444 missing = append(missing, "N") 445 case key.E == nil: 446 missing = append(missing, "E") 447 case key.D == nil: 448 missing = append(missing, "D") 449 case key.P == nil: 450 missing = append(missing, "P") 451 case key.Q == nil: 452 missing = append(missing, "Q") 453 } 454 455 if len(missing) > 0 { 456 return nil, fmt.Errorf("square/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", ")) 457 } 458 459 rv := &rsa.PrivateKey{ 460 PublicKey: rsa.PublicKey{ 461 N: key.N.bigInt(), 462 E: key.E.toInt(), 463 }, 464 D: key.D.bigInt(), 465 Primes: []*big.Int{ 466 key.P.bigInt(), 467 key.Q.bigInt(), 468 }, 469 } 470 471 if key.Dp != nil { 472 rv.Precomputed.Dp = key.Dp.bigInt() 473 } 474 if key.Dq != nil { 475 rv.Precomputed.Dq = key.Dq.bigInt() 476 } 477 if key.Qi != nil { 478 rv.Precomputed.Qinv = key.Qi.bigInt() 479 } 480 481 err := rv.Validate() 482 return rv, err 483} 484 485func fromEdPrivateKey(ed ed25519.PrivateKey) (*rawJSONWebKey, error) { 486 raw := fromEdPublicKey(ed25519.PublicKey(ed[32:])) 487 488 raw.D = newBuffer(ed[0:32]) 489 return raw, nil 490} 491 492func fromRsaPrivateKey(rsa *rsa.PrivateKey) (*rawJSONWebKey, error) { 493 if len(rsa.Primes) != 2 { 494 return nil, ErrUnsupportedKeyType 495 } 496 497 raw := fromRsaPublicKey(&rsa.PublicKey) 498 499 raw.D = newBuffer(rsa.D.Bytes()) 500 raw.P = newBuffer(rsa.Primes[0].Bytes()) 501 raw.Q = newBuffer(rsa.Primes[1].Bytes()) 502 503 if rsa.Precomputed.Dp != nil { 504 raw.Dp = newBuffer(rsa.Precomputed.Dp.Bytes()) 505 } 506 if rsa.Precomputed.Dq != nil { 507 raw.Dq = newBuffer(rsa.Precomputed.Dq.Bytes()) 508 } 509 if rsa.Precomputed.Qinv != nil { 510 raw.Qi = newBuffer(rsa.Precomputed.Qinv.Bytes()) 511 } 512 513 return raw, nil 514} 515 516func (key rawJSONWebKey) ecPrivateKey() (*ecdsa.PrivateKey, error) { 517 var curve elliptic.Curve 518 switch key.Crv { 519 case "P-256": 520 curve = elliptic.P256() 521 case "P-384": 522 curve = elliptic.P384() 523 case "P-521": 524 curve = elliptic.P521() 525 default: 526 return nil, fmt.Errorf("square/go-jose: unsupported elliptic curve '%s'", key.Crv) 527 } 528 529 if key.X == nil || key.Y == nil || key.D == nil { 530 return nil, fmt.Errorf("square/go-jose: invalid EC private key, missing x/y/d values") 531 } 532 533 // The length of this octet string MUST be the full size of a coordinate for 534 // the curve specified in the "crv" parameter. 535 // https://tools.ietf.org/html/rfc7518#section-6.2.1.2 536 if curveSize(curve) != len(key.X.data) { 537 return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for x") 538 } 539 540 if curveSize(curve) != len(key.Y.data) { 541 return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for y") 542 } 543 544 // https://tools.ietf.org/html/rfc7518#section-6.2.2.1 545 if dSize(curve) != len(key.D.data) { 546 return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for d") 547 } 548 549 x := key.X.bigInt() 550 y := key.Y.bigInt() 551 552 if !curve.IsOnCurve(x, y) { 553 return nil, errors.New("square/go-jose: invalid EC key, X/Y are not on declared curve") 554 } 555 556 return &ecdsa.PrivateKey{ 557 PublicKey: ecdsa.PublicKey{ 558 Curve: curve, 559 X: x, 560 Y: y, 561 }, 562 D: key.D.bigInt(), 563 }, nil 564} 565 566func fromEcPrivateKey(ec *ecdsa.PrivateKey) (*rawJSONWebKey, error) { 567 raw, err := fromEcPublicKey(&ec.PublicKey) 568 if err != nil { 569 return nil, err 570 } 571 572 if ec.D == nil { 573 return nil, fmt.Errorf("square/go-jose: invalid EC private key") 574 } 575 576 raw.D = newFixedSizeBuffer(ec.D.Bytes(), dSize(ec.PublicKey.Curve)) 577 578 return raw, nil 579} 580 581// dSize returns the size in octets for the "d" member of an elliptic curve 582// private key. 583// The length of this octet string MUST be ceiling(log-base-2(n)/8) 584// octets (where n is the order of the curve). 585// https://tools.ietf.org/html/rfc7518#section-6.2.2.1 586func dSize(curve elliptic.Curve) int { 587 order := curve.Params().P 588 bitLen := order.BitLen() 589 size := bitLen / 8 590 if bitLen%8 != 0 { 591 size = size + 1 592 } 593 return size 594} 595 596func fromSymmetricKey(key []byte) (*rawJSONWebKey, error) { 597 return &rawJSONWebKey{ 598 Kty: "oct", 599 K: newBuffer(key), 600 }, nil 601} 602 603func (key rawJSONWebKey) symmetricKey() ([]byte, error) { 604 if key.K == nil { 605 return nil, fmt.Errorf("square/go-jose: invalid OCT (symmetric) key, missing k value") 606 } 607 return key.K.bytes(), nil 608} 609