Moved to google.golang.org/genproto/googleapis/api/annotations
Fixes #52
This commit is contained in:
		
							
								
								
									
										378
									
								
								vendor/golang.org/x/crypto/openpgp/write.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										378
									
								
								vendor/golang.org/x/crypto/openpgp/write.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,378 @@
 | 
			
		||||
// 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 openpgp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto"
 | 
			
		||||
	"hash"
 | 
			
		||||
	"io"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/crypto/openpgp/armor"
 | 
			
		||||
	"golang.org/x/crypto/openpgp/errors"
 | 
			
		||||
	"golang.org/x/crypto/openpgp/packet"
 | 
			
		||||
	"golang.org/x/crypto/openpgp/s2k"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DetachSign signs message with the private key from signer (which must
 | 
			
		||||
// already have been decrypted) and writes the signature to w.
 | 
			
		||||
// If config is nil, sensible defaults will be used.
 | 
			
		||||
func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
 | 
			
		||||
	return detachSign(w, signer, message, packet.SigTypeBinary, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ArmoredDetachSign signs message with the private key from signer (which
 | 
			
		||||
// must already have been decrypted) and writes an armored signature to w.
 | 
			
		||||
// If config is nil, sensible defaults will be used.
 | 
			
		||||
func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) {
 | 
			
		||||
	return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DetachSignText signs message (after canonicalising the line endings) with
 | 
			
		||||
// the private key from signer (which must already have been decrypted) and
 | 
			
		||||
// writes the signature to w.
 | 
			
		||||
// If config is nil, sensible defaults will be used.
 | 
			
		||||
func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
 | 
			
		||||
	return detachSign(w, signer, message, packet.SigTypeText, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ArmoredDetachSignText signs message (after canonicalising the line endings)
 | 
			
		||||
// with the private key from signer (which must already have been decrypted)
 | 
			
		||||
// and writes an armored signature to w.
 | 
			
		||||
// If config is nil, sensible defaults will be used.
 | 
			
		||||
func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
 | 
			
		||||
	return armoredDetachSign(w, signer, message, packet.SigTypeText, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
 | 
			
		||||
	out, err := armor.Encode(w, SignatureType, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	err = detachSign(out, signer, message, sigType, config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return out.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
 | 
			
		||||
	if signer.PrivateKey == nil {
 | 
			
		||||
		return errors.InvalidArgumentError("signing key doesn't have a private key")
 | 
			
		||||
	}
 | 
			
		||||
	if signer.PrivateKey.Encrypted {
 | 
			
		||||
		return errors.InvalidArgumentError("signing key is encrypted")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sig := new(packet.Signature)
 | 
			
		||||
	sig.SigType = sigType
 | 
			
		||||
	sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
 | 
			
		||||
	sig.Hash = config.Hash()
 | 
			
		||||
	sig.CreationTime = config.Now()
 | 
			
		||||
	sig.IssuerKeyId = &signer.PrivateKey.KeyId
 | 
			
		||||
 | 
			
		||||
	h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	io.Copy(wrappedHash, message)
 | 
			
		||||
 | 
			
		||||
	err = sig.Sign(h, signer.PrivateKey, config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sig.Serialize(w)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FileHints contains metadata about encrypted files. This metadata is, itself,
 | 
			
		||||
// encrypted.
 | 
			
		||||
type FileHints struct {
 | 
			
		||||
	// IsBinary can be set to hint that the contents are binary data.
 | 
			
		||||
	IsBinary bool
 | 
			
		||||
	// FileName hints at the name of the file that should be written. It's
 | 
			
		||||
	// truncated to 255 bytes if longer. It may be empty to suggest that the
 | 
			
		||||
	// file should not be written to disk. It may be equal to "_CONSOLE" to
 | 
			
		||||
	// suggest the data should not be written to disk.
 | 
			
		||||
	FileName string
 | 
			
		||||
	// ModTime contains the modification time of the file, or the zero time if not applicable.
 | 
			
		||||
	ModTime time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase.
 | 
			
		||||
// The resulting WriteCloser must be closed after the contents of the file have
 | 
			
		||||
// been written.
 | 
			
		||||
// If config is nil, sensible defaults will be used.
 | 
			
		||||
func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
 | 
			
		||||
	if hints == nil {
 | 
			
		||||
		hints = &FileHints{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	literaldata := w
 | 
			
		||||
	if algo := config.Compression(); algo != packet.CompressionNone {
 | 
			
		||||
		var compConfig *packet.CompressionConfig
 | 
			
		||||
		if config != nil {
 | 
			
		||||
			compConfig = config.CompressionConfig
 | 
			
		||||
		}
 | 
			
		||||
		literaldata, err = packet.SerializeCompressed(w, algo, compConfig)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var epochSeconds uint32
 | 
			
		||||
	if !hints.ModTime.IsZero() {
 | 
			
		||||
		epochSeconds = uint32(hints.ModTime.Unix())
 | 
			
		||||
	}
 | 
			
		||||
	return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// intersectPreferences mutates and returns a prefix of a that contains only
 | 
			
		||||
// the values in the intersection of a and b. The order of a is preserved.
 | 
			
		||||
func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) {
 | 
			
		||||
	var j int
 | 
			
		||||
	for _, v := range a {
 | 
			
		||||
		for _, v2 := range b {
 | 
			
		||||
			if v == v2 {
 | 
			
		||||
				a[j] = v
 | 
			
		||||
				j++
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return a[:j]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hashToHashId(h crypto.Hash) uint8 {
 | 
			
		||||
	v, ok := s2k.HashToHashId(h)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		panic("tried to convert unknown hash")
 | 
			
		||||
	}
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encrypt encrypts a message to a number of recipients and, optionally, signs
 | 
			
		||||
// it. hints contains optional information, that is also encrypted, that aids
 | 
			
		||||
// the recipients in processing the message. The resulting WriteCloser must
 | 
			
		||||
// be closed after the contents of the file have been written.
 | 
			
		||||
// If config is nil, sensible defaults will be used.
 | 
			
		||||
func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
 | 
			
		||||
	var signer *packet.PrivateKey
 | 
			
		||||
	if signed != nil {
 | 
			
		||||
		signKey, ok := signed.signingKey(config.Now())
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, errors.InvalidArgumentError("no valid signing keys")
 | 
			
		||||
		}
 | 
			
		||||
		signer = signKey.PrivateKey
 | 
			
		||||
		if signer == nil {
 | 
			
		||||
			return nil, errors.InvalidArgumentError("no private key in signing key")
 | 
			
		||||
		}
 | 
			
		||||
		if signer.Encrypted {
 | 
			
		||||
			return nil, errors.InvalidArgumentError("signing key must be decrypted")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// These are the possible ciphers that we'll use for the message.
 | 
			
		||||
	candidateCiphers := []uint8{
 | 
			
		||||
		uint8(packet.CipherAES128),
 | 
			
		||||
		uint8(packet.CipherAES256),
 | 
			
		||||
		uint8(packet.CipherCAST5),
 | 
			
		||||
	}
 | 
			
		||||
	// These are the possible hash functions that we'll use for the signature.
 | 
			
		||||
	candidateHashes := []uint8{
 | 
			
		||||
		hashToHashId(crypto.SHA256),
 | 
			
		||||
		hashToHashId(crypto.SHA512),
 | 
			
		||||
		hashToHashId(crypto.SHA1),
 | 
			
		||||
		hashToHashId(crypto.RIPEMD160),
 | 
			
		||||
	}
 | 
			
		||||
	// In the event that a recipient doesn't specify any supported ciphers
 | 
			
		||||
	// or hash functions, these are the ones that we assume that every
 | 
			
		||||
	// implementation supports.
 | 
			
		||||
	defaultCiphers := candidateCiphers[len(candidateCiphers)-1:]
 | 
			
		||||
	defaultHashes := candidateHashes[len(candidateHashes)-1:]
 | 
			
		||||
 | 
			
		||||
	encryptKeys := make([]Key, len(to))
 | 
			
		||||
	for i := range to {
 | 
			
		||||
		var ok bool
 | 
			
		||||
		encryptKeys[i], ok = to[i].encryptionKey(config.Now())
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sig := to[i].primaryIdentity().SelfSignature
 | 
			
		||||
 | 
			
		||||
		preferredSymmetric := sig.PreferredSymmetric
 | 
			
		||||
		if len(preferredSymmetric) == 0 {
 | 
			
		||||
			preferredSymmetric = defaultCiphers
 | 
			
		||||
		}
 | 
			
		||||
		preferredHashes := sig.PreferredHash
 | 
			
		||||
		if len(preferredHashes) == 0 {
 | 
			
		||||
			preferredHashes = defaultHashes
 | 
			
		||||
		}
 | 
			
		||||
		candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric)
 | 
			
		||||
		candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(candidateCiphers) == 0 || len(candidateHashes) == 0 {
 | 
			
		||||
		return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cipher := packet.CipherFunction(candidateCiphers[0])
 | 
			
		||||
	// If the cipher specified by config is a candidate, we'll use that.
 | 
			
		||||
	configuredCipher := config.Cipher()
 | 
			
		||||
	for _, c := range candidateCiphers {
 | 
			
		||||
		cipherFunc := packet.CipherFunction(c)
 | 
			
		||||
		if cipherFunc == configuredCipher {
 | 
			
		||||
			cipher = cipherFunc
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var hash crypto.Hash
 | 
			
		||||
	for _, hashId := range candidateHashes {
 | 
			
		||||
		if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() {
 | 
			
		||||
			hash = h
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If the hash specified by config is a candidate, we'll use that.
 | 
			
		||||
	if configuredHash := config.Hash(); configuredHash.Available() {
 | 
			
		||||
		for _, hashId := range candidateHashes {
 | 
			
		||||
			if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash {
 | 
			
		||||
				hash = h
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hash == 0 {
 | 
			
		||||
		hashId := candidateHashes[0]
 | 
			
		||||
		name, ok := s2k.HashIdToString(hashId)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			name = "#" + strconv.Itoa(int(hashId))
 | 
			
		||||
		}
 | 
			
		||||
		return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	symKey := make([]byte, cipher.KeySize())
 | 
			
		||||
	if _, err := io.ReadFull(config.Random(), symKey); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, key := range encryptKeys {
 | 
			
		||||
		if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if signer != nil {
 | 
			
		||||
		ops := &packet.OnePassSignature{
 | 
			
		||||
			SigType:    packet.SigTypeBinary,
 | 
			
		||||
			Hash:       hash,
 | 
			
		||||
			PubKeyAlgo: signer.PubKeyAlgo,
 | 
			
		||||
			KeyId:      signer.KeyId,
 | 
			
		||||
			IsLast:     true,
 | 
			
		||||
		}
 | 
			
		||||
		if err := ops.Serialize(encryptedData); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hints == nil {
 | 
			
		||||
		hints = &FileHints{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w := encryptedData
 | 
			
		||||
	if signer != nil {
 | 
			
		||||
		// If we need to write a signature packet after the literal
 | 
			
		||||
		// data then we need to stop literalData from closing
 | 
			
		||||
		// encryptedData.
 | 
			
		||||
		w = noOpCloser{encryptedData}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	var epochSeconds uint32
 | 
			
		||||
	if !hints.ModTime.IsZero() {
 | 
			
		||||
		epochSeconds = uint32(hints.ModTime.Unix())
 | 
			
		||||
	}
 | 
			
		||||
	literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if signer != nil {
 | 
			
		||||
		return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return literalData, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// signatureWriter hashes the contents of a message while passing it along to
 | 
			
		||||
// literalData. When closed, it closes literalData, writes a signature packet
 | 
			
		||||
// to encryptedData and then also closes encryptedData.
 | 
			
		||||
type signatureWriter struct {
 | 
			
		||||
	encryptedData io.WriteCloser
 | 
			
		||||
	literalData   io.WriteCloser
 | 
			
		||||
	hashType      crypto.Hash
 | 
			
		||||
	h             hash.Hash
 | 
			
		||||
	signer        *packet.PrivateKey
 | 
			
		||||
	config        *packet.Config
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s signatureWriter) Write(data []byte) (int, error) {
 | 
			
		||||
	s.h.Write(data)
 | 
			
		||||
	return s.literalData.Write(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s signatureWriter) Close() error {
 | 
			
		||||
	sig := &packet.Signature{
 | 
			
		||||
		SigType:      packet.SigTypeBinary,
 | 
			
		||||
		PubKeyAlgo:   s.signer.PubKeyAlgo,
 | 
			
		||||
		Hash:         s.hashType,
 | 
			
		||||
		CreationTime: s.config.Now(),
 | 
			
		||||
		IssuerKeyId:  &s.signer.KeyId,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := sig.Sign(s.h, s.signer, s.config); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := s.literalData.Close(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := sig.Serialize(s.encryptedData); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return s.encryptedData.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
 | 
			
		||||
// TODO: we have two of these in OpenPGP packages alone. This probably needs
 | 
			
		||||
// to be promoted somewhere more common.
 | 
			
		||||
type noOpCloser struct {
 | 
			
		||||
	w io.Writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c noOpCloser) Write(data []byte) (n int, err error) {
 | 
			
		||||
	return c.w.Write(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c noOpCloser) Close() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user