openpgp: eliminate implicit rand.Reader and time.Now

Fixes golang/go#2501.

R=rsc, bradfitz
CC=golang-dev
https://golang.org/cl/5653067
This commit is contained in:
Adam Langley
2012-02-20 10:48:21 -05:00
parent 6c548e9506
commit 54eafe1dea
13 changed files with 127 additions and 98 deletions
+6 -9
View File
@@ -17,7 +17,6 @@ import (
"io"
"net/textproto"
"strconv"
"time"
"code.google.com/p/go.crypto/openpgp/armor"
"code.google.com/p/go.crypto/openpgp/errors"
@@ -179,9 +178,8 @@ type dashEscaper struct {
whitespace []byte
byteBuf []byte // a one byte buffer to save allocations
privateKey *packet.PrivateKey
signingTime time.Time
rand io.Reader
privateKey *packet.PrivateKey
config *packet.Config
}
func (d *dashEscaper) Write(data []byte) (n int, err error) {
@@ -261,10 +259,10 @@ func (d *dashEscaper) Close() (err error) {
sig.SigType = packet.SigTypeText
sig.PubKeyAlgo = d.privateKey.PubKeyAlgo
sig.Hash = d.hashType
sig.CreationTime = d.signingTime
sig.CreationTime = d.config.Now()
sig.IssuerKeyId = &d.privateKey.KeyId
if err = sig.Sign(d.rand, d.h, d.privateKey); err != nil {
if err = sig.Sign(d.h, d.privateKey, d.config); err != nil {
return
}
@@ -334,9 +332,8 @@ func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (
byteBuf: make([]byte, 1),
privateKey: privateKey,
signingTime: config.Now(),
rand: config.Random(),
privateKey: privateKey,
config: config,
}
return
+17 -15
View File
@@ -8,11 +8,8 @@ import (
"code.google.com/p/go.crypto/openpgp/armor"
"code.google.com/p/go.crypto/openpgp/errors"
"code.google.com/p/go.crypto/openpgp/packet"
"crypto"
"crypto/rand"
"crypto/rsa"
"io"
"time"
)
// PublicKeyType is the armor type for a PGP public key.
@@ -383,16 +380,19 @@ const defaultRSAKeyBits = 2048
// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
// single identity composed of the given full name, comment and email, any of
// which may be empty but must not contain any of "()<>\x00".
func NewEntity(rand io.Reader, currentTime time.Time, name, comment, email string) (*Entity, error) {
// If config is nil, sensible defaults will be used.
func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
currentTime := config.Now()
uid := packet.NewUserId(name, comment, email)
if uid == nil {
return nil, errors.InvalidArgumentError("user id field contained invalid characters")
}
signingPriv, err := rsa.GenerateKey(rand, defaultRSAKeyBits)
signingPriv, err := rsa.GenerateKey(config.Random(), defaultRSAKeyBits)
if err != nil {
return nil, err
}
encryptingPriv, err := rsa.GenerateKey(rand, defaultRSAKeyBits)
encryptingPriv, err := rsa.GenerateKey(config.Random(), defaultRSAKeyBits)
if err != nil {
return nil, err
}
@@ -410,7 +410,7 @@ func NewEntity(rand io.Reader, currentTime time.Time, name, comment, email strin
CreationTime: currentTime,
SigType: packet.SigTypePositiveCert,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: crypto.SHA256,
Hash: config.Hash(),
IsPrimaryId: &isPrimaryId,
FlagsValid: true,
FlagSign: true,
@@ -427,7 +427,7 @@ func NewEntity(rand io.Reader, currentTime time.Time, name, comment, email strin
CreationTime: currentTime,
SigType: packet.SigTypeSubkeyBinding,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: crypto.SHA256,
Hash: config.Hash(),
FlagsValid: true,
FlagEncryptStorage: true,
FlagEncryptCommunications: true,
@@ -443,7 +443,8 @@ func NewEntity(rand io.Reader, currentTime time.Time, name, comment, email strin
// SerializePrivate serializes an Entity, including private key material, to
// the given Writer. For now, it must only be used on an Entity returned from
// NewEntity.
func (e *Entity) SerializePrivate(w io.Writer) (err error) {
// If config is nil, sensible defaults will be used.
func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
err = e.PrivateKey.Serialize(w)
if err != nil {
return
@@ -453,7 +454,7 @@ func (e *Entity) SerializePrivate(w io.Writer) (err error) {
if err != nil {
return
}
err = ident.SelfSignature.SignUserId(rand.Reader, ident.UserId.Id, e.PrimaryKey, e.PrivateKey)
err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
if err != nil {
return
}
@@ -467,7 +468,7 @@ func (e *Entity) SerializePrivate(w io.Writer) (err error) {
if err != nil {
return
}
err = subkey.Sig.SignKey(rand.Reader, subkey.PublicKey, e.PrivateKey)
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
if err != nil {
return
}
@@ -519,7 +520,8 @@ func (e *Entity) Serialize(w io.Writer) error {
// associated with e. The provided identity must already be an element of
// e.Identities and the private key of signer must have been decrypted if
// necessary.
func (e *Entity) SignIdentity(identity string, signer *Entity) error {
// If config is nil, sensible defaults will be used.
func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
if signer.PrivateKey == nil {
return errors.InvalidArgumentError("signing Entity must have a private key")
}
@@ -534,11 +536,11 @@ func (e *Entity) SignIdentity(identity string, signer *Entity) error {
sig := &packet.Signature{
SigType: packet.SigTypeGenericCert,
PubKeyAlgo: signer.PrivateKey.PubKeyAlgo,
Hash: crypto.SHA256,
CreationTime: time.Now(),
Hash: config.Hash(),
CreationTime: config.Now(),
IssuerKeyId: &signer.PrivateKey.KeyId,
}
if err := sig.SignKey(rand.Reader, e.PrimaryKey, signer.PrivateKey); err != nil {
if err := sig.SignKey(e.PrimaryKey, signer.PrivateKey, config); err != nil {
return err
}
ident.Signatures = append(ident.Signatures, sig)
+7 -6
View File
@@ -7,7 +7,6 @@ package packet
import (
"code.google.com/p/go.crypto/openpgp/elgamal"
"code.google.com/p/go.crypto/openpgp/errors"
"crypto/rand"
"crypto/rsa"
"encoding/binary"
"io"
@@ -63,7 +62,8 @@ func checksumKeyMaterial(key []byte) uint16 {
// Decrypt decrypts an encrypted session key with the given private key. The
// private key must have been decrypted first.
func (e *EncryptedKey) Decrypt(priv *PrivateKey) error {
// If config is nil, sensible defaults will be used.
func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
var err error
var b []byte
@@ -71,7 +71,7 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey) error {
// padding oracle attacks.
switch priv.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
b, err = rsa.DecryptPKCS1v15(rand.Reader, priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1)
b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1)
case PubKeyAlgoElGamal:
c1 := new(big.Int).SetBytes(e.encryptedMPI1)
c2 := new(big.Int).SetBytes(e.encryptedMPI2)
@@ -97,7 +97,8 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey) error {
// SerializeEncryptedKey serializes an encrypted key packet to w that contains
// key, encrypted to pub.
func SerializeEncryptedKey(w io.Writer, rand io.Reader, pub *PublicKey, cipherFunc CipherFunction, key []byte) error {
// If config is nil, sensible defaults will be used.
func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
var buf [10]byte
buf[0] = encryptedKeyVersion
binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
@@ -112,9 +113,9 @@ func SerializeEncryptedKey(w io.Writer, rand io.Reader, pub *PublicKey, cipherFu
switch pub.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
return serializeEncryptedKeyRSA(w, rand, buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
case PubKeyAlgoElGamal:
return serializeEncryptedKeyElGamal(w, rand, buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
}
+3 -4
View File
@@ -6,7 +6,6 @@ package packet
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"fmt"
"math/big"
@@ -58,7 +57,7 @@ func TestDecryptingEncryptedKey(t *testing.T) {
return
}
err = ek.Decrypt(encryptedKeyPriv)
err = ek.Decrypt(encryptedKeyPriv, nil)
if err != nil {
t.Errorf("error from Decrypt: %s", err)
return
@@ -87,7 +86,7 @@ func TestEncryptingEncryptedKey(t *testing.T) {
}
buf := new(bytes.Buffer)
err := SerializeEncryptedKey(buf, rand.Reader, pub, CipherAES128, key)
err := SerializeEncryptedKey(buf, pub, CipherAES128, key, nil)
if err != nil {
t.Errorf("error writing encrypted key packet: %s", err)
}
@@ -108,7 +107,7 @@ func TestEncryptingEncryptedKey(t *testing.T) {
return
}
err = ek.Decrypt(encryptedKeyPriv)
err = ek.Decrypt(encryptedKeyPriv, nil)
if err != nil {
t.Errorf("error from Decrypt: %s", err)
return
+10 -7
View File
@@ -426,7 +426,8 @@ func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
// Sign signs a message with a private key. The hash, h, must contain
// the hash of the message to be signed and will be mutated by this function.
// On success, the signature is stored in sig. Call Serialize to write it out.
func (sig *Signature) Sign(rand io.Reader, h hash.Hash, priv *PrivateKey) (err error) {
// If config is nil, sensible defaults will be used.
func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
sig.outSubpackets = sig.buildSubpackets()
digest, err := sig.signPrepareHash(h)
if err != nil {
@@ -435,7 +436,7 @@ func (sig *Signature) Sign(rand io.Reader, h hash.Hash, priv *PrivateKey) (err e
switch priv.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
case PubKeyAlgoDSA:
dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
@@ -445,7 +446,7 @@ func (sig *Signature) Sign(rand io.Reader, h hash.Hash, priv *PrivateKey) (err e
if len(digest) > subgroupSize {
digest = digest[:subgroupSize]
}
r, s, err := dsa.Sign(rand, dsaPriv, digest)
r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
if err == nil {
sig.DSASigR.bytes = r.Bytes()
sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
@@ -462,22 +463,24 @@ func (sig *Signature) Sign(rand io.Reader, h hash.Hash, priv *PrivateKey) (err e
// SignUserId computes a signature from priv, asserting that pub is a valid
// key for the identity id. On success, the signature is stored in sig. Call
// Serialize to write it out.
func (sig *Signature) SignUserId(rand io.Reader, id string, pub *PublicKey, priv *PrivateKey) error {
// If config is nil, sensible defaults will be used.
func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
h, err := userIdSignatureHash(id, pub, sig)
if err != nil {
return nil
}
return sig.Sign(rand, h, priv)
return sig.Sign(h, priv, config)
}
// SignKey computes a signature from priv, asserting that pub is a subkey. On
// success, the signature is stored in sig. Call Serialize to write it out.
func (sig *Signature) SignKey(rand io.Reader, pub *PublicKey, priv *PrivateKey) error {
// If config is nil, sensible defaults will be used.
func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
h, err := keySignatureHash(&priv.PublicKey, pub, sig)
if err != nil {
return err
}
return sig.Sign(rand, h, priv)
return sig.Sign(h, priv, config)
}
// Serialize marshals sig to w. SignRSA or SignDSA must have been called first.
+5 -3
View File
@@ -107,7 +107,9 @@ func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) error {
// 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.
func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []byte, cipherFunc CipherFunction) (key []byte, err error) {
// If config is nil, sensible defaults will be used.
func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
cipherFunc := config.Cipher()
keySize := cipherFunc.KeySize()
if keySize == 0 {
return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
@@ -117,7 +119,7 @@ func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []by
keyEncryptingKey := make([]byte, keySize)
// s2k.Serialize salts and stretches the passphrase, and writes the
// resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
err = s2k.Serialize(s2kBuf, keyEncryptingKey, rand, passphrase)
err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase)
if err != nil {
return
}
@@ -142,7 +144,7 @@ func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []by
}
sessionKey := make([]byte, keySize)
_, err = io.ReadFull(rand, sessionKey)
_, err = io.ReadFull(config.Random(), sessionKey)
if err != nil {
return
}
@@ -6,7 +6,6 @@ package packet
import (
"bytes"
"crypto/rand"
"encoding/hex"
"io"
"io/ioutil"
@@ -65,9 +64,11 @@ const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a"
func TestSerializeSymmetricKeyEncrypted(t *testing.T) {
buf := bytes.NewBuffer(nil)
passphrase := []byte("testing")
cipherFunc := CipherAES128
config := &Config{
DefaultCipher: CipherAES128,
}
key, err := SerializeSymmetricKeyEncrypted(buf, rand.Reader, passphrase, cipherFunc)
key, err := SerializeSymmetricKeyEncrypted(buf, passphrase, config)
if err != nil {
t.Errorf("failed to serialize: %s", err)
return
@@ -87,8 +88,8 @@ func TestSerializeSymmetricKeyEncrypted(t *testing.T) {
if !ske.Encrypted {
t.Errorf("SKE not encrypted but should be")
}
if ske.CipherFunc != cipherFunc {
t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, cipherFunc)
if ske.CipherFunc != config.DefaultCipher {
t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, config.DefaultCipher)
}
err = ske.Decrypt(passphrase)
if err != nil {
+3 -2
View File
@@ -252,7 +252,8 @@ func (c noOpCloser) Close() error {
// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
// to w and returns a WriteCloser to which the to-be-encrypted packets can be
// written.
func SerializeSymmetricallyEncrypted(w io.Writer, rand io.Reader, c CipherFunction, key []byte) (contents io.WriteCloser, err error) {
// If config is nil, sensible defaults will be used.
func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) {
if c.KeySize() != len(key) {
return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
}
@@ -270,7 +271,7 @@ func SerializeSymmetricallyEncrypted(w io.Writer, rand io.Reader, c CipherFuncti
block := c.new(key)
blockSize := block.BlockSize()
iv := make([]byte, blockSize)
_, err = rand.Read(iv)
_, err = config.Random().Read(iv)
if err != nil {
return
}
@@ -7,7 +7,6 @@ package packet
import (
"bytes"
"code.google.com/p/go.crypto/openpgp/errors"
"crypto/rand"
"crypto/sha1"
"encoding/hex"
"io"
@@ -83,7 +82,7 @@ func TestSerialize(t *testing.T) {
c := CipherAES128
key := make([]byte, c.KeySize())
w, err := SerializeSymmetricallyEncrypted(buf, rand.Reader, c, key)
w, err := SerializeSymmetricallyEncrypted(buf, c, key, nil)
if err != nil {
t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err)
return
+3 -2
View File
@@ -80,7 +80,8 @@ type keyEnvelopePair struct {
// 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.
func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction) (md *MessageDetails, err error) {
// If config is nil, sensible defaults will be used.
func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) {
var p packet.Packet
var symKeys []*packet.SymmetricKeyEncrypted
@@ -155,7 +156,7 @@ FindKey:
}
if !pk.key.PrivateKey.Encrypted {
if len(pk.encryptedKey.Key) == 0 {
pk.encryptedKey.Decrypt(pk.key.PrivateKey)
pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
}
if len(pk.encryptedKey.Key) == 0 {
continue
+4 -4
View File
@@ -104,7 +104,7 @@ func TestGetKeyById(t *testing.T) {
func checkSignedMessage(t *testing.T, signedHex, expected string) {
kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
md, err := ReadMessage(readerFromHex(signedHex), kring, nil)
md, err := ReadMessage(readerFromHex(signedHex), kring, nil, nil)
if err != nil {
t.Error(err)
return
@@ -178,7 +178,7 @@ func TestSignedEncryptedMessage(t *testing.T) {
return nil, nil
}
md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt)
md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt, nil)
if err != nil {
t.Errorf("#%d: error reading message: %s", i, err)
return
@@ -206,7 +206,7 @@ func TestUnspecifiedRecipient(t *testing.T) {
expected := "Recipient unspecified\n"
kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil)
md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil, nil)
if err != nil {
t.Errorf("error reading message: %s", err)
return
@@ -236,7 +236,7 @@ func TestSymmetricallyEncrypted(t *testing.T) {
return []byte("password"), nil
}
md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt)
md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt, nil)
if err != nil {
t.Errorf("ReadMessage: %s", err)
return
+52 -27
View File
@@ -10,8 +10,6 @@ import (
"code.google.com/p/go.crypto/openpgp/packet"
"code.google.com/p/go.crypto/openpgp/s2k"
"crypto"
"crypto/rand"
_ "crypto/sha256"
"hash"
"io"
"strconv"
@@ -20,43 +18,47 @@ import (
// 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) error {
return detachSign(w, signer, message, packet.SigTypeBinary)
// 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.
func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader) (err error) {
return armoredDetachSign(w, signer, message, packet.SigTypeBinary)
// 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.
func DetachSignText(w io.Writer, signer *Entity, message io.Reader) error {
return detachSign(w, signer, message, packet.SigTypeText)
// 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.
func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader) error {
return armoredDetachSign(w, signer, message, packet.SigTypeText)
// 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) (err error) {
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)
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) (err error) {
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")
}
@@ -67,8 +69,8 @@ func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.S
sig := new(packet.Signature)
sig.SigType = sigType
sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
sig.Hash = crypto.SHA256
sig.CreationTime = time.Now()
sig.Hash = config.Hash()
sig.CreationTime = config.Now()
sig.IssuerKeyId = &signer.PrivateKey.KeyId
h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
@@ -77,7 +79,7 @@ func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.S
}
io.Copy(wrappedHash, message)
err = sig.Sign(rand.Reader, h, signer.PrivateKey)
err = sig.Sign(h, signer.PrivateKey, config)
if err != nil {
return
}
@@ -102,16 +104,17 @@ type FileHints struct {
// 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.
func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints) (plaintext io.WriteCloser, err error) {
// 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, rand.Reader, passphrase, packet.CipherAES128)
key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config)
if err != nil {
return
}
w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, rand.Reader, packet.CipherAES128, key)
w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config)
if err != nil {
return
}
@@ -151,7 +154,8 @@ func hashToHashId(h crypto.Hash) uint8 {
// 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.
func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints) (plaintext io.WriteCloser, err error) {
// 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 {
signer = signed.signingKey().PrivateKey
@@ -205,19 +209,39 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
}
cipher := packet.CipherFunction(candidateCiphers[0])
hash, _ := s2k.HashIdToHash(candidateHashes[0])
// If the cipher specifed 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
}
}
hashFunc := candidateHashes[0]
// If the hash specified by config is a candidate, we'll use that.
configuredHash := config.Hash()
for _, h := range candidateHashes {
if h == uint8(configuredHash) {
hashFunc = h
break
}
}
hash, _ := s2k.HashIdToHash(hashFunc)
symKey := make([]byte, cipher.KeySize())
if _, err := io.ReadFull(rand.Reader, symKey); err != nil {
if _, err := io.ReadFull(config.Random(), symKey); err != nil {
return nil, err
}
for _, key := range encryptKeys {
if err := packet.SerializeEncryptedKey(ciphertext, rand.Reader, key.PublicKey, cipher, symKey); err != nil {
if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil {
return nil, err
}
}
encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, rand.Reader, cipher, symKey)
encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config)
if err != nil {
return
}
@@ -257,7 +281,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
}
if signer != nil {
return signatureWriter{encryptedData, literalData, hash, hash.New(), signer}, nil
return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil
}
return literalData, nil
}
@@ -271,6 +295,7 @@ type signatureWriter struct {
hashType crypto.Hash
h hash.Hash
signer *packet.PrivateKey
config *packet.Config
}
func (s signatureWriter) Write(data []byte) (int, error) {
@@ -283,11 +308,11 @@ func (s signatureWriter) Close() error {
SigType: packet.SigTypeBinary,
PubKeyAlgo: s.signer.PubKeyAlgo,
Hash: s.hashType,
CreationTime: time.Now(),
CreationTime: s.config.Now(),
IssuerKeyId: &s.signer.KeyId,
}
if err := sig.Sign(rand.Reader, s.h, s.signer); err != nil {
if err := sig.Sign(s.h, s.signer, s.config); err != nil {
return err
}
if err := s.literalData.Close(); err != nil {
+10 -12
View File
@@ -6,18 +6,16 @@ package openpgp
import (
"bytes"
"crypto/rand"
"io"
"io/ioutil"
"testing"
"time"
)
func TestSignDetached(t *testing.T) {
kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
out := bytes.NewBuffer(nil)
message := bytes.NewBufferString(signedInput)
err := DetachSign(out, kring[0], message)
err := DetachSign(out, kring[0], message, nil)
if err != nil {
t.Error(err)
}
@@ -29,7 +27,7 @@ func TestSignTextDetached(t *testing.T) {
kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
out := bytes.NewBuffer(nil)
message := bytes.NewBufferString(signedInput)
err := DetachSignText(out, kring[0], message)
err := DetachSignText(out, kring[0], message, nil)
if err != nil {
t.Error(err)
}
@@ -41,7 +39,7 @@ func TestSignDetachedDSA(t *testing.T) {
kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex))
out := bytes.NewBuffer(nil)
message := bytes.NewBufferString(signedInput)
err := DetachSign(out, kring[0], message)
err := DetachSign(out, kring[0], message, nil)
if err != nil {
t.Error(err)
}
@@ -54,14 +52,14 @@ func TestNewEntity(t *testing.T) {
return
}
e, err := NewEntity(rand.Reader, time.Now(), "Test User", "test", "test@example.com")
e, err := NewEntity("Test User", "test", "test@example.com", nil)
if err != nil {
t.Errorf("failed to create entity: %s", err)
return
}
w := bytes.NewBuffer(nil)
if err := e.SerializePrivate(w); err != nil {
if err := e.SerializePrivate(w, nil); err != nil {
t.Errorf("failed to serialize entity: %s", err)
return
}
@@ -78,7 +76,7 @@ func TestNewEntity(t *testing.T) {
}
w = bytes.NewBuffer(nil)
if err := e.SerializePrivate(w); err != nil {
if err := e.SerializePrivate(w, nil); err != nil {
t.Errorf("failed to serialize entity second time: %s", err)
return
}
@@ -90,7 +88,7 @@ func TestNewEntity(t *testing.T) {
func TestSymmetricEncryption(t *testing.T) {
buf := new(bytes.Buffer)
plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil)
plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil, nil)
if err != nil {
t.Errorf("error writing headers: %s", err)
return
@@ -107,7 +105,7 @@ func TestSymmetricEncryption(t *testing.T) {
md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, error) {
return []byte("testing"), nil
})
}, nil)
if err != nil {
t.Errorf("error rereading message: %s", err)
}
@@ -171,7 +169,7 @@ func TestEncryption(t *testing.T) {
}
buf := new(bytes.Buffer)
w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */ )
w, err := Encrypt(buf, kring[:1], signed, nil, /* no hints */ nil)
if err != nil {
t.Errorf("#%d: error in Encrypt: %s", i, err)
continue
@@ -189,7 +187,7 @@ func TestEncryption(t *testing.T) {
continue
}
md, err := ReadMessage(buf, kring, nil /* no prompt */ )
md, err := ReadMessage(buf, kring, nil, /* no prompt */ nil)
if err != nil {
t.Errorf("#%d: error reading message: %s", i, err)
continue