diff options
Diffstat (limited to 'src/pkg/crypto/openpgp/write.go')
| -rw-r--r-- | src/pkg/crypto/openpgp/write.go | 92 | 
1 files changed, 92 insertions, 0 deletions
| diff --git a/src/pkg/crypto/openpgp/write.go b/src/pkg/crypto/openpgp/write.go new file mode 100644 index 000000000..1a2e2bf04 --- /dev/null +++ b/src/pkg/crypto/openpgp/write.go @@ -0,0 +1,92 @@ +// 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" +	"crypto/openpgp/armor" +	"crypto/openpgp/error" +	"crypto/openpgp/packet" +	"crypto/rsa" +	_ "crypto/sha256" +	"io" +	"os" +	"strconv" +	"time" +) + +// DetachSign signs message with the private key from signer (which must +// already have been decrypted) and writes the signature to w. +func DetachSign(w io.Writer, signer *Entity, message io.Reader) os.Error { +	return detachSign(w, signer, message, packet.SigTypeBinary) +} + +// ArmoredDetachSign signs message with the private key from signer (which +// must already have been decrypted) and writes an armored signature to w. +func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader) (err os.Error) { +	return armoredDetachSign(w, signer, message, packet.SigTypeBinary) +} + +// 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. +func DetachSignText(w io.Writer, signer *Entity, message io.Reader) os.Error { +	return detachSign(w, signer, message, packet.SigTypeText) +} + +// 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. +func SignTextDetachedArmored(w io.Writer, signer *Entity, message io.Reader) os.Error { +	return armoredDetachSign(w, signer, message, packet.SigTypeText) +} + +func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err os.Error) { +	out, err := armor.Encode(w, SignatureType, nil) +	if err != nil { +		return +	} +	err = detachSign(out, signer, message, sigType) +	if err != nil { +		return +	} +	return out.Close() +} + +func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err os.Error) { +	if signer.PrivateKey == nil { +		return error.InvalidArgumentError("signing key doesn't have a private key") +	} +	if signer.PrivateKey.Encrypted { +		return error.InvalidArgumentError("signing key is encrypted") +	} + +	sig := new(packet.Signature) +	sig.SigType = sigType +	sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo +	sig.Hash = crypto.SHA256 +	sig.CreationTime = uint32(time.Seconds()) +	sig.IssuerKeyId = &signer.PrivateKey.KeyId + +	h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType) +	if err != nil { +		return +	} +	io.Copy(wrappedHash, message) + +	switch signer.PrivateKey.PubKeyAlgo { +	case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSASignOnly: +		priv := signer.PrivateKey.PrivateKey.(*rsa.PrivateKey) +		err = sig.SignRSA(h, priv) +	default: +		err = error.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) +	} + +	if err != nil { +		return +	} + +	return sig.Serialize(w) +} | 
