2011-02-24 18:19:53 -07:00
|
|
|
// 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"
|
2011-03-16 08:50:06 -06:00
|
|
|
"crypto/dsa"
|
2011-02-24 18:19:53 -07:00
|
|
|
"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.
|
2011-03-10 08:14:31 -07:00
|
|
|
func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader) os.Error {
|
2011-02-24 18:19:53 -07:00
|
|
|
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)
|
2011-03-16 08:50:06 -06:00
|
|
|
case packet.PubKeyAlgoDSA:
|
|
|
|
priv := signer.PrivateKey.PrivateKey.(*dsa.PrivateKey)
|
|
|
|
err = sig.SignDSA(h, priv)
|
2011-02-24 18:19:53 -07:00
|
|
|
default:
|
|
|
|
err = error.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return sig.Serialize(w)
|
|
|
|
}
|