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 implements high level operations on OpenPGP messages.
package openpgp // import "golang.org/x/crypto/openpgp"

import (
	
	_ 
	
	
	

	
	
	
)
SignatureType is the armor type for a PGP signature.
var SignatureType = "PGP SIGNATURE"
readArmored reads an armored block with the given type.
func ( io.Reader,  string) ( io.Reader,  error) {
	,  := armor.Decode()
	if  != nil {
		return
	}

	if .Type !=  {
		return nil, errors.InvalidArgumentError("expected '" +  + "', got: " + .Type)
	}

	return .Body, nil
}
MessageDetails contains the result of parsing an OpenPGP encrypted and/or signed message.
type MessageDetails struct {
	IsEncrypted              bool                // true if the message was encrypted.
	EncryptedToKeyIds        []uint64            // the list of recipient key ids.
	IsSymmetricallyEncrypted bool                // true if a passphrase could have decrypted the message.
	DecryptedWith            Key                 // the private key used to decrypt the message, if any.
	IsSigned                 bool                // true if the message is signed.
	SignedByKeyId            uint64              // the key id of the signer, if any.
	SignedBy                 *Key                // the key of the signer, if available.
	LiteralData              *packet.LiteralData // the metadata of the contents
	UnverifiedBody           io.Reader           // the contents of the message.
If IsSigned is true and SignedBy is non-zero then the signature will be verified as UnverifiedBody is read. The signature cannot be checked until the whole of UnverifiedBody is read so UnverifiedBody must be consumed until EOF before the data can be trusted. Even if a message isn't signed (or the signer is unknown) the data may contain an authentication code that is only checked once UnverifiedBody has been consumed. Once EOF has been seen, the following fields are valid. (An authentication code failure is reported as a SignatureError error when reading from UnverifiedBody.)
	SignatureError error               // nil if the signature is good.
	Signature      *packet.Signature   // the signature packet itself, if v4 (default)
	SignatureV3    *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature

	decrypted io.ReadCloser
}
A PromptFunction is used as a callback by functions that may need to decrypt a private key, or prompt for a passphrase. It is called with a list of acceptable, encrypted private keys and a boolean that indicates whether a passphrase is usable. It should either decrypt a private key or return a passphrase to try. If the decrypted private key or given passphrase isn't correct, the function will be called again, forever. Any error returned will be passed up.
type PromptFunction func(keys []Key, symmetric bool) ([]byte, error)
A keyEnvelopePair is used to store a private key with the envelope that contains a symmetric key, encrypted with that key.
ReadMessage parses an OpenPGP message that may be signed and/or encrypted. The given KeyRing should contain both public keys (for signature verification) and, possibly encrypted, private keys for decrypting. If config is nil, sensible defaults will be used.
func ( io.Reader,  KeyRing,  PromptFunction,  *packet.Config) ( *MessageDetails,  error) {
	var  packet.Packet

	var  []*packet.SymmetricKeyEncrypted
	var  []keyEnvelopePair
	var  *packet.SymmetricallyEncrypted

	 := packet.NewReader()
	 = new(MessageDetails)
	.IsEncrypted = true
The message, if encrypted, starts with a number of packets containing an encrypted decryption key. The decryption key is either encrypted to a public key, or with a passphrase. This loop collects these packets.
:
	for {
		,  = .Next()
		if  != nil {
			return nil, 
		}
		switch p := .(type) {
This packet contains the decryption key encrypted with a passphrase.
			.IsSymmetricallyEncrypted = true
			 = append(, )
This packet contains the decryption key encrypted to a public key.
			.EncryptedToKeyIds = append(.EncryptedToKeyIds, .KeyId)
			switch .Algo {
			case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
				break
			default:
				continue
			}
			var  []Key
			if .KeyId == 0 {
				 = .DecryptionKeys()
			} else {
				 = .KeysById(.KeyId)
			}
			for ,  := range  {
				 = append(, keyEnvelopePair{, })
			}
		case *packet.SymmetricallyEncrypted:
			 = 
			break 
This message isn't encrypted.
			if len() != 0 || len() != 0 {
				return nil, errors.StructuralError("key material not followed by encrypted message")
			}
			.Unread()
			return readSignedMessage(, nil, )
		}
	}

	var  []Key
	var  io.ReadCloser
Now that we have the list of encrypted keys we need to decrypt at least one of them or, if we cannot, we need to call the prompt function so that it can decrypt a key or give us a passphrase.
:
See if any of the keys already have a private key available
		 = [:0]
		 := make(map[string]bool)

		for ,  := range  {
			if .key.PrivateKey == nil {
				continue
			}
			if !.key.PrivateKey.Encrypted {
				if len(.encryptedKey.Key) == 0 {
					.encryptedKey.Decrypt(.key.PrivateKey, )
				}
				if len(.encryptedKey.Key) == 0 {
					continue
				}
				,  = .Decrypt(.encryptedKey.CipherFunc, .encryptedKey.Key)
				if  != nil &&  != errors.ErrKeyIncorrect {
					return nil, 
				}
				if  != nil {
					.DecryptedWith = .key
					break 
				}
			} else {
				 := string(.key.PublicKey.Fingerprint[:])
				if  := [];  {
					continue
				}
				 = append(, .key)
				[] = true
			}
		}

		if len() == 0 && len() == 0 {
			return nil, errors.ErrKeyIncorrect
		}

		if  == nil {
			return nil, errors.ErrKeyIncorrect
		}

		,  := (, len() != 0)
		if  != nil {
			return nil, 
		}
Try the symmetric passphrase first
		if len() != 0 &&  != nil {
			for ,  := range  {
				, ,  := .Decrypt()
				if  == nil {
					,  = .Decrypt(, )
					if  != nil &&  != errors.ErrKeyIncorrect {
						return nil, 
					}
					if  != nil {
						break 
					}
				}

			}
		}
	}

	.decrypted = 
	if  := .Push();  != nil {
		return nil, 
	}
	return readSignedMessage(, , )
}
readSignedMessage reads a possibly signed message if mdin is non-zero then that structure is updated and returned. Otherwise a fresh MessageDetails is used.
func ( *packet.Reader,  *MessageDetails,  KeyRing) ( *MessageDetails,  error) {
	if  == nil {
		 = new(MessageDetails)
	}
	 = 

	var  packet.Packet
	var  hash.Hash
	var  hash.Hash
:
	for {
		,  = .Next()
		if  != nil {
			return nil, 
		}
		switch p := .(type) {
		case *packet.Compressed:
			if  := .Push(.Body);  != nil {
				return nil, 
			}
		case *packet.OnePassSignature:
			if !.IsLast {
				return nil, errors.UnsupportedError("nested signatures")
			}

			, ,  = hashForSignature(.Hash, .SigType)
			if  != nil {
				 = nil
				return
			}

			.IsSigned = true
			.SignedByKeyId = .KeyId
			 := .KeysByIdUsage(.KeyId, packet.KeyFlagSign)
			if len() > 0 {
				.SignedBy = &[0]
			}
		case *packet.LiteralData:
			.LiteralData = 
			break 
		}
	}

	if .SignedBy != nil {
		.UnverifiedBody = &signatureCheckReader{, , , }
	} else if .decrypted != nil {
		.UnverifiedBody = checkReader{}
	} else {
		.UnverifiedBody = .LiteralData.Body
	}

	return , nil
}
hashForSignature returns a pair of hashes that can be used to verify a signature. The signature may specify that the contents of the signed message should be preprocessed (i.e. to normalize line endings). Thus this function returns two hashes. The second should be used to hash the message itself and performs any needed preprocessing.
func ( crypto.Hash,  packet.SignatureType) (hash.Hash, hash.Hash, error) {
	if !.Available() {
		return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int()))
	}
	 := .New()

	switch  {
	case packet.SigTypeBinary:
		return , , nil
	case packet.SigTypeText:
		return , NewCanonicalTextHash(), nil
	}

	return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int()))
}
checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger MDC checks.
type checkReader struct {
	md *MessageDetails
}

func ( checkReader) ( []byte) ( int,  error) {
	,  = .md.LiteralData.Body.Read()
	if  == io.EOF {
		 := .md.decrypted.Close()
		if  != nil {
			 = 
		}
	}
	return
}
signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes the data as it is read. When it sees an EOF from the underlying io.Reader it parses and checks a trailing Signature packet and triggers any MDC checks.
type signatureCheckReader struct {
	packets        *packet.Reader
	h, wrappedHash hash.Hash
	md             *MessageDetails
}

func ( *signatureCheckReader) ( []byte) ( int,  error) {
	,  = .md.LiteralData.Body.Read()
	.wrappedHash.Write([:])
	if  == io.EOF {
		var  packet.Packet
		, .md.SignatureError = .packets.Next()
		if .md.SignatureError != nil {
			return
		}

		var  bool
		if .md.Signature,  = .(*packet.Signature);  {
			.md.SignatureError = .md.SignedBy.PublicKey.VerifySignature(.h, .md.Signature)
		} else if .md.SignatureV3,  = .(*packet.SignatureV3);  {
			.md.SignatureError = .md.SignedBy.PublicKey.VerifySignatureV3(.h, .md.SignatureV3)
		} else {
			.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
			return
		}
The SymmetricallyEncrypted packet, if any, might have an unsigned hash of its own. In order to check this we need to close that Reader.
		if .md.decrypted != nil {
			 := .md.decrypted.Close()
			if  != nil {
				 = 
			}
		}
	}
	return
}
CheckDetachedSignature takes a signed file and a detached signature and returns the signer if the signature is valid. If the signer isn't known, ErrUnknownIssuer is returned.
func ( KeyRing, ,  io.Reader) ( *Entity,  error) {
	var  uint64
	var  crypto.Hash
	var  packet.SignatureType
	var  []Key
	var  packet.Packet

	 := packet.NewReader()
	for {
		,  = .Next()
		if  == io.EOF {
			return nil, errors.ErrUnknownIssuer
		}
		if  != nil {
			return nil, 
		}

		switch sig := .(type) {
		case *packet.Signature:
			if .IssuerKeyId == nil {
				return nil, errors.StructuralError("signature doesn't have an issuer")
			}
			 = *.IssuerKeyId
			 = .Hash
			 = .SigType
		case *packet.SignatureV3:
			 = .IssuerKeyId
			 = .Hash
			 = .SigType
		default:
			return nil, errors.StructuralError("non signature packet found")
		}

		 = .KeysByIdUsage(, packet.KeyFlagSign)
		if len() > 0 {
			break
		}
	}

	if len() == 0 {
		panic("unreachable")
	}

	, ,  := hashForSignature(, )
	if  != nil {
		return nil, 
	}

	if ,  := io.Copy(, );  != nil &&  != io.EOF {
		return nil, 
	}

	for ,  := range  {
		switch sig := .(type) {
		case *packet.Signature:
			 = .PublicKey.VerifySignature(, )
		case *packet.SignatureV3:
			 = .PublicKey.VerifySignatureV3(, )
		default:
			panic("unreachable")
		}

		if  == nil {
			return .Entity, nil
		}
	}

	return nil, 
}
CheckArmoredDetachedSignature performs the same actions as CheckDetachedSignature but expects the signature to be armored.
func ( KeyRing, ,  io.Reader) ( *Entity,  error) {
	,  := readArmored(, SignatureType)
	if  != nil {
		return
	}

	return CheckDetachedSignature(, , )