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.
10 "crypto/openpgp/error"
17 // This is the largest session key that we'll support. Since no 512-bit cipher
18 // has even been seriously used, this is comfortably large.
19 const maxSessionKeySizeInBytes = 64
21 // SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
23 type SymmetricKeyEncrypted struct {
24 CipherFunc CipherFunction
26 Key []byte // Empty unless Encrypted is false.
27 s2k func(out, in []byte)
31 const symmetricKeyEncryptedVersion = 4
33 func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err os.Error) {
34 // RFC 4880, section 5.3.
36 _, err = readFull(r, buf[:])
40 if buf[0] != symmetricKeyEncryptedVersion {
41 return error.UnsupportedError("SymmetricKeyEncrypted version")
43 ske.CipherFunc = CipherFunction(buf[1])
45 if ske.CipherFunc.KeySize() == 0 {
46 return error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
49 ske.s2k, err = s2k.Parse(r)
54 encryptedKey := make([]byte, maxSessionKeySizeInBytes)
55 // The session key may follow. We just have to try and read to find
56 // out. If it exists then we limit it to maxSessionKeySizeInBytes.
57 n, err := readFull(r, encryptedKey)
58 if err != nil && err != io.ErrUnexpectedEOF {
63 if n == maxSessionKeySizeInBytes {
64 return error.UnsupportedError("oversized encrypted session key")
66 ske.encryptedKey = encryptedKey[:n]
74 // Decrypt attempts to decrypt an encrypted session key. If it returns nil,
75 // ske.Key will contain the session key.
76 func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) os.Error {
81 key := make([]byte, ske.CipherFunc.KeySize())
82 ske.s2k(key, passphrase)
84 if len(ske.encryptedKey) == 0 {
87 // the IV is all zeros
88 iv := make([]byte, ske.CipherFunc.blockSize())
89 c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
90 c.XORKeyStream(ske.encryptedKey, ske.encryptedKey)
91 ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
92 if ske.CipherFunc.blockSize() == 0 {
93 return error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(ske.CipherFunc)))
95 ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
96 ske.Key = ske.encryptedKey[1:]
97 if len(ske.Key)%ske.CipherFunc.blockSize() != 0 {
99 return error.StructuralError("length of decrypted key not a multiple of block size")
103 ske.Encrypted = false
107 // SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
108 // packet contains a random session key, encrypted by a key derived from the
109 // given passphrase. The session key is returned and must be passed to
110 // SerializeSymmetricallyEncrypted.
111 func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []byte, cipherFunc CipherFunction) (key []byte, err os.Error) {
112 keySize := cipherFunc.KeySize()
114 return nil, error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
117 s2kBuf := new(bytes.Buffer)
118 keyEncryptingKey := make([]byte, keySize)
119 // s2k.Serialize salts and stretches the passphrase, and writes the
120 // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
121 err = s2k.Serialize(s2kBuf, keyEncryptingKey, rand, passphrase)
125 s2kBytes := s2kBuf.Bytes()
127 packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
128 err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
134 buf[0] = symmetricKeyEncryptedVersion
135 buf[1] = byte(cipherFunc)
136 _, err = w.Write(buf[:])
140 _, err = w.Write(s2kBytes)
145 sessionKey := make([]byte, keySize)
146 _, err = io.ReadFull(rand, sessionKey)
150 iv := make([]byte, cipherFunc.blockSize())
151 c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
152 encryptedCipherAndKey := make([]byte, keySize+1)
153 c.XORKeyStream(encryptedCipherAndKey, buf[1:])
154 c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
155 _, err = w.Write(encryptedCipherAndKey)