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/aes" 22 "crypto/ecdsa" 23 "crypto/rand" 24 "crypto/rsa" 25 "crypto/sha1" 26 "crypto/sha256" 27 "errors" 28 "fmt" 29 "math/big" 30 31 "golang.org/x/crypto/ed25519" 32 josecipher "gopkg.in/square/go-jose.v2/cipher" 33 "gopkg.in/square/go-jose.v2/json" 34) 35 36// A generic RSA-based encrypter/verifier 37type rsaEncrypterVerifier struct { 38 publicKey *rsa.PublicKey 39} 40 41// A generic RSA-based decrypter/signer 42type rsaDecrypterSigner struct { 43 privateKey *rsa.PrivateKey 44} 45 46// A generic EC-based encrypter/verifier 47type ecEncrypterVerifier struct { 48 publicKey *ecdsa.PublicKey 49} 50 51type edEncrypterVerifier struct { 52 publicKey ed25519.PublicKey 53} 54 55// A key generator for ECDH-ES 56type ecKeyGenerator struct { 57 size int 58 algID string 59 publicKey *ecdsa.PublicKey 60} 61 62// A generic EC-based decrypter/signer 63type ecDecrypterSigner struct { 64 privateKey *ecdsa.PrivateKey 65} 66 67type edDecrypterSigner struct { 68 privateKey ed25519.PrivateKey 69} 70 71// newRSARecipient creates recipientKeyInfo based on the given key. 72func newRSARecipient(keyAlg KeyAlgorithm, publicKey *rsa.PublicKey) (recipientKeyInfo, error) { 73 // Verify that key management algorithm is supported by this encrypter 74 switch keyAlg { 75 case RSA1_5, RSA_OAEP, RSA_OAEP_256: 76 default: 77 return recipientKeyInfo{}, ErrUnsupportedAlgorithm 78 } 79 80 if publicKey == nil { 81 return recipientKeyInfo{}, errors.New("invalid public key") 82 } 83 84 return recipientKeyInfo{ 85 keyAlg: keyAlg, 86 keyEncrypter: &rsaEncrypterVerifier{ 87 publicKey: publicKey, 88 }, 89 }, nil 90} 91 92// newRSASigner creates a recipientSigInfo based on the given key. 93func newRSASigner(sigAlg SignatureAlgorithm, privateKey *rsa.PrivateKey) (recipientSigInfo, error) { 94 // Verify that key management algorithm is supported by this encrypter 95 switch sigAlg { 96 case RS256, RS384, RS512, PS256, PS384, PS512: 97 default: 98 return recipientSigInfo{}, ErrUnsupportedAlgorithm 99 } 100 101 if privateKey == nil { 102 return recipientSigInfo{}, errors.New("invalid private key") 103 } 104 105 return recipientSigInfo{ 106 sigAlg: sigAlg, 107 publicKey: staticPublicKey(&JSONWebKey{ 108 Key: privateKey.Public(), 109 }), 110 signer: &rsaDecrypterSigner{ 111 privateKey: privateKey, 112 }, 113 }, nil 114} 115 116func newEd25519Signer(sigAlg SignatureAlgorithm, privateKey ed25519.PrivateKey) (recipientSigInfo, error) { 117 if sigAlg != EdDSA { 118 return recipientSigInfo{}, ErrUnsupportedAlgorithm 119 } 120 121 if privateKey == nil { 122 return recipientSigInfo{}, errors.New("invalid private key") 123 } 124 return recipientSigInfo{ 125 sigAlg: sigAlg, 126 publicKey: staticPublicKey(&JSONWebKey{ 127 Key: privateKey.Public(), 128 }), 129 signer: &edDecrypterSigner{ 130 privateKey: privateKey, 131 }, 132 }, nil 133} 134 135// newECDHRecipient creates recipientKeyInfo based on the given key. 136func newECDHRecipient(keyAlg KeyAlgorithm, publicKey *ecdsa.PublicKey) (recipientKeyInfo, error) { 137 // Verify that key management algorithm is supported by this encrypter 138 switch keyAlg { 139 case ECDH_ES, ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW: 140 default: 141 return recipientKeyInfo{}, ErrUnsupportedAlgorithm 142 } 143 144 if publicKey == nil || !publicKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) { 145 return recipientKeyInfo{}, errors.New("invalid public key") 146 } 147 148 return recipientKeyInfo{ 149 keyAlg: keyAlg, 150 keyEncrypter: &ecEncrypterVerifier{ 151 publicKey: publicKey, 152 }, 153 }, nil 154} 155 156// newECDSASigner creates a recipientSigInfo based on the given key. 157func newECDSASigner(sigAlg SignatureAlgorithm, privateKey *ecdsa.PrivateKey) (recipientSigInfo, error) { 158 // Verify that key management algorithm is supported by this encrypter 159 switch sigAlg { 160 case ES256, ES384, ES512: 161 default: 162 return recipientSigInfo{}, ErrUnsupportedAlgorithm 163 } 164 165 if privateKey == nil { 166 return recipientSigInfo{}, errors.New("invalid private key") 167 } 168 169 return recipientSigInfo{ 170 sigAlg: sigAlg, 171 publicKey: staticPublicKey(&JSONWebKey{ 172 Key: privateKey.Public(), 173 }), 174 signer: &ecDecrypterSigner{ 175 privateKey: privateKey, 176 }, 177 }, nil 178} 179 180// Encrypt the given payload and update the object. 181func (ctx rsaEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) { 182 encryptedKey, err := ctx.encrypt(cek, alg) 183 if err != nil { 184 return recipientInfo{}, err 185 } 186 187 return recipientInfo{ 188 encryptedKey: encryptedKey, 189 header: &rawHeader{}, 190 }, nil 191} 192 193// Encrypt the given payload. Based on the key encryption algorithm, 194// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256). 195func (ctx rsaEncrypterVerifier) encrypt(cek []byte, alg KeyAlgorithm) ([]byte, error) { 196 switch alg { 197 case RSA1_5: 198 return rsa.EncryptPKCS1v15(RandReader, ctx.publicKey, cek) 199 case RSA_OAEP: 200 return rsa.EncryptOAEP(sha1.New(), RandReader, ctx.publicKey, cek, []byte{}) 201 case RSA_OAEP_256: 202 return rsa.EncryptOAEP(sha256.New(), RandReader, ctx.publicKey, cek, []byte{}) 203 } 204 205 return nil, ErrUnsupportedAlgorithm 206} 207 208// Decrypt the given payload and return the content encryption key. 209func (ctx rsaDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) { 210 return ctx.decrypt(recipient.encryptedKey, headers.getAlgorithm(), generator) 211} 212 213// Decrypt the given payload. Based on the key encryption algorithm, 214// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256). 215func (ctx rsaDecrypterSigner) decrypt(jek []byte, alg KeyAlgorithm, generator keyGenerator) ([]byte, error) { 216 // Note: The random reader on decrypt operations is only used for blinding, 217 // so stubbing is meanlingless (hence the direct use of rand.Reader). 218 switch alg { 219 case RSA1_5: 220 defer func() { 221 // DecryptPKCS1v15SessionKey sometimes panics on an invalid payload 222 // because of an index out of bounds error, which we want to ignore. 223 // This has been fixed in Go 1.3.1 (released 2014/08/13), the recover() 224 // only exists for preventing crashes with unpatched versions. 225 // See: https://groups.google.com/forum/#!topic/golang-dev/7ihX6Y6kx9k 226 // See: https://code.google.com/p/go/source/detail?r=58ee390ff31602edb66af41ed10901ec95904d33 227 _ = recover() 228 }() 229 230 // Perform some input validation. 231 keyBytes := ctx.privateKey.PublicKey.N.BitLen() / 8 232 if keyBytes != len(jek) { 233 // Input size is incorrect, the encrypted payload should always match 234 // the size of the public modulus (e.g. using a 2048 bit key will 235 // produce 256 bytes of output). Reject this since it's invalid input. 236 return nil, ErrCryptoFailure 237 } 238 239 cek, _, err := generator.genKey() 240 if err != nil { 241 return nil, ErrCryptoFailure 242 } 243 244 // When decrypting an RSA-PKCS1v1.5 payload, we must take precautions to 245 // prevent chosen-ciphertext attacks as described in RFC 3218, "Preventing 246 // the Million Message Attack on Cryptographic Message Syntax". We are 247 // therefore deliberately ignoring errors here. 248 _ = rsa.DecryptPKCS1v15SessionKey(rand.Reader, ctx.privateKey, jek, cek) 249 250 return cek, nil 251 case RSA_OAEP: 252 // Use rand.Reader for RSA blinding 253 return rsa.DecryptOAEP(sha1.New(), rand.Reader, ctx.privateKey, jek, []byte{}) 254 case RSA_OAEP_256: 255 // Use rand.Reader for RSA blinding 256 return rsa.DecryptOAEP(sha256.New(), rand.Reader, ctx.privateKey, jek, []byte{}) 257 } 258 259 return nil, ErrUnsupportedAlgorithm 260} 261 262// Sign the given payload 263func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { 264 var hash crypto.Hash 265 266 switch alg { 267 case RS256, PS256: 268 hash = crypto.SHA256 269 case RS384, PS384: 270 hash = crypto.SHA384 271 case RS512, PS512: 272 hash = crypto.SHA512 273 default: 274 return Signature{}, ErrUnsupportedAlgorithm 275 } 276 277 hasher := hash.New() 278 279 // According to documentation, Write() on hash never fails 280 _, _ = hasher.Write(payload) 281 hashed := hasher.Sum(nil) 282 283 var out []byte 284 var err error 285 286 switch alg { 287 case RS256, RS384, RS512: 288 out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed) 289 case PS256, PS384, PS512: 290 out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{ 291 SaltLength: rsa.PSSSaltLengthEqualsHash, 292 }) 293 } 294 295 if err != nil { 296 return Signature{}, err 297 } 298 299 return Signature{ 300 Signature: out, 301 protected: &rawHeader{}, 302 }, nil 303} 304 305// Verify the given payload 306func (ctx rsaEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { 307 var hash crypto.Hash 308 309 switch alg { 310 case RS256, PS256: 311 hash = crypto.SHA256 312 case RS384, PS384: 313 hash = crypto.SHA384 314 case RS512, PS512: 315 hash = crypto.SHA512 316 default: 317 return ErrUnsupportedAlgorithm 318 } 319 320 hasher := hash.New() 321 322 // According to documentation, Write() on hash never fails 323 _, _ = hasher.Write(payload) 324 hashed := hasher.Sum(nil) 325 326 switch alg { 327 case RS256, RS384, RS512: 328 return rsa.VerifyPKCS1v15(ctx.publicKey, hash, hashed, signature) 329 case PS256, PS384, PS512: 330 return rsa.VerifyPSS(ctx.publicKey, hash, hashed, signature, nil) 331 } 332 333 return ErrUnsupportedAlgorithm 334} 335 336// Encrypt the given payload and update the object. 337func (ctx ecEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) { 338 switch alg { 339 case ECDH_ES: 340 // ECDH-ES mode doesn't wrap a key, the shared secret is used directly as the key. 341 return recipientInfo{ 342 header: &rawHeader{}, 343 }, nil 344 case ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW: 345 default: 346 return recipientInfo{}, ErrUnsupportedAlgorithm 347 } 348 349 generator := ecKeyGenerator{ 350 algID: string(alg), 351 publicKey: ctx.publicKey, 352 } 353 354 switch alg { 355 case ECDH_ES_A128KW: 356 generator.size = 16 357 case ECDH_ES_A192KW: 358 generator.size = 24 359 case ECDH_ES_A256KW: 360 generator.size = 32 361 } 362 363 kek, header, err := generator.genKey() 364 if err != nil { 365 return recipientInfo{}, err 366 } 367 368 block, err := aes.NewCipher(kek) 369 if err != nil { 370 return recipientInfo{}, err 371 } 372 373 jek, err := josecipher.KeyWrap(block, cek) 374 if err != nil { 375 return recipientInfo{}, err 376 } 377 378 return recipientInfo{ 379 encryptedKey: jek, 380 header: &header, 381 }, nil 382} 383 384// Get key size for EC key generator 385func (ctx ecKeyGenerator) keySize() int { 386 return ctx.size 387} 388 389// Get a content encryption key for ECDH-ES 390func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) { 391 priv, err := ecdsa.GenerateKey(ctx.publicKey.Curve, RandReader) 392 if err != nil { 393 return nil, rawHeader{}, err 394 } 395 396 out := josecipher.DeriveECDHES(ctx.algID, []byte{}, []byte{}, priv, ctx.publicKey, ctx.size) 397 398 b, err := json.Marshal(&JSONWebKey{ 399 Key: &priv.PublicKey, 400 }) 401 if err != nil { 402 return nil, nil, err 403 } 404 405 headers := rawHeader{ 406 headerEPK: makeRawMessage(b), 407 } 408 409 return out, headers, nil 410} 411 412// Decrypt the given payload and return the content encryption key. 413func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) { 414 epk, err := headers.getEPK() 415 if err != nil { 416 return nil, errors.New("square/go-jose: invalid epk header") 417 } 418 if epk == nil { 419 return nil, errors.New("square/go-jose: missing epk header") 420 } 421 422 publicKey, ok := epk.Key.(*ecdsa.PublicKey) 423 if publicKey == nil || !ok { 424 return nil, errors.New("square/go-jose: invalid epk header") 425 } 426 427 if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) { 428 return nil, errors.New("square/go-jose: invalid public key in epk header") 429 } 430 431 apuData, err := headers.getAPU() 432 if err != nil { 433 return nil, errors.New("square/go-jose: invalid apu header") 434 } 435 apvData, err := headers.getAPV() 436 if err != nil { 437 return nil, errors.New("square/go-jose: invalid apv header") 438 } 439 440 deriveKey := func(algID string, size int) []byte { 441 return josecipher.DeriveECDHES(algID, apuData.bytes(), apvData.bytes(), ctx.privateKey, publicKey, size) 442 } 443 444 var keySize int 445 446 algorithm := headers.getAlgorithm() 447 switch algorithm { 448 case ECDH_ES: 449 // ECDH-ES uses direct key agreement, no key unwrapping necessary. 450 return deriveKey(string(headers.getEncryption()), generator.keySize()), nil 451 case ECDH_ES_A128KW: 452 keySize = 16 453 case ECDH_ES_A192KW: 454 keySize = 24 455 case ECDH_ES_A256KW: 456 keySize = 32 457 default: 458 return nil, ErrUnsupportedAlgorithm 459 } 460 461 key := deriveKey(string(algorithm), keySize) 462 block, err := aes.NewCipher(key) 463 if err != nil { 464 return nil, err 465 } 466 467 return josecipher.KeyUnwrap(block, recipient.encryptedKey) 468} 469 470func (ctx edDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { 471 if alg != EdDSA { 472 return Signature{}, ErrUnsupportedAlgorithm 473 } 474 475 sig, err := ctx.privateKey.Sign(RandReader, payload, crypto.Hash(0)) 476 if err != nil { 477 return Signature{}, err 478 } 479 480 return Signature{ 481 Signature: sig, 482 protected: &rawHeader{}, 483 }, nil 484} 485 486func (ctx edEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { 487 if alg != EdDSA { 488 return ErrUnsupportedAlgorithm 489 } 490 ok := ed25519.Verify(ctx.publicKey, payload, signature) 491 if !ok { 492 return errors.New("square/go-jose: ed25519 signature failed to verify") 493 } 494 return nil 495} 496 497// Sign the given payload 498func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { 499 var expectedBitSize int 500 var hash crypto.Hash 501 502 switch alg { 503 case ES256: 504 expectedBitSize = 256 505 hash = crypto.SHA256 506 case ES384: 507 expectedBitSize = 384 508 hash = crypto.SHA384 509 case ES512: 510 expectedBitSize = 521 511 hash = crypto.SHA512 512 } 513 514 curveBits := ctx.privateKey.Curve.Params().BitSize 515 if expectedBitSize != curveBits { 516 return Signature{}, fmt.Errorf("square/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits) 517 } 518 519 hasher := hash.New() 520 521 // According to documentation, Write() on hash never fails 522 _, _ = hasher.Write(payload) 523 hashed := hasher.Sum(nil) 524 525 r, s, err := ecdsa.Sign(RandReader, ctx.privateKey, hashed) 526 if err != nil { 527 return Signature{}, err 528 } 529 530 keyBytes := curveBits / 8 531 if curveBits%8 > 0 { 532 keyBytes++ 533 } 534 535 // We serialize the outputs (r and s) into big-endian byte arrays and pad 536 // them with zeros on the left to make sure the sizes work out. Both arrays 537 // must be keyBytes long, and the output must be 2*keyBytes long. 538 rBytes := r.Bytes() 539 rBytesPadded := make([]byte, keyBytes) 540 copy(rBytesPadded[keyBytes-len(rBytes):], rBytes) 541 542 sBytes := s.Bytes() 543 sBytesPadded := make([]byte, keyBytes) 544 copy(sBytesPadded[keyBytes-len(sBytes):], sBytes) 545 546 out := append(rBytesPadded, sBytesPadded...) 547 548 return Signature{ 549 Signature: out, 550 protected: &rawHeader{}, 551 }, nil 552} 553 554// Verify the given payload 555func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { 556 var keySize int 557 var hash crypto.Hash 558 559 switch alg { 560 case ES256: 561 keySize = 32 562 hash = crypto.SHA256 563 case ES384: 564 keySize = 48 565 hash = crypto.SHA384 566 case ES512: 567 keySize = 66 568 hash = crypto.SHA512 569 default: 570 return ErrUnsupportedAlgorithm 571 } 572 573 if len(signature) != 2*keySize { 574 return fmt.Errorf("square/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize) 575 } 576 577 hasher := hash.New() 578 579 // According to documentation, Write() on hash never fails 580 _, _ = hasher.Write(payload) 581 hashed := hasher.Sum(nil) 582 583 r := big.NewInt(0).SetBytes(signature[:keySize]) 584 s := big.NewInt(0).SetBytes(signature[keySize:]) 585 586 match := ecdsa.Verify(ctx.publicKey, hashed, r, s) 587 if !match { 588 return errors.New("square/go-jose: ecdsa signature failed to verify") 589 } 590 591 return nil 592} 593