symmetric_key_encrypted.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. "code.google.com/p/go.crypto/openpgp/errors"
  8. "code.google.com/p/go.crypto/openpgp/s2k"
  9. "crypto/cipher"
  10. "io"
  11. "strconv"
  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. func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []byte, cipherFunc CipherFunction) (key []byte, err error) {
  95. keySize := cipherFunc.KeySize()
  96. if keySize == 0 {
  97. return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
  98. }
  99. s2kBuf := new(bytes.Buffer)
  100. keyEncryptingKey := make([]byte, keySize)
  101. // s2k.Serialize salts and stretches the passphrase, and writes the
  102. // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
  103. err = s2k.Serialize(s2kBuf, keyEncryptingKey, rand, passphrase)
  104. if err != nil {
  105. return
  106. }
  107. s2kBytes := s2kBuf.Bytes()
  108. packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
  109. err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
  110. if err != nil {
  111. return
  112. }
  113. var buf [2]byte
  114. buf[0] = symmetricKeyEncryptedVersion
  115. buf[1] = byte(cipherFunc)
  116. _, err = w.Write(buf[:])
  117. if err != nil {
  118. return
  119. }
  120. _, err = w.Write(s2kBytes)
  121. if err != nil {
  122. return
  123. }
  124. sessionKey := make([]byte, keySize)
  125. _, err = io.ReadFull(rand, sessionKey)
  126. if err != nil {
  127. return
  128. }
  129. iv := make([]byte, cipherFunc.blockSize())
  130. c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
  131. encryptedCipherAndKey := make([]byte, keySize+1)
  132. c.XORKeyStream(encryptedCipherAndKey, buf[1:])
  133. c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
  134. _, err = w.Write(encryptedCipherAndKey)
  135. if err != nil {
  136. return
  137. }
  138. key = sessionKey
  139. return
  140. }