You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

132 line
3.7 KiB

  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package pkcs12
  5. import (
  6. "bytes"
  7. "crypto/cipher"
  8. "crypto/des"
  9. "crypto/x509/pkix"
  10. "encoding/asn1"
  11. "errors"
  12. "golang.org/x/crypto/pkcs12/internal/rc2"
  13. )
  14. var (
  15. oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3})
  16. oidPBEWithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6})
  17. )
  18. // pbeCipher is an abstraction of a PKCS#12 cipher.
  19. type pbeCipher interface {
  20. // create returns a cipher.Block given a key.
  21. create(key []byte) (cipher.Block, error)
  22. // deriveKey returns a key derived from the given password and salt.
  23. deriveKey(salt, password []byte, iterations int) []byte
  24. // deriveKey returns an IV derived from the given password and salt.
  25. deriveIV(salt, password []byte, iterations int) []byte
  26. }
  27. type shaWithTripleDESCBC struct{}
  28. func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) {
  29. return des.NewTripleDESCipher(key)
  30. }
  31. func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte {
  32. return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24)
  33. }
  34. func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte {
  35. return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
  36. }
  37. type shaWith40BitRC2CBC struct{}
  38. func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) {
  39. return rc2.New(key, len(key)*8)
  40. }
  41. func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte {
  42. return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5)
  43. }
  44. func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte {
  45. return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
  46. }
  47. type pbeParams struct {
  48. Salt []byte
  49. Iterations int
  50. }
  51. func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) {
  52. var cipherType pbeCipher
  53. switch {
  54. case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC):
  55. cipherType = shaWithTripleDESCBC{}
  56. case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC):
  57. cipherType = shaWith40BitRC2CBC{}
  58. default:
  59. return nil, 0, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported")
  60. }
  61. var params pbeParams
  62. if err := unmarshal(algorithm.Parameters.FullBytes, &params); err != nil {
  63. return nil, 0, err
  64. }
  65. key := cipherType.deriveKey(params.Salt, password, params.Iterations)
  66. iv := cipherType.deriveIV(params.Salt, password, params.Iterations)
  67. block, err := cipherType.create(key)
  68. if err != nil {
  69. return nil, 0, err
  70. }
  71. return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil
  72. }
  73. func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) {
  74. cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password)
  75. if err != nil {
  76. return nil, err
  77. }
  78. encrypted := info.Data()
  79. if len(encrypted) == 0 {
  80. return nil, errors.New("pkcs12: empty encrypted data")
  81. }
  82. if len(encrypted)%blockSize != 0 {
  83. return nil, errors.New("pkcs12: input is not a multiple of the block size")
  84. }
  85. decrypted = make([]byte, len(encrypted))
  86. cbc.CryptBlocks(decrypted, encrypted)
  87. psLen := int(decrypted[len(decrypted)-1])
  88. if psLen == 0 || psLen > blockSize {
  89. return nil, ErrDecryption
  90. }
  91. if len(decrypted) < psLen {
  92. return nil, ErrDecryption
  93. }
  94. ps := decrypted[len(decrypted)-psLen:]
  95. decrypted = decrypted[:len(decrypted)-psLen]
  96. if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 {
  97. return nil, ErrDecryption
  98. }
  99. return
  100. }
  101. // decryptable abstracts an object that contains ciphertext.
  102. type decryptable interface {
  103. Algorithm() pkix.AlgorithmIdentifier
  104. Data() []byte
  105. }