Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/crypto/openpgp: Fixed failure to encrypt data using deserialized Entity #163

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions openpgp/packet/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ func (sig *Signature) parse(r io.Reader) (err error) {
return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
}

sig.PreferredHash = append(sig.PreferredHash, buf[2])

hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
l := 6 + hashedSubpacketsLength
sig.HashSuffix = make([]byte, l+6)
Expand Down
13 changes: 4 additions & 9 deletions openpgp/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
}

if hash == 0 {
hashId := candidateHashes[0]
hashId := candidateHashes[len(candidateHashes)-1]
name, ok := s2k.HashIdToString(hashId)
if !ok {
name = "#" + strconv.Itoa(int(hashId))
Expand Down Expand Up @@ -276,11 +276,6 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
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 {
Expand All @@ -294,11 +289,11 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint

preferredSymmetric := sig.PreferredSymmetric
if len(preferredSymmetric) == 0 {
preferredSymmetric = defaultCiphers
preferredSymmetric = candidateCiphers
}
preferredHashes := sig.PreferredHash
if len(preferredHashes) == 0 {
preferredHashes = defaultHashes
preferredHashes = candidateHashes
}
candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric)
candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
Expand All @@ -308,7 +303,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
}

cipher := packet.CipherFunction(candidateCiphers[0])
cipher := packet.CipherFunction(candidateCiphers[len(candidateCiphers)-1])
// If the cipher specified by config is a candidate, we'll use that.
configuredCipher := config.Cipher()
for _, c := range candidateCiphers {
Expand Down
76 changes: 76 additions & 0 deletions openpgp/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ package openpgp

import (
"bytes"
"crypto"
"golang.org/x/crypto/openpgp/armor"
"io"
"io/ioutil"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -272,6 +275,79 @@ func TestEncryption(t *testing.T) {
}
}

func TestSerialEncryption(t *testing.T) {
DefaultEncryptionConfig := func() *packet.Config {
return &packet.Config{
DefaultHash: crypto.SHA512,
DefaultCipher: packet.CipherAES256,
DefaultCompressionAlgo: packet.CompressionNone,
RSABits: 4096,
}
}

const MessageEncoding = "Message"

entity, _ := NewEntity("Name", "", "", DefaultEncryptionConfig())

// Remove Private Keys to share
r, w := io.Pipe()
defer r.Close()
go func() {
defer w.Close()
entity.Serialize(w)
}()
publicEntity, err := ReadEntity(packet.NewReader(r))
if err != nil {
t.Error(err)
}

messageSent := "Some message"
content := bytes.NewBuffer([]byte(messageSent))

println("Creating Message")
// Create an Encrypted Message to send
to := EntityList{publicEntity}
r, w = io.Pipe()
defer r.Close()

go func() {
defer w.Close()
w2, err := armor.Encode(w, MessageEncoding, make(map[string]string))
if err != nil {
t.Error(err)
}
defer w2.Close()

w3, err := Encrypt(w2, to, nil, nil, DefaultEncryptionConfig())
if err != nil {
t.Error(err)
return
}
defer w3.Close()

_, err = io.Copy(w3, content)
if err != nil {
t.Error(err)
}
}()

decode, err := armor.Decode(r)
if err != nil {
t.Error(err)
}
messageDetails, err := ReadMessage(decode.Body, EntityList{entity}, nil, DefaultEncryptionConfig())
if err != nil {
t.Error(err)
}
messageRead, err := ioutil.ReadAll(messageDetails.UnverifiedBody)
if err != nil {
t.Error(err)
}
if strings.Compare(messageSent, string(messageRead)) != 0 {
t.Errorf("Message sent isn't the same as message read\n'%s' != '%s'", messageSent, string(messageRead))
}
}

var testSigningTests = []struct {
keyRingHex string
}{
Expand Down