Copyright 2011 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package packet

import (
	
	
	
	

	
	
)
This is the largest session key that we'll support. Since no 512-bit cipher has even been seriously used, this is comfortably large.
SymmetricKeyEncrypted represents a passphrase protected session key. See RFC 4880, section 5.3.
RFC 4880, section 5.3.
	var  [2]byte
	if ,  := readFull(, [:]);  != nil {
		return 
	}
	if [0] != symmetricKeyEncryptedVersion {
		return errors.UnsupportedError("SymmetricKeyEncrypted version")
	}
	.CipherFunc = CipherFunction([1])

	if .CipherFunc.KeySize() == 0 {
		return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int([1])))
	}

	var  error
	.s2k,  = s2k.Parse()
	if  != nil {
		return 
	}

The session key may follow. We just have to try and read to find out. If it exists then we limit it to maxSessionKeySizeInBytes.
	,  := readFull(, )
	if  != nil &&  != io.ErrUnexpectedEOF {
		return 
	}

	if  != 0 {
		if  == maxSessionKeySizeInBytes {
			return errors.UnsupportedError("oversized encrypted session key")
		}
		.encryptedKey = [:]
	}

	return nil
}
Decrypt attempts to decrypt an encrypted session key and returns the key and the cipher to use when decrypting a subsequent Symmetrically Encrypted Data packet.
func ( *SymmetricKeyEncrypted) ( []byte) ([]byte, CipherFunction, error) {
	 := make([]byte, .CipherFunc.KeySize())
	.s2k(, )

	if len(.encryptedKey) == 0 {
		return , .CipherFunc, nil
	}
the IV is all zeros
	 := make([]byte, .CipherFunc.blockSize())
	 := cipher.NewCFBDecrypter(.CipherFunc.new(), )
	 := make([]byte, len(.encryptedKey))
	.XORKeyStream(, .encryptedKey)
	 := CipherFunction([0])
	if .blockSize() == 0 {
		return nil, .CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int()))
	}
	 = [1:]
	if ,  := len(), .KeySize();  != .KeySize() {
		return nil, , errors.StructuralError("length of decrypted key (" + strconv.Itoa() + ") " +
			"not equal to cipher keysize (" + strconv.Itoa() + ")")
	}
	return , , nil
}
SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The packet contains a random session key, encrypted by a key derived from the given passphrase. The session key is returned and must be passed to SerializeSymmetricallyEncrypted. If config is nil, sensible defaults will be used.
func ( io.Writer,  []byte,  *Config) ( []byte,  error) {
	 := .Cipher()
	 := .KeySize()
	if  == 0 {
		return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int()))
	}

	 := new(bytes.Buffer)
s2k.Serialize salts and stretches the passphrase, and writes the resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
	 = s2k.Serialize(, , .Random(), , &s2k.Config{Hash: .Hash(), S2KCount: .PasswordHashIterations()})
	if  != nil {
		return
	}
	 := .Bytes()

	 := 2 /* header */ + len() + 1 /* cipher type */ + 
	 = serializeHeader(, packetTypeSymmetricKeyEncrypted, )
	if  != nil {
		return
	}

	var  [2]byte
	[0] = symmetricKeyEncryptedVersion
	[1] = byte()
	_,  = .Write([:])
	if  != nil {
		return
	}
	_,  = .Write()
	if  != nil {
		return
	}

	 := make([]byte, )
	_,  = io.ReadFull(.Random(), )
	if  != nil {
		return
	}
	 := make([]byte, .blockSize())
	 := cipher.NewCFBEncrypter(.new(), )
	 := make([]byte, +1)
	.XORKeyStream(, [1:])
	.XORKeyStream([1:], )
	_,  = .Write()
	if  != nil {
		return
	}

	 = 
	return