github.com/lestrrat-go/jwx/v2@v2.0.21/jwe/internal/keyenc/keyenc.go (about) 1 package keyenc 2 3 import ( 4 "crypto" 5 "crypto/aes" 6 "crypto/cipher" 7 "crypto/ecdsa" 8 "crypto/rand" 9 "crypto/rsa" 10 "crypto/sha1" 11 "crypto/sha256" 12 "crypto/sha512" 13 "crypto/subtle" 14 "encoding/binary" 15 "fmt" 16 "hash" 17 "io" 18 19 "golang.org/x/crypto/curve25519" 20 "golang.org/x/crypto/pbkdf2" 21 22 "github.com/lestrrat-go/jwx/v2/internal/ecutil" 23 "github.com/lestrrat-go/jwx/v2/jwa" 24 contentcipher "github.com/lestrrat-go/jwx/v2/jwe/internal/cipher" 25 "github.com/lestrrat-go/jwx/v2/jwe/internal/concatkdf" 26 "github.com/lestrrat-go/jwx/v2/jwe/internal/keygen" 27 "github.com/lestrrat-go/jwx/v2/x25519" 28 ) 29 30 func NewNoop(alg jwa.KeyEncryptionAlgorithm, sharedkey []byte) (*Noop, error) { 31 return &Noop{ 32 alg: alg, 33 sharedkey: sharedkey, 34 }, nil 35 } 36 37 func (kw *Noop) Algorithm() jwa.KeyEncryptionAlgorithm { 38 return kw.alg 39 } 40 41 func (kw *Noop) SetKeyID(v string) { 42 kw.keyID = v 43 } 44 45 func (kw *Noop) KeyID() string { 46 return kw.keyID 47 } 48 49 func (kw *Noop) EncryptKey(_ []byte) (keygen.ByteSource, error) { 50 return keygen.ByteKey(kw.sharedkey), nil 51 } 52 53 // NewAES creates a key-wrap encrypter using AES. 54 // Although the name suggests otherwise, this does the decryption as well. 55 func NewAES(alg jwa.KeyEncryptionAlgorithm, sharedkey []byte) (*AES, error) { 56 return &AES{ 57 alg: alg, 58 sharedkey: sharedkey, 59 }, nil 60 } 61 62 // Algorithm returns the key encryption algorithm being used 63 func (kw *AES) Algorithm() jwa.KeyEncryptionAlgorithm { 64 return kw.alg 65 } 66 67 func (kw *AES) SetKeyID(v string) { 68 kw.keyID = v 69 } 70 71 // KeyID returns the key ID associated with this encrypter 72 func (kw *AES) KeyID() string { 73 return kw.keyID 74 } 75 76 // Decrypt decrypts the encrypted key using AES key unwrap 77 func (kw *AES) Decrypt(enckey []byte) ([]byte, error) { 78 block, err := aes.NewCipher(kw.sharedkey) 79 if err != nil { 80 return nil, fmt.Errorf(`failed to create cipher from shared key: %w`, err) 81 } 82 83 cek, err := Unwrap(block, enckey) 84 if err != nil { 85 return nil, fmt.Errorf(`failed to unwrap data: %w`, err) 86 } 87 return cek, nil 88 } 89 90 // KeyEncrypt encrypts the given content encryption key 91 func (kw *AES) EncryptKey(cek []byte) (keygen.ByteSource, error) { 92 block, err := aes.NewCipher(kw.sharedkey) 93 if err != nil { 94 return nil, fmt.Errorf(`failed to create cipher from shared key: %w`, err) 95 } 96 encrypted, err := Wrap(block, cek) 97 if err != nil { 98 return nil, fmt.Errorf(`keywrap: failed to wrap key: %w`, err) 99 } 100 return keygen.ByteKey(encrypted), nil 101 } 102 103 func NewAESGCMEncrypt(alg jwa.KeyEncryptionAlgorithm, sharedkey []byte) (*AESGCMEncrypt, error) { 104 return &AESGCMEncrypt{ 105 algorithm: alg, 106 sharedkey: sharedkey, 107 }, nil 108 } 109 110 func (kw AESGCMEncrypt) Algorithm() jwa.KeyEncryptionAlgorithm { 111 return kw.algorithm 112 } 113 114 func (kw *AESGCMEncrypt) SetKeyID(v string) { 115 kw.keyID = v 116 } 117 118 func (kw AESGCMEncrypt) KeyID() string { 119 return kw.keyID 120 } 121 122 func (kw AESGCMEncrypt) EncryptKey(cek []byte) (keygen.ByteSource, error) { 123 block, err := aes.NewCipher(kw.sharedkey) 124 if err != nil { 125 return nil, fmt.Errorf(`failed to create cipher from shared key: %w`, err) 126 } 127 aesgcm, err := cipher.NewGCM(block) 128 if err != nil { 129 return nil, fmt.Errorf(`failed to create gcm from cipher: %w`, err) 130 } 131 132 iv := make([]byte, aesgcm.NonceSize()) 133 _, err = io.ReadFull(rand.Reader, iv) 134 if err != nil { 135 return nil, fmt.Errorf(`failed to get random iv: %w`, err) 136 } 137 138 encrypted := aesgcm.Seal(nil, iv, cek, nil) 139 tag := encrypted[len(encrypted)-aesgcm.Overhead():] 140 ciphertext := encrypted[:len(encrypted)-aesgcm.Overhead()] 141 return keygen.ByteWithIVAndTag{ 142 ByteKey: ciphertext, 143 IV: iv, 144 Tag: tag, 145 }, nil 146 } 147 148 func NewPBES2Encrypt(alg jwa.KeyEncryptionAlgorithm, password []byte) (*PBES2Encrypt, error) { 149 var hashFunc func() hash.Hash 150 var keylen int 151 switch alg { 152 case jwa.PBES2_HS256_A128KW: 153 hashFunc = sha256.New 154 keylen = 16 155 case jwa.PBES2_HS384_A192KW: 156 hashFunc = sha512.New384 157 keylen = 24 158 case jwa.PBES2_HS512_A256KW: 159 hashFunc = sha512.New 160 keylen = 32 161 default: 162 return nil, fmt.Errorf("unexpected key encryption algorithm %s", alg) 163 } 164 return &PBES2Encrypt{ 165 algorithm: alg, 166 password: password, 167 hashFunc: hashFunc, 168 keylen: keylen, 169 }, nil 170 } 171 172 func (kw PBES2Encrypt) Algorithm() jwa.KeyEncryptionAlgorithm { 173 return kw.algorithm 174 } 175 176 func (kw *PBES2Encrypt) SetKeyID(v string) { 177 kw.keyID = v 178 } 179 180 func (kw PBES2Encrypt) KeyID() string { 181 return kw.keyID 182 } 183 184 func (kw PBES2Encrypt) EncryptKey(cek []byte) (keygen.ByteSource, error) { 185 count := 10000 186 salt := make([]byte, kw.keylen) 187 _, err := io.ReadFull(rand.Reader, salt) 188 if err != nil { 189 return nil, fmt.Errorf(`failed to get random salt: %w`, err) 190 } 191 192 fullsalt := []byte(kw.algorithm) 193 fullsalt = append(fullsalt, byte(0)) 194 fullsalt = append(fullsalt, salt...) 195 sharedkey := pbkdf2.Key(kw.password, fullsalt, count, kw.keylen, kw.hashFunc) 196 197 block, err := aes.NewCipher(sharedkey) 198 if err != nil { 199 return nil, fmt.Errorf(`failed to create cipher from shared key: %w`, err) 200 } 201 encrypted, err := Wrap(block, cek) 202 if err != nil { 203 return nil, fmt.Errorf(`keywrap: failed to wrap key: %w`, err) 204 } 205 return keygen.ByteWithSaltAndCount{ 206 ByteKey: encrypted, 207 Salt: salt, 208 Count: count, 209 }, nil 210 } 211 212 // NewECDHESEncrypt creates a new key encrypter based on ECDH-ES 213 func NewECDHESEncrypt(alg jwa.KeyEncryptionAlgorithm, enc jwa.ContentEncryptionAlgorithm, keysize int, keyif interface{}, apu, apv []byte) (*ECDHESEncrypt, error) { 214 var generator keygen.Generator 215 var err error 216 switch key := keyif.(type) { 217 case *ecdsa.PublicKey: 218 generator, err = keygen.NewEcdhes(alg, enc, keysize, key, apu, apv) 219 case x25519.PublicKey: 220 generator, err = keygen.NewX25519(alg, enc, keysize, key) 221 default: 222 return nil, fmt.Errorf("unexpected key type %T", keyif) 223 } 224 if err != nil { 225 return nil, fmt.Errorf(`failed to create key generator: %w`, err) 226 } 227 return &ECDHESEncrypt{ 228 algorithm: alg, 229 generator: generator, 230 }, nil 231 } 232 233 // Algorithm returns the key encryption algorithm being used 234 func (kw ECDHESEncrypt) Algorithm() jwa.KeyEncryptionAlgorithm { 235 return kw.algorithm 236 } 237 238 func (kw *ECDHESEncrypt) SetKeyID(v string) { 239 kw.keyID = v 240 } 241 242 // KeyID returns the key ID associated with this encrypter 243 func (kw ECDHESEncrypt) KeyID() string { 244 return kw.keyID 245 } 246 247 // KeyEncrypt encrypts the content encryption key using ECDH-ES 248 func (kw ECDHESEncrypt) EncryptKey(cek []byte) (keygen.ByteSource, error) { 249 kg, err := kw.generator.Generate() 250 if err != nil { 251 return nil, fmt.Errorf(`failed to create key generator: %w`, err) 252 } 253 254 bwpk, ok := kg.(keygen.ByteWithECPublicKey) 255 if !ok { 256 return nil, fmt.Errorf(`key generator generated invalid key (expected ByteWithECPrivateKey)`) 257 } 258 259 if kw.algorithm == jwa.ECDH_ES { 260 return bwpk, nil 261 } 262 263 block, err := aes.NewCipher(bwpk.Bytes()) 264 if err != nil { 265 return nil, fmt.Errorf(`failed to generate cipher from generated key: %w`, err) 266 } 267 268 jek, err := Wrap(block, cek) 269 if err != nil { 270 return nil, fmt.Errorf(`failed to wrap data: %w`, err) 271 } 272 273 bwpk.ByteKey = keygen.ByteKey(jek) 274 275 return bwpk, nil 276 } 277 278 // NewECDHESDecrypt creates a new key decrypter using ECDH-ES 279 func NewECDHESDecrypt(keyalg jwa.KeyEncryptionAlgorithm, contentalg jwa.ContentEncryptionAlgorithm, pubkey interface{}, apu, apv []byte, privkey interface{}) *ECDHESDecrypt { 280 return &ECDHESDecrypt{ 281 keyalg: keyalg, 282 contentalg: contentalg, 283 apu: apu, 284 apv: apv, 285 privkey: privkey, 286 pubkey: pubkey, 287 } 288 } 289 290 // Algorithm returns the key encryption algorithm being used 291 func (kw ECDHESDecrypt) Algorithm() jwa.KeyEncryptionAlgorithm { 292 return kw.keyalg 293 } 294 295 func DeriveZ(privkeyif interface{}, pubkeyif interface{}) ([]byte, error) { 296 switch privkeyif.(type) { 297 case x25519.PrivateKey: 298 privkey, ok := privkeyif.(x25519.PrivateKey) 299 if !ok { 300 return nil, fmt.Errorf(`private key must be x25519.PrivateKey, was: %T`, privkeyif) 301 } 302 pubkey, ok := pubkeyif.(x25519.PublicKey) 303 if !ok { 304 return nil, fmt.Errorf(`public key must be x25519.PublicKey, was: %T`, pubkeyif) 305 } 306 return curve25519.X25519(privkey.Seed(), pubkey) 307 default: 308 privkey, ok := privkeyif.(*ecdsa.PrivateKey) 309 if !ok { 310 return nil, fmt.Errorf(`private key must be *ecdsa.PrivateKey, was: %T`, privkeyif) 311 } 312 pubkey, ok := pubkeyif.(*ecdsa.PublicKey) 313 if !ok { 314 return nil, fmt.Errorf(`public key must be *ecdsa.PublicKey, was: %T`, pubkeyif) 315 } 316 if !privkey.PublicKey.Curve.IsOnCurve(pubkey.X, pubkey.Y) { 317 return nil, fmt.Errorf(`public key must be on the same curve as private key`) 318 } 319 320 z, _ := privkey.PublicKey.Curve.ScalarMult(pubkey.X, pubkey.Y, privkey.D.Bytes()) 321 zBytes := ecutil.AllocECPointBuffer(z, privkey.Curve) 322 defer ecutil.ReleaseECPointBuffer(zBytes) 323 zCopy := make([]byte, len(zBytes)) 324 copy(zCopy, zBytes) 325 return zCopy, nil 326 } 327 } 328 329 func DeriveECDHES(alg, apu, apv []byte, privkey interface{}, pubkey interface{}, keysize uint32) ([]byte, error) { 330 pubinfo := make([]byte, 4) 331 binary.BigEndian.PutUint32(pubinfo, keysize*8) 332 zBytes, err := DeriveZ(privkey, pubkey) 333 if err != nil { 334 return nil, fmt.Errorf(`unable to determine Z: %w`, err) 335 } 336 kdf := concatkdf.New(crypto.SHA256, alg, zBytes, apu, apv, pubinfo, []byte{}) 337 key := make([]byte, keysize) 338 if _, err := kdf.Read(key); err != nil { 339 return nil, fmt.Errorf(`failed to read kdf: %w`, err) 340 } 341 342 return key, nil 343 } 344 345 // Decrypt decrypts the encrypted key using ECDH-ES 346 func (kw ECDHESDecrypt) Decrypt(enckey []byte) ([]byte, error) { 347 var algBytes []byte 348 var keysize uint32 349 350 // Use keyalg except for when jwa.ECDH_ES 351 algBytes = []byte(kw.keyalg.String()) 352 353 switch kw.keyalg { 354 case jwa.ECDH_ES: 355 // Create a content cipher from the content encryption algorithm 356 c, err := contentcipher.NewAES(kw.contentalg) 357 if err != nil { 358 return nil, fmt.Errorf(`failed to create content cipher for %s: %w`, kw.contentalg, err) 359 } 360 keysize = uint32(c.KeySize()) 361 algBytes = []byte(kw.contentalg.String()) 362 case jwa.ECDH_ES_A128KW: 363 keysize = 16 364 case jwa.ECDH_ES_A192KW: 365 keysize = 24 366 case jwa.ECDH_ES_A256KW: 367 keysize = 32 368 default: 369 return nil, fmt.Errorf("invalid ECDH-ES key wrap algorithm (%s)", kw.keyalg) 370 } 371 372 key, err := DeriveECDHES(algBytes, kw.apu, kw.apv, kw.privkey, kw.pubkey, keysize) 373 if err != nil { 374 return nil, fmt.Errorf(`failed to derive ECDHES encryption key: %w`, err) 375 } 376 377 // ECDH-ES does not wrap keys 378 if kw.keyalg == jwa.ECDH_ES { 379 return key, nil 380 } 381 382 block, err := aes.NewCipher(key) 383 if err != nil { 384 return nil, fmt.Errorf(`failed to create cipher for ECDH-ES key wrap: %w`, err) 385 } 386 387 return Unwrap(block, enckey) 388 } 389 390 // NewRSAOAEPEncrypt creates a new key encrypter using RSA OAEP 391 func NewRSAOAEPEncrypt(alg jwa.KeyEncryptionAlgorithm, pubkey *rsa.PublicKey) (*RSAOAEPEncrypt, error) { 392 switch alg { 393 case jwa.RSA_OAEP, jwa.RSA_OAEP_256: 394 default: 395 return nil, fmt.Errorf("invalid RSA OAEP encrypt algorithm (%s)", alg) 396 } 397 return &RSAOAEPEncrypt{ 398 alg: alg, 399 pubkey: pubkey, 400 }, nil 401 } 402 403 // NewRSAPKCSEncrypt creates a new key encrypter using PKCS1v15 404 func NewRSAPKCSEncrypt(alg jwa.KeyEncryptionAlgorithm, pubkey *rsa.PublicKey) (*RSAPKCSEncrypt, error) { 405 switch alg { 406 case jwa.RSA1_5: 407 default: 408 return nil, fmt.Errorf("invalid RSA PKCS encrypt algorithm (%s)", alg) 409 } 410 411 return &RSAPKCSEncrypt{ 412 alg: alg, 413 pubkey: pubkey, 414 }, nil 415 } 416 417 // Algorithm returns the key encryption algorithm being used 418 func (e RSAPKCSEncrypt) Algorithm() jwa.KeyEncryptionAlgorithm { 419 return e.alg 420 } 421 422 func (e *RSAPKCSEncrypt) SetKeyID(v string) { 423 e.keyID = v 424 } 425 426 // KeyID returns the key ID associated with this encrypter 427 func (e RSAPKCSEncrypt) KeyID() string { 428 return e.keyID 429 } 430 431 // Algorithm returns the key encryption algorithm being used 432 func (e RSAOAEPEncrypt) Algorithm() jwa.KeyEncryptionAlgorithm { 433 return e.alg 434 } 435 436 func (e *RSAOAEPEncrypt) SetKeyID(v string) { 437 e.keyID = v 438 } 439 440 // KeyID returns the key ID associated with this encrypter 441 func (e RSAOAEPEncrypt) KeyID() string { 442 return e.keyID 443 } 444 445 // KeyEncrypt encrypts the content encryption key using RSA PKCS1v15 446 func (e RSAPKCSEncrypt) EncryptKey(cek []byte) (keygen.ByteSource, error) { 447 if e.alg != jwa.RSA1_5 { 448 return nil, fmt.Errorf("invalid RSA PKCS encrypt algorithm (%s)", e.alg) 449 } 450 encrypted, err := rsa.EncryptPKCS1v15(rand.Reader, e.pubkey, cek) 451 if err != nil { 452 return nil, fmt.Errorf(`failed to encrypt using PKCS1v15: %w`, err) 453 } 454 return keygen.ByteKey(encrypted), nil 455 } 456 457 // KeyEncrypt encrypts the content encryption key using RSA OAEP 458 func (e RSAOAEPEncrypt) EncryptKey(cek []byte) (keygen.ByteSource, error) { 459 var hash hash.Hash 460 switch e.alg { 461 case jwa.RSA_OAEP: 462 hash = sha1.New() 463 case jwa.RSA_OAEP_256: 464 hash = sha256.New() 465 default: 466 return nil, fmt.Errorf(`failed to generate key encrypter for RSA-OAEP: RSA_OAEP/RSA_OAEP_256 required`) 467 } 468 encrypted, err := rsa.EncryptOAEP(hash, rand.Reader, e.pubkey, cek, []byte{}) 469 if err != nil { 470 return nil, fmt.Errorf(`failed to OAEP encrypt: %w`, err) 471 } 472 return keygen.ByteKey(encrypted), nil 473 } 474 475 // NewRSAPKCS15Decrypt creates a new decrypter using RSA PKCS1v15 476 func NewRSAPKCS15Decrypt(alg jwa.KeyEncryptionAlgorithm, privkey *rsa.PrivateKey, keysize int) *RSAPKCS15Decrypt { 477 generator := keygen.NewRandom(keysize * 2) 478 return &RSAPKCS15Decrypt{ 479 alg: alg, 480 privkey: privkey, 481 generator: generator, 482 } 483 } 484 485 // Algorithm returns the key encryption algorithm being used 486 func (d RSAPKCS15Decrypt) Algorithm() jwa.KeyEncryptionAlgorithm { 487 return d.alg 488 } 489 490 // Decrypt decrypts the encrypted key using RSA PKCS1v1.5 491 func (d RSAPKCS15Decrypt) Decrypt(enckey []byte) ([]byte, error) { 492 // Hey, these notes and workarounds were stolen from go-jose 493 defer func() { 494 // DecryptPKCS1v15SessionKey sometimes panics on an invalid payload 495 // because of an index out of bounds error, which we want to ignore. 496 // This has been fixed in Go 1.3.1 (released 2014/08/13), the recover() 497 // only exists for preventing crashes with unpatched versions. 498 // See: https://groups.google.com/forum/#!topic/golang-dev/7ihX6Y6kx9k 499 // See: https://code.google.com/p/go/source/detail?r=58ee390ff31602edb66af41ed10901ec95904d33 500 _ = recover() 501 }() 502 503 // Perform some input validation. 504 expectedlen := d.privkey.PublicKey.N.BitLen() / 8 505 if expectedlen != len(enckey) { 506 // Input size is incorrect, the encrypted payload should always match 507 // the size of the public modulus (e.g. using a 2048 bit key will 508 // produce 256 bytes of output). Reject this since it's invalid input. 509 return nil, fmt.Errorf( 510 "input size for key decrypt is incorrect (expected %d, got %d)", 511 expectedlen, 512 len(enckey), 513 ) 514 } 515 516 var err error 517 518 bk, err := d.generator.Generate() 519 if err != nil { 520 return nil, fmt.Errorf(`failed to generate key`) 521 } 522 cek := bk.Bytes() 523 524 // When decrypting an RSA-PKCS1v1.5 payload, we must take precautions to 525 // prevent chosen-ciphertext attacks as described in RFC 3218, "Preventing 526 // the Million Message Attack on Cryptographic Message Syntax". We are 527 // therefore deliberately ignoring errors here. 528 err = rsa.DecryptPKCS1v15SessionKey(rand.Reader, d.privkey, enckey, cek) 529 if err != nil { 530 return nil, fmt.Errorf(`failed to decrypt via PKCS1v15: %w`, err) 531 } 532 533 return cek, nil 534 } 535 536 // NewRSAOAEPDecrypt creates a new key decrypter using RSA OAEP 537 func NewRSAOAEPDecrypt(alg jwa.KeyEncryptionAlgorithm, privkey *rsa.PrivateKey) (*RSAOAEPDecrypt, error) { 538 switch alg { 539 case jwa.RSA_OAEP, jwa.RSA_OAEP_256: 540 default: 541 return nil, fmt.Errorf("invalid RSA OAEP decrypt algorithm (%s)", alg) 542 } 543 544 return &RSAOAEPDecrypt{ 545 alg: alg, 546 privkey: privkey, 547 }, nil 548 } 549 550 // Algorithm returns the key encryption algorithm being used 551 func (d RSAOAEPDecrypt) Algorithm() jwa.KeyEncryptionAlgorithm { 552 return d.alg 553 } 554 555 // Decrypt decrypts the encrypted key using RSA OAEP 556 func (d RSAOAEPDecrypt) Decrypt(enckey []byte) ([]byte, error) { 557 var hash hash.Hash 558 switch d.alg { 559 case jwa.RSA_OAEP: 560 hash = sha1.New() 561 case jwa.RSA_OAEP_256: 562 hash = sha256.New() 563 default: 564 return nil, fmt.Errorf(`failed to generate key encrypter for RSA-OAEP: RSA_OAEP/RSA_OAEP_256 required`) 565 } 566 return rsa.DecryptOAEP(hash, rand.Reader, d.privkey, enckey, []byte{}) 567 } 568 569 // Decrypt for DirectDecrypt does not do anything other than 570 // return a copy of the embedded key 571 func (d DirectDecrypt) Decrypt() ([]byte, error) { 572 cek := make([]byte, len(d.Key)) 573 copy(cek, d.Key) 574 return cek, nil 575 } 576 577 var keywrapDefaultIV = []byte{0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6} 578 579 const keywrapChunkLen = 8 580 581 func Wrap(kek cipher.Block, cek []byte) ([]byte, error) { 582 if len(cek)%8 != 0 { 583 return nil, fmt.Errorf(`keywrap input must be 8 byte blocks`) 584 } 585 586 n := len(cek) / keywrapChunkLen 587 r := make([][]byte, n) 588 589 for i := 0; i < n; i++ { 590 r[i] = make([]byte, keywrapChunkLen) 591 copy(r[i], cek[i*keywrapChunkLen:]) 592 } 593 594 buffer := make([]byte, keywrapChunkLen*2) 595 tBytes := make([]byte, keywrapChunkLen) 596 copy(buffer, keywrapDefaultIV) 597 598 for t := 0; t < 6*n; t++ { 599 copy(buffer[keywrapChunkLen:], r[t%n]) 600 601 kek.Encrypt(buffer, buffer) 602 603 binary.BigEndian.PutUint64(tBytes, uint64(t+1)) 604 605 for i := 0; i < keywrapChunkLen; i++ { 606 buffer[i] = buffer[i] ^ tBytes[i] 607 } 608 copy(r[t%n], buffer[keywrapChunkLen:]) 609 } 610 611 out := make([]byte, (n+1)*keywrapChunkLen) 612 copy(out, buffer[:keywrapChunkLen]) 613 for i := range r { 614 copy(out[(i+1)*8:], r[i]) 615 } 616 617 return out, nil 618 } 619 620 func Unwrap(block cipher.Block, ciphertxt []byte) ([]byte, error) { 621 if len(ciphertxt)%keywrapChunkLen != 0 { 622 return nil, fmt.Errorf(`keyunwrap input must be %d byte blocks`, keywrapChunkLen) 623 } 624 625 n := (len(ciphertxt) / keywrapChunkLen) - 1 626 r := make([][]byte, n) 627 628 for i := range r { 629 r[i] = make([]byte, keywrapChunkLen) 630 copy(r[i], ciphertxt[(i+1)*keywrapChunkLen:]) 631 } 632 633 buffer := make([]byte, keywrapChunkLen*2) 634 tBytes := make([]byte, keywrapChunkLen) 635 copy(buffer[:keywrapChunkLen], ciphertxt[:keywrapChunkLen]) 636 637 for t := 6*n - 1; t >= 0; t-- { 638 binary.BigEndian.PutUint64(tBytes, uint64(t+1)) 639 640 for i := 0; i < keywrapChunkLen; i++ { 641 buffer[i] = buffer[i] ^ tBytes[i] 642 } 643 copy(buffer[keywrapChunkLen:], r[t%n]) 644 645 block.Decrypt(buffer, buffer) 646 647 copy(r[t%n], buffer[keywrapChunkLen:]) 648 } 649 650 if subtle.ConstantTimeCompare(buffer[:keywrapChunkLen], keywrapDefaultIV) == 0 { 651 return nil, fmt.Errorf(`key unwrap: failed to unwrap key`) 652 } 653 654 out := make([]byte, n*keywrapChunkLen) 655 for i := range r { 656 copy(out[i*keywrapChunkLen:], r[i]) 657 } 658 659 return out, nil 660 }