symmetric_key_encrypted.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright 2011 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 packet
  5. import (
  6. "bytes"
  7. "crypto/cipher"
  8. "io"
  9. "strconv"
  10. "golang.org/x/crypto/openpgp/errors"
  11. "golang.org/x/crypto/openpgp/s2k"
  12. )
  13. // This is the largest session key that we'll support. Since no 512-bit cipher
  14. // has even been seriously used, this is comfortably large.
  15. const maxSessionKeySizeInBytes = 64
  16. // SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
  17. // 4880, section 5.3.
  18. type SymmetricKeyEncrypted struct {
  19. CipherFunc CipherFunction
  20. Encrypted bool
  21. Key []byte // Empty unless Encrypted is false.
  22. s2k func(out, in []byte)
  23. encryptedKey []byte
  24. }
  25. const symmetricKeyEncryptedVersion = 4
  26. func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err error) {
  27. // RFC 4880, section 5.3.
  28. var buf [2]byte
  29. _, err = readFull(r, buf[:])
  30. if err != nil {
  31. return
  32. }
  33. if buf[0] != symmetricKeyEncryptedVersion {
  34. return errors.UnsupportedError("SymmetricKeyEncrypted version")
  35. }
  36. ske.CipherFunc = CipherFunction(buf[1])
  37. if ske.CipherFunc.KeySize() == 0 {
  38. return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
  39. }
  40. ske.s2k, err = s2k.Parse(r)
  41. if err != nil {
  42. return
  43. }
  44. encryptedKey := make([]byte, maxSessionKeySizeInBytes)
  45. // The session key may follow. We just have to try and read to find
  46. // out. If it exists then we limit it to maxSessionKeySizeInBytes.
  47. n, err := readFull(r, encryptedKey)
  48. if err != nil && err != io.ErrUnexpectedEOF {
  49. return
  50. }
  51. err = nil
  52. if n != 0 {
  53. if n == maxSessionKeySizeInBytes {
  54. return errors.UnsupportedError("oversized encrypted session key")
  55. }
  56. ske.encryptedKey = encryptedKey[:n]
  57. }
  58. ske.Encrypted = true
  59. return
  60. }
  61. // Decrypt attempts to decrypt an encrypted session key. If it returns nil,
  62. // ske.Key will contain the session key.
  63. func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) error {
  64. if !ske.Encrypted {
  65. return nil
  66. }
  67. key := make([]byte, ske.CipherFunc.KeySize())
  68. ske.s2k(key, passphrase)
  69. if len(ske.encryptedKey) == 0 {
  70. ske.Key = key
  71. } else {
  72. // the IV is all zeros
  73. iv := make([]byte, ske.CipherFunc.blockSize())
  74. c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
  75. c.XORKeyStream(ske.encryptedKey, ske.encryptedKey)
  76. ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
  77. if ske.CipherFunc.blockSize() == 0 {
  78. return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(ske.CipherFunc)))
  79. }
  80. ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
  81. ske.Key = ske.encryptedKey[1:]
  82. if len(ske.Key)%ske.CipherFunc.blockSize() != 0 {
  83. ske.Key = nil
  84. return errors.StructuralError("length of decrypted key not a multiple of block size")
  85. }
  86. }
  87. ske.Encrypted = false
  88. return nil
  89. }
  90. // SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
  91. // packet contains a random session key, encrypted by a key derived from the
  92. // given passphrase. The session key is returned and must be passed to
  93. // SerializeSymmetricallyEncrypted.
  94. // If config is nil, sensible defaults will be used.
  95. func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
  96. cipherFunc := config.Cipher()
  97. keySize := cipherFunc.KeySize()
  98. if keySize == 0 {
  99. return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
  100. }
  101. s2kBuf := new(bytes.Buffer)
  102. keyEncryptingKey := make([]byte, keySize)
  103. // s2k.Serialize salts and stretches the passphrase, and writes the
  104. // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
  105. err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()})
  106. if err != nil {
  107. return
  108. }
  109. s2kBytes := s2kBuf.Bytes()
  110. packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
  111. err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
  112. if err != nil {
  113. return
  114. }
  115. var buf [2]byte
  116. buf[0] = symmetricKeyEncryptedVersion
  117. buf[1] = byte(cipherFunc)
  118. _, err = w.Write(buf[:])
  119. if err != nil {
  120. return
  121. }
  122. _, err = w.Write(s2kBytes)
  123. if err != nil {
  124. return
  125. }
  126. sessionKey := make([]byte, keySize)
  127. _, err = io.ReadFull(config.Random(), sessionKey)
  128. if err != nil {
  129. return
  130. }
  131. iv := make([]byte, cipherFunc.blockSize())
  132. c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
  133. encryptedCipherAndKey := make([]byte, keySize+1)
  134. c.XORKeyStream(encryptedCipherAndKey, buf[1:])
  135. c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
  136. _, err = w.Write(encryptedCipherAndKey)
  137. if err != nil {
  138. return
  139. }
  140. key = sessionKey
  141. return
  142. }