Improve error handling, fix linter (#92)

* Improve error handling, fix linter
This commit is contained in:
wussler 2020-10-29 12:42:32 +01:00 committed by GitHub
parent 6b2ac0b11c
commit 53a85837e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 194 additions and 186 deletions

View file

@ -29,3 +29,4 @@ linters:
- gofumpt # Enforce a stricter format than gofmt - gofumpt # Enforce a stricter format than gofmt
- gci # Enforce blank lines check - gci # Enforce blank lines check
- nlreturn # Enforce blank lines for return statements - nlreturn # Enforce blank lines for return statements
- exhaustivestruct # Enforce structures to be fully filled on instantiation - terrible with openpgp configs

View file

@ -97,6 +97,7 @@ NewPlainMessageFromFile(data []byte, filename string, modTime int) *PlainMessage
now accept private keys as public keys and perform automatic casting if the keys are locked. now accept private keys as public keys and perform automatic casting if the keys are locked.
- The `PlainMessage` struct now contains the fields `Filename` (string) and `Time` (uint32) - The `PlainMessage` struct now contains the fields `Filename` (string) and `Time` (uint32)
- All the Decrypt* functions return the filename, type, and time specified in the encrypted message - All the Decrypt* functions return the filename, type, and time specified in the encrypted message
- Improved error wrapping and management
### Fixed ### Fixed
- Public key armoring headers - Public key armoring headers

View file

@ -9,7 +9,7 @@ import (
"github.com/ProtonMail/gopenpgp/v2/constants" "github.com/ProtonMail/gopenpgp/v2/constants"
"github.com/ProtonMail/gopenpgp/v2/internal" "github.com/ProtonMail/gopenpgp/v2/internal"
"github.com/pkg/errors"
"golang.org/x/crypto/openpgp/armor" "golang.org/x/crypto/openpgp/armor"
) )
@ -46,7 +46,7 @@ func ArmorWithTypeAndCustomHeaders(input []byte, armorType, version, comment str
func Unarmor(input string) ([]byte, error) { func Unarmor(input string) ([]byte, error) {
b, err := internal.Unarmor(input) b, err := internal.Unarmor(input)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopengp: unable to unarmor")
} }
return ioutil.ReadAll(b.Body) return ioutil.ReadAll(b.Body)
} }
@ -57,13 +57,13 @@ func armorWithTypeAndHeaders(input []byte, armorType string, headers map[string]
w, err := armor.Encode(&b, armorType, headers) w, err := armor.Encode(&b, armorType, headers)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopengp: unable to encode armoring")
} }
if _, err = w.Write(input); err != nil { if _, err = w.Write(input); err != nil {
return "", err return "", errors.Wrap(err, "gopengp: unable to write armored to buffer")
} }
if err := w.Close(); err != nil { if err := w.Close(); err != nil {
return "", err return "", errors.Wrap(err, "gopengp: unable to close armor buffer")
} }
return b.String(), nil return b.String(), nil
} }

View file

@ -8,6 +8,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/pkg/errors"
"golang.org/x/crypto/openpgp" "golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
) )
@ -36,11 +37,11 @@ func (ap *AttachmentProcessor) Finish() (*PGPSplitMessage, error) {
return nil, ap.err return nil, ap.err
} }
if err := (*ap.w).Close(); err != nil { if err := (*ap.w).Close(); err != nil {
return nil, err return nil, errors.Wrap(err, "gopengpp: unable to close writer")
} }
if err := (*ap.pipe).Close(); err != nil { if err := (*ap.pipe).Close(); err != nil {
return nil, err return nil, errors.Wrap(err, "gopengpp: unable to close pipe")
} }
ap.done.Wait() ap.done.Wait()
@ -88,7 +89,7 @@ func (keyRing *KeyRing) newAttachmentProcessor(
var encryptErr error var encryptErr error
ew, encryptErr = openpgp.Encrypt(writer, keyRing.entities, nil, hints, config) ew, encryptErr = openpgp.Encrypt(writer, keyRing.entities, nil, hints, config)
if encryptErr != nil { if encryptErr != nil {
return nil, encryptErr return nil, errors.Wrap(encryptErr, "gopengpp: unable to encrypt attachment")
} }
attachmentProc.w = &ew attachmentProc.w = &ew
attachmentProc.pipe = writer attachmentProc.pipe = writer
@ -148,13 +149,13 @@ func (keyRing *KeyRing) DecryptAttachment(message *PGPSplitMessage) (*PlainMessa
md, err := openpgp.ReadMessage(encryptedReader, privKeyEntries, nil, config) md, err := openpgp.ReadMessage(encryptedReader, privKeyEntries, nil, config)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopengpp: unable to read attachment")
} }
decrypted := md.UnverifiedBody decrypted := md.UnverifiedBody
b, err := ioutil.ReadAll(decrypted) b, err := ioutil.ReadAll(decrypted)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopengpp: unable to read attachment body")
} }
return &PlainMessage{ return &PlainMessage{

View file

@ -186,7 +186,11 @@ func (key *Key) Serialize() ([]byte, error) {
err = key.entity.SerializePrivateWithoutSigning(&buffer, nil) err = key.entity.SerializePrivateWithoutSigning(&buffer, nil)
} }
return buffer.Bytes(), err if err != nil {
return nil, errors.Wrap(err, "gopenpgp: error in serializing key")
}
return buffer.Bytes(), nil
} }
// Armor returns the armored key as a string with default gopenpgp headers. // Armor returns the armored key as a string with default gopenpgp headers.
@ -235,7 +239,7 @@ func (key *Key) GetArmoredPublicKeyWithCustomHeaders(comment, version string) (s
func (key *Key) GetPublicKey() (b []byte, err error) { func (key *Key) GetPublicKey() (b []byte, err error) {
var outBuf bytes.Buffer var outBuf bytes.Buffer
if err = key.entity.Serialize(&outBuf); err != nil { if err = key.entity.Serialize(&outBuf); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in serializing public key")
} }
return outBuf.Bytes(), nil return outBuf.Bytes(), nil
@ -397,7 +401,7 @@ func (key *Key) readFrom(r io.Reader, armored bool) error {
entities, err = openpgp.ReadKeyRing(r) entities, err = openpgp.ReadKeyRing(r)
} }
if err != nil { if err != nil {
return err return errors.Wrap(err, "gopenpgp: error in reading key ring")
} }
if len(entities) > 1 { if len(entities) > 1 {
@ -456,7 +460,7 @@ func generateKey(
newEntity, err := openpgp.NewEntity(name, comments, email, cfg) newEntity, err := openpgp.NewEntity(name, comments, email, cfg)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopengpp: error in encoding new entity")
} }
if newEntity.PrivateKey == nil { if newEntity.PrivateKey == nil {

View file

@ -82,8 +82,7 @@ func (keyRing *KeyRing) getSigningEntity() (*openpgp.Entity, error) {
} }
} }
if signEntity == nil { if signEntity == nil {
err := errors.New("gopenpgp: cannot sign message, unable to unlock signer key") return nil, errors.New("gopenpgp: cannot sign message, unable to unlock signer key")
return signEntity, err
} }
return signEntity, nil return signEntity, nil

View file

@ -6,6 +6,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"github.com/pkg/errors"
"golang.org/x/crypto/openpgp" "golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
) )
@ -47,7 +48,7 @@ func (keyRing *KeyRing) SignDetached(message *PlainMessage) (*PGPSignature, erro
var outBuf bytes.Buffer var outBuf bytes.Buffer
// sign bin // sign bin
if err := openpgp.DetachSign(&outBuf, signEntity, message.NewReader(), config); err != nil { if err := openpgp.DetachSign(&outBuf, signEntity, message.NewReader(), config); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in signing")
} }
return NewPGPSignature(outBuf.Bytes()), nil return NewPGPSignature(outBuf.Bytes()), nil
@ -95,17 +96,17 @@ func asymmetricEncrypt(plainMessage *PlainMessage, publicKey, privateKey *KeyRin
encryptWriter, err = openpgp.EncryptText(&outBuf, publicKey.entities, signEntity, hints, config) encryptWriter, err = openpgp.EncryptText(&outBuf, publicKey.entities, signEntity, hints, config)
} }
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in encrypting asymmetrically")
} }
_, err = encryptWriter.Write(plainMessage.GetBinary()) _, err = encryptWriter.Write(plainMessage.GetBinary())
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in writing to message")
} }
err = encryptWriter.Close() err = encryptWriter.Close()
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in closing message")
} }
return outBuf.Bytes(), nil return outBuf.Bytes(), nil
@ -130,12 +131,12 @@ func asymmetricDecrypt(
messageDetails, err := openpgp.ReadMessage(encryptedIO, privKeyEntries, nil, config) messageDetails, err := openpgp.ReadMessage(encryptedIO, privKeyEntries, nil, config)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in reading message")
} }
body, err := ioutil.ReadAll(messageDetails.UnverifiedBody) body, err := ioutil.ReadAll(messageDetails.UnverifiedBody)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in reading message body")
} }
if verifyKey != nil { if verifyKey != nil {

View file

@ -2,7 +2,6 @@ package crypto
import ( import (
"bytes" "bytes"
"fmt"
"strconv" "strconv"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -18,7 +17,7 @@ func (keyRing *KeyRing) DecryptSessionKey(keyPacket []byte) (*SessionKey, error)
var p packet.Packet var p packet.Packet
var err error var err error
if p, err = packets.Next(); err != nil { if p, err = packets.Next(); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in reading packets")
} }
ek := p.(*packet.EncryptedKey) ek := p.(*packet.EncryptedKey)
@ -35,7 +34,7 @@ func (keyRing *KeyRing) DecryptSessionKey(keyPacket []byte) (*SessionKey, error)
} }
if decryptErr != nil { if decryptErr != nil {
return nil, decryptErr return nil, errors.Wrap(decryptErr, "gopenpgp: error in decrypting")
} }
if ek == nil { if ek == nil {
@ -68,8 +67,7 @@ func (keyRing *KeyRing) EncryptSessionKey(sk *SessionKey) ([]byte, error) {
for _, pub := range pubKeys { for _, pub := range pubKeys {
if err := packet.SerializeEncryptedKey(outbuf, pub, cf, sk.Key, nil); err != nil { if err := packet.SerializeEncryptedKey(outbuf, pub, cf, sk.Key, nil); err != nil {
err = fmt.Errorf("gopenpgp: cannot set key: %v", err) return nil, errors.Wrap(err, "gopenpgp: cannot set key")
return nil, err
} }
} }
return outbuf.Bytes(), nil return outbuf.Bytes(), nil

View file

@ -3,8 +3,7 @@ package crypto
import ( import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"errors" goerrors "errors"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"regexp" "regexp"
@ -15,7 +14,7 @@ import (
"github.com/ProtonMail/gopenpgp/v2/armor" "github.com/ProtonMail/gopenpgp/v2/armor"
"github.com/ProtonMail/gopenpgp/v2/constants" "github.com/ProtonMail/gopenpgp/v2/constants"
"github.com/ProtonMail/gopenpgp/v2/internal" "github.com/ProtonMail/gopenpgp/v2/internal"
"github.com/pkg/errors"
"golang.org/x/crypto/openpgp/clearsign" "golang.org/x/crypto/openpgp/clearsign"
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
) )
@ -68,6 +67,7 @@ func NewPlainMessage(data []byte) *PlainMessage {
return &PlainMessage{ return &PlainMessage{
Data: clone(data), Data: clone(data),
TextType: false, TextType: false,
Filename: "",
Time: uint32(GetUnixTime()), Time: uint32(GetUnixTime()),
} }
} }
@ -90,6 +90,7 @@ func NewPlainMessageFromString(text string) *PlainMessage {
return &PlainMessage{ return &PlainMessage{
Data: []byte(strings.ReplaceAll(strings.ReplaceAll(text, "\r\n", "\n"), "\n", "\r\n")), Data: []byte(strings.ReplaceAll(strings.ReplaceAll(text, "\r\n", "\n"), "\n", "\r\n")),
TextType: true, TextType: true,
Filename: "",
Time: uint32(GetUnixTime()), Time: uint32(GetUnixTime()),
} }
} }
@ -105,12 +106,12 @@ func NewPGPMessage(data []byte) *PGPMessage {
func NewPGPMessageFromArmored(armored string) (*PGPMessage, error) { func NewPGPMessageFromArmored(armored string) (*PGPMessage, error) {
encryptedIO, err := internal.Unarmor(armored) encryptedIO, err := internal.Unarmor(armored)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in unarmoring message")
} }
message, err := ioutil.ReadAll(encryptedIO.Body) message, err := ioutil.ReadAll(encryptedIO.Body)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in reading armored message")
} }
return &PGPMessage{ return &PGPMessage{
@ -150,12 +151,12 @@ func NewPGPSignature(data []byte) *PGPSignature {
func NewPGPSignatureFromArmored(armored string) (*PGPSignature, error) { func NewPGPSignatureFromArmored(armored string) (*PGPSignature, error) {
encryptedIO, err := internal.Unarmor(armored) encryptedIO, err := internal.Unarmor(armored)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in unarmoring signature")
} }
signature, err := ioutil.ReadAll(encryptedIO.Body) signature, err := ioutil.ReadAll(encryptedIO.Body)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in reading armored signature")
} }
return &PGPSignature{ return &PGPSignature{
@ -182,7 +183,7 @@ func NewClearTextMessageFromArmored(signedMessage string) (*ClearTextMessage, er
signature, err := ioutil.ReadAll(modulusBlock.ArmoredSignature.Body) signature, err := ioutil.ReadAll(modulusBlock.ArmoredSignature.Body)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in reading cleartext message")
} }
return NewClearTextMessage(modulusBlock.Bytes, signature), nil return NewClearTextMessage(modulusBlock.Bytes, signature), nil
@ -257,7 +258,7 @@ func (msg *PGPMessage) GetEncryptionKeyIDs() ([]uint64, bool) {
Loop: Loop:
for { for {
var p packet.Packet var p packet.Packet
if p, err = packets.Next(); err == io.EOF { if p, err = packets.Next(); goerrors.Is(err, io.EOF) {
break break
} }
switch p := p.(type) { switch p := p.(type) {
@ -333,7 +334,7 @@ func (msg *PGPMessage) SeparateKeyAndData(estimatedLength, garbageCollector int)
var encryptedKey *packet.EncryptedKey var encryptedKey *packet.EncryptedKey
for { for {
var p packet.Packet var p packet.Packet
if p, err = packets.Next(); err == io.EOF { if p, err = packets.Next(); goerrors.Is(err, io.EOF) {
err = nil err = nil
break break
} }
@ -354,22 +355,22 @@ func (msg *PGPMessage) SeparateKeyAndData(estimatedLength, garbageCollector int)
b.Grow(1<<16 + estimatedLength) b.Grow(1<<16 + estimatedLength)
// empty encoded length + start byte // empty encoded length + start byte
if _, err := b.Write(make([]byte, 6)); err != nil { if _, err := b.Write(make([]byte, 6)); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in writing data packet header")
} }
if err := b.WriteByte(byte(1)); err != nil { if err := b.WriteByte(byte(1)); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in writing data packet header")
} }
actualLength := 1 actualLength := 1
block := make([]byte, 128) block := make([]byte, 128)
for { for {
n, err := p.Contents.Read(block) n, err := p.Contents.Read(block)
if err == io.EOF { if goerrors.Is(err, io.EOF) {
break break
} }
if _, err := b.Write(block[:n]); err != nil { if _, err := b.Write(block[:n]); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in writing data packet body")
} }
actualLength += n actualLength += n
gcCounter += n gcCounter += n
@ -409,7 +410,7 @@ func (msg *PGPMessage) SeparateKeyAndData(estimatedLength, garbageCollector int)
var buf bytes.Buffer var buf bytes.Buffer
if err := encryptedKey.Serialize(&buf); err != nil { if err := encryptedKey.Serialize(&buf); err != nil {
return nil, fmt.Errorf("gopenpgp: cannot serialize encrypted key: %v", err) return nil, errors.Wrap(err, "gopenpgp: cannot serialize encrypted key")
} }
outSplit.KeyPacket = buf.Bytes() outSplit.KeyPacket = buf.Bytes()
@ -456,7 +457,7 @@ func (msg *ClearTextMessage) GetBinarySignature() []byte {
func (msg *ClearTextMessage) GetArmored() (string, error) { func (msg *ClearTextMessage) GetArmored() (string, error) {
armSignature, err := armor.ArmorWithType(msg.GetBinarySignature(), constants.PGPSignatureHeader) armSignature, err := armor.ArmorWithType(msg.GetBinarySignature(), constants.PGPSignatureHeader)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: error in armoring cleartext message")
} }
str := "-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: SHA512\r\n\r\n" str := "-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: SHA512\r\n\r\n"
@ -486,7 +487,7 @@ func getSignatureKeyIDs(data []byte) ([]uint64, bool) {
Loop: Loop:
for { for {
var p packet.Packet var p packet.Packet
if p, err = packets.Next(); err == io.EOF { if p, err = packets.Next(); goerrors.Is(err, io.EOF) {
break break
} }
switch p := p.(type) { switch p := p.(type) {

View file

@ -3,6 +3,7 @@ package crypto
import ( import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"errors"
"io" "io"
"testing" "testing"
"time" "time"
@ -24,7 +25,7 @@ func TestTextMessageEncryptionWithPassword(t *testing.T) {
for { for {
var p packet.Packet var p packet.Packet
var errEOF error var errEOF error
if p, errEOF = packets.Next(); errEOF == io.EOF { if p, errEOF = packets.Next(); errors.Is(errEOF, io.EOF) {
break break
} }
sessionKey, ok := p.(*packet.SymmetricKeyEncrypted) sessionKey, ok := p.(*packet.SymmetricKeyEncrypted)
@ -138,7 +139,7 @@ func TestIssue11(t *testing.T) {
issue11Keyring, err := NewKeyRing(issue11Key) issue11Keyring, err := NewKeyRing(issue11Key)
if err != nil { if err != nil {
t.Fatal("Expected no error while bulding private keyring, got:", err) t.Fatal("Expected no error while building private keyring, got:", err)
} }
senderKey, err := NewKeyFromArmored(readTestFile("issue11_publickey", false)) senderKey, err := NewKeyFromArmored(readTestFile("issue11_publickey", false))
@ -154,7 +155,7 @@ func TestIssue11(t *testing.T) {
pgpMessage, err := NewPGPMessageFromArmored(readTestFile("issue11_message", false)) pgpMessage, err := NewPGPMessageFromArmored(readTestFile("issue11_message", false))
if err != nil { if err != nil {
t.Fatal("Expected no error while unlocking private keyring, got:", err) t.Fatal("Expected no error while reading ciphertext, got:", err)
} }
plainMessage, err := issue11Keyring.Decrypt(pgpMessage, senderKeyring, 0) plainMessage, err := issue11Keyring.Decrypt(pgpMessage, senderKeyring, 0)

View file

@ -8,7 +8,7 @@ import (
"strings" "strings"
gomime "github.com/ProtonMail/go-mime" gomime "github.com/ProtonMail/go-mime"
"github.com/pkg/errors"
"golang.org/x/crypto/openpgp" "golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
) )
@ -53,14 +53,14 @@ func parseMIME(
) (*gomime.BodyCollector, []string, []string, error) { ) (*gomime.BodyCollector, []string, []string, error) {
mm, err := mail.ReadMessage(strings.NewReader(mimeBody)) mm, err := mail.ReadMessage(strings.NewReader(mimeBody))
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, errors.Wrap(err, "gopenpgp: error in reading message")
} }
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: getTimeGenerator()} config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: getTimeGenerator()}
h := textproto.MIMEHeader(mm.Header) h := textproto.MIMEHeader(mm.Header)
mmBodyData, err := ioutil.ReadAll(mm.Body) mmBodyData, err := ioutil.ReadAll(mm.Body)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, errors.Wrap(err, "gopenpgp: error in reading message body data")
} }
printAccepter := gomime.NewMIMEPrinter() printAccepter := gomime.NewMIMEPrinter()

View file

@ -119,16 +119,16 @@ func passwordEncrypt(message *PlainMessage, password []byte) ([]byte, error) {
encryptWriter, err := openpgp.SymmetricallyEncrypt(&outBuf, password, hints, config) encryptWriter, err := openpgp.SymmetricallyEncrypt(&outBuf, password, hints, config)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in encrypting message symmetrically")
} }
_, err = encryptWriter.Write(message.GetBinary()) _, err = encryptWriter.Write(message.GetBinary())
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in writing data to message")
} }
err = encryptWriter.Close() err = encryptWriter.Close()
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in closing writer")
} }
return outBuf.Bytes(), nil return outBuf.Bytes(), nil
@ -151,13 +151,13 @@ func passwordDecrypt(encryptedIO io.Reader, password []byte) (*PlainMessage, err
var emptyKeyRing openpgp.EntityList var emptyKeyRing openpgp.EntityList
md, err := openpgp.ReadMessage(encryptedIO, emptyKeyRing, prompt, config) md, err := openpgp.ReadMessage(encryptedIO, emptyKeyRing, prompt, config)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in reading password protected message")
} }
messageBuf := bytes.NewBuffer(nil) messageBuf := bytes.NewBuffer(nil)
_, err = io.Copy(messageBuf, md.UnverifiedBody) _, err = io.Copy(messageBuf, md.UnverifiedBody)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in reading password protected message body")
} }
return &PlainMessage{ return &PlainMessage{

View file

@ -50,7 +50,7 @@ func RandomToken(size int) ([]byte, error) {
config := &packet.Config{DefaultCipher: packet.CipherAES256} config := &packet.Config{DefaultCipher: packet.CipherAES256}
symKey := make([]byte, size) symKey := make([]byte, size)
if _, err := io.ReadFull(config.Random(), symKey); err != nil { if _, err := io.ReadFull(config.Random(), symKey); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in generating random token")
} }
return symKey, nil return symKey, nil
} }
@ -152,12 +152,12 @@ func (sk *SessionKey) Encrypt(message *PlainMessage) ([]byte, error) {
_, err = encryptWriter.Write(message.GetBinary()) _, err = encryptWriter.Write(message.GetBinary())
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in writing message")
} }
err = encryptWriter.Close() err = encryptWriter.Close()
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in closing message")
} }
return encBuf.Bytes(), nil return encBuf.Bytes(), nil
@ -213,7 +213,7 @@ func (sk *SessionKey) Decrypt(dataPacket []byte) (*PlainMessage, error) {
messageBuf := new(bytes.Buffer) messageBuf := new(bytes.Buffer)
_, err = messageBuf.ReadFrom(md.UnverifiedBody) _, err = messageBuf.ReadFrom(md.UnverifiedBody)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: error in reading message body")
} }
return &PlainMessage{ return &PlainMessage{
@ -221,7 +221,7 @@ func (sk *SessionKey) Decrypt(dataPacket []byte) (*PlainMessage, error) {
TextType: !md.LiteralData.IsBinary, TextType: !md.LiteralData.IsBinary,
Filename: md.LiteralData.FileName, Filename: md.LiteralData.FileName,
Time: md.LiteralData.Time, Time: md.LiteralData.Time,
}, err }, nil
} }
func (sk *SessionKey) checkSize() error { func (sk *SessionKey) checkSize() error {

View file

@ -3,6 +3,7 @@ package crypto
import ( import (
"bytes" "bytes"
"crypto" "crypto"
"errors"
"fmt" "fmt"
"io" "io"
"math" "math"
@ -43,8 +44,8 @@ func (e SignatureVerificationError) Error() string {
// SignatureFailed. // SignatureFailed.
func newSignatureFailed() SignatureVerificationError { func newSignatureFailed() SignatureVerificationError {
return SignatureVerificationError{ return SignatureVerificationError{
constants.SIGNATURE_FAILED, Status: constants.SIGNATURE_FAILED,
"Invalid signature", Message: "Invalid signature",
} }
} }
@ -52,8 +53,8 @@ func newSignatureFailed() SignatureVerificationError {
// SignatureFailed, with a message describing the signature as insecure. // SignatureFailed, with a message describing the signature as insecure.
func newSignatureInsecure() SignatureVerificationError { func newSignatureInsecure() SignatureVerificationError {
return SignatureVerificationError{ return SignatureVerificationError{
constants.SIGNATURE_FAILED, Status: constants.SIGNATURE_FAILED,
"Insecure signature", Message: "Insecure signature",
} }
} }
@ -61,8 +62,8 @@ func newSignatureInsecure() SignatureVerificationError {
// SignatureNotSigned. // SignatureNotSigned.
func newSignatureNotSigned() SignatureVerificationError { func newSignatureNotSigned() SignatureVerificationError {
return SignatureVerificationError{ return SignatureVerificationError{
constants.SIGNATURE_NOT_SIGNED, Status: constants.SIGNATURE_NOT_SIGNED,
"Missing signature", Message: "Missing signature",
} }
} }
@ -70,15 +71,15 @@ func newSignatureNotSigned() SignatureVerificationError {
// SignatureNoVerifier. // SignatureNoVerifier.
func newSignatureNoVerifier() SignatureVerificationError { func newSignatureNoVerifier() SignatureVerificationError {
return SignatureVerificationError{ return SignatureVerificationError{
constants.SIGNATURE_NO_VERIFIER, Status: constants.SIGNATURE_NO_VERIFIER,
"No matching signature", Message: "No matching signature",
} }
} }
// processSignatureExpiration handles signature time verification manually, so // processSignatureExpiration handles signature time verification manually, so
// we can add a margin to the creationTime check. // we can add a margin to the creationTime check.
func processSignatureExpiration(md *openpgp.MessageDetails, verifyTime int64) { func processSignatureExpiration(md *openpgp.MessageDetails, verifyTime int64) {
if md.SignatureError != pgpErrors.ErrSignatureExpired { if !errors.Is(md.SignatureError, pgpErrors.ErrSignatureExpired) {
return return
} }
if verifyTime == 0 { if verifyTime == 0 {
@ -131,7 +132,7 @@ func verifySignature(pubKeyEntries openpgp.EntityList, origText io.Reader, signa
signer, err := openpgp.CheckDetachedSignatureAndHash(pubKeyEntries, origText, signatureReader, allowedHashes, config) signer, err := openpgp.CheckDetachedSignatureAndHash(pubKeyEntries, origText, signatureReader, allowedHashes, config)
if err == pgpErrors.ErrSignatureExpired && signer != nil && verifyTime > 0 { if errors.Is(err, pgpErrors.ErrSignatureExpired) && signer != nil && verifyTime > 0 {
// if verifyTime = 0: time check disabled, everything is okay // if verifyTime = 0: time check disabled, everything is okay
// Maybe the creation time offset pushed it over the edge // Maybe the creation time offset pushed it over the edge
// Retry with the actual verification time // Retry with the actual verification time

View file

@ -8,7 +8,7 @@ import (
"net/textproto" "net/textproto"
gomime "github.com/ProtonMail/go-mime" gomime "github.com/ProtonMail/go-mime"
"github.com/pkg/errors"
"golang.org/x/crypto/openpgp" "golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
) )
@ -58,7 +58,7 @@ func (sc *SignatureCollector) Accept(
sc.verified = newSignatureNotSigned() sc.verified = newSignatureNotSigned()
// Invalid multipart/signed format just pass along // Invalid multipart/signed format just pass along
if _, err = ioutil.ReadAll(rawBody); err != nil { if _, err = ioutil.ReadAll(rawBody); err != nil {
return err return errors.Wrap(err, "gopenpgp: error in reading raw message body")
} }
for i, p := range multiparts { for i, p := range multiparts {
@ -72,12 +72,12 @@ func (sc *SignatureCollector) Accept(
// actual multipart/signed format // actual multipart/signed format
err = sc.target.Accept(multiparts[0], multipartHeaders[0], hasPlainChild, true, true) err = sc.target.Accept(multiparts[0], multipartHeaders[0], hasPlainChild, true, true)
if err != nil { if err != nil {
return err return errors.Wrap(err, "gopenpgp: error in parsing body")
} }
partData, err := ioutil.ReadAll(multiparts[1]) partData, err := ioutil.ReadAll(multiparts[1])
if err != nil { if err != nil {
return err return errors.Wrap(err, "gopenpgp: error in ready part data")
} }
decodedPart := gomime.DecodeContentEncoding( decodedPart := gomime.DecodeContentEncoding(
@ -86,12 +86,12 @@ func (sc *SignatureCollector) Accept(
buffer, err := ioutil.ReadAll(decodedPart) buffer, err := ioutil.ReadAll(decodedPart)
if err != nil { if err != nil {
return err return errors.Wrap(err, "gopenpgp: error in reading decoded data")
} }
mediaType, _, _ := mime.ParseMediaType(header.Get("Content-Type")) mediaType, _, _ := mime.ParseMediaType(header.Get("Content-Type"))
buffer, err = gomime.DecodeCharset(buffer, mediaType, params) buffer, err = gomime.DecodeCharset(buffer, mediaType, params)
if err != nil { if err != nil {
return err return errors.Wrap(err, "gopenpgp: error in decoding charset")
} }
sc.signature = string(buffer) sc.signature = string(buffer)
str, _ := ioutil.ReadAll(rawBody) str, _ := ioutil.ReadAll(rawBody)
@ -107,7 +107,8 @@ func (sc *SignatureCollector) Accept(
} else { } else {
sc.verified = newSignatureNoVerifier() sc.verified = newSignatureNoVerifier()
} }
return err
return nil
} }
// GetSignature collected by Accept. // GetSignature collected by Accept.

View file

@ -1,6 +1,7 @@
package crypto package crypto
import ( import (
"errors"
"regexp" "regexp"
"testing" "testing"
@ -44,7 +45,8 @@ func TestVerifyTextDetachedSigWrong(t *testing.T) {
assert.EqualError(t, verificationError, "Signature Verification Error: Invalid signature") assert.EqualError(t, verificationError, "Signature Verification Error: Invalid signature")
err, _ := verificationError.(SignatureVerificationError) err := &SignatureVerificationError{}
_ = errors.As(verificationError, err)
assert.Exactly(t, constants.SIGNATURE_FAILED, err.Status) assert.Exactly(t, constants.SIGNATURE_FAILED, err.Status)
} }

View file

@ -3,6 +3,7 @@ package helper
import ( import (
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/gopenpgp/v2/internal" "github.com/ProtonMail/gopenpgp/v2/internal"
"github.com/pkg/errors"
) )
// SignCleartextMessageArmored signs text given a private key and its // SignCleartextMessageArmored signs text given a private key and its
@ -11,18 +12,18 @@ import (
func SignCleartextMessageArmored(privateKey string, passphrase []byte, text string) (string, error) { func SignCleartextMessageArmored(privateKey string, passphrase []byte, text string) (string, error) {
signingKey, err := crypto.NewKeyFromArmored(privateKey) signingKey, err := crypto.NewKeyFromArmored(privateKey)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: error in creating key object")
} }
unlockedKey, err := signingKey.Unlock(passphrase) unlockedKey, err := signingKey.Unlock(passphrase)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: error in unlocking key")
} }
defer unlockedKey.ClearPrivateParams() defer unlockedKey.ClearPrivateParams()
keyRing, err := crypto.NewKeyRing(unlockedKey) keyRing, err := crypto.NewKeyRing(unlockedKey)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: error in creating keyring")
} }
return SignCleartextMessage(keyRing, text) return SignCleartextMessage(keyRing, text)
@ -34,12 +35,12 @@ func SignCleartextMessageArmored(privateKey string, passphrase []byte, text stri
func VerifyCleartextMessageArmored(publicKey, armored string, verifyTime int64) (string, error) { func VerifyCleartextMessageArmored(publicKey, armored string, verifyTime int64) (string, error) {
signingKey, err := crypto.NewKeyFromArmored(publicKey) signingKey, err := crypto.NewKeyFromArmored(publicKey)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: error in creating key object")
} }
verifyKeyRing, err := crypto.NewKeyRing(signingKey) verifyKeyRing, err := crypto.NewKeyRing(signingKey)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: error in creating key ring")
} }
return VerifyCleartextMessage(verifyKeyRing, armored, verifyTime) return VerifyCleartextMessage(verifyKeyRing, armored, verifyTime)
@ -53,7 +54,7 @@ func SignCleartextMessage(keyRing *crypto.KeyRing, text string) (string, error)
signature, err := keyRing.SignDetached(message) signature, err := keyRing.SignDetached(message)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: error in signing cleartext message")
} }
return crypto.NewClearTextMessage(message.GetBinary(), signature.GetBinary()).GetArmored() return crypto.NewClearTextMessage(message.GetBinary(), signature.GetBinary()).GetArmored()
@ -65,14 +66,14 @@ func SignCleartextMessage(keyRing *crypto.KeyRing, text string) (string, error)
func VerifyCleartextMessage(keyRing *crypto.KeyRing, armored string, verifyTime int64) (string, error) { func VerifyCleartextMessage(keyRing *crypto.KeyRing, armored string, verifyTime int64) (string, error) {
clearTextMessage, err := crypto.NewClearTextMessageFromArmored(armored) clearTextMessage, err := crypto.NewClearTextMessageFromArmored(armored)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopengpp: unable to unarmor cleartext message")
} }
message := crypto.NewPlainMessageFromString(clearTextMessage.GetString()) message := crypto.NewPlainMessageFromString(clearTextMessage.GetString())
signature := crypto.NewPGPSignature(clearTextMessage.GetBinarySignature()) signature := crypto.NewPGPSignature(clearTextMessage.GetBinarySignature())
err = keyRing.VerifyDetached(message, signature, verifyTime) err = keyRing.VerifyDetached(message, signature, verifyTime)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopengpp: unable to verify cleartext message")
} }
return message.GetString(), nil return message.GetString(), nil

View file

@ -2,9 +2,8 @@
package helper package helper
import ( import (
"errors"
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/pkg/errors"
) )
// EncryptMessageWithPassword encrypts a string with a passphrase using AES256. // EncryptMessageWithPassword encrypts a string with a passphrase using AES256.
@ -14,11 +13,11 @@ func EncryptMessageWithPassword(password []byte, plaintext string) (ciphertext s
var message = crypto.NewPlainMessageFromString(plaintext) var message = crypto.NewPlainMessageFromString(plaintext)
if pgpMessage, err = crypto.EncryptMessageWithPassword(message, password); err != nil { if pgpMessage, err = crypto.EncryptMessageWithPassword(message, password); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to encrypt message with password")
} }
if ciphertext, err = pgpMessage.GetArmored(); err != nil { if ciphertext, err = pgpMessage.GetArmored(); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to armor ciphertext")
} }
return ciphertext, nil return ciphertext, nil
@ -31,11 +30,11 @@ func DecryptMessageWithPassword(password []byte, ciphertext string) (plaintext s
var pgpMessage *crypto.PGPMessage var pgpMessage *crypto.PGPMessage
if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil { if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to unarmor ciphertext")
} }
if message, err = crypto.DecryptMessageWithPassword(pgpMessage, password); err != nil { if message, err = crypto.DecryptMessageWithPassword(pgpMessage, password); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to decrypt message with password")
} }
return message.GetString(), nil return message.GetString(), nil
@ -63,24 +62,24 @@ func EncryptSignMessageArmored(
} }
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil { if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to read key")
} }
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil { if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to unlock key")
} }
defer unlockedKeyObj.ClearPrivateParams() defer unlockedKeyObj.ClearPrivateParams()
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil { if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to create new keyring")
} }
if pgpMessage, err = publicKeyRing.Encrypt(message, privateKeyRing); err != nil { if pgpMessage, err = publicKeyRing.Encrypt(message, privateKeyRing); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to encrypt message")
} }
if ciphertext, err = pgpMessage.GetArmored(); err != nil { if ciphertext, err = pgpMessage.GetArmored(); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to armor ciphertext")
} }
return ciphertext, nil return ciphertext, nil
@ -116,24 +115,24 @@ func DecryptVerifyMessageArmored(
} }
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil { if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to unarmor private key")
} }
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil { if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to unlock private key")
} }
defer unlockedKeyObj.ClearPrivateParams() defer unlockedKeyObj.ClearPrivateParams()
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil { if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to create new keyring")
} }
if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil { if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to unarmor ciphertext")
} }
if message, err = privateKeyRing.Decrypt(pgpMessage, publicKeyRing, crypto.GetUnixTime()); err != nil { if message, err = privateKeyRing.Decrypt(pgpMessage, publicKeyRing, crypto.GetUnixTime()); err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to decrypt message")
} }
return message.GetString(), nil return message.GetString(), nil
@ -191,31 +190,31 @@ func encryptSignArmoredDetached(
publicKey, privateKey string, publicKey, privateKey string,
passphrase, plainData []byte, passphrase, plainData []byte,
) (ciphertext, encryptedSignature string, err error) { ) (ciphertext, encryptedSignature string, err error) {
var message *crypto.PlainMessage = crypto.NewPlainMessage(plainData) var message = crypto.NewPlainMessage(plainData)
// We generate the session key // We generate the session key
sessionKey, err := crypto.GenerateSessionKey() sessionKey, err := crypto.GenerateSessionKey()
if err != nil { if err != nil {
return "", "", err return "", "", errors.Wrap(err, "gopenpgp: unable to generate session key")
} }
// We encrypt the message with the session key // We encrypt the message with the session key
messageDataPacket, err := sessionKey.Encrypt(message) messageDataPacket, err := sessionKey.Encrypt(message)
if err != nil { if err != nil {
return "", "", err return "", "", errors.Wrap(err, "gopenpgp: unable to encrypt message")
} }
// We sign the message // We sign the message
detachedSignature, err := signDetached(privateKey, passphrase, message) detachedSignature, err := signDetached(privateKey, passphrase, message)
if err != nil { if err != nil {
return "", "", err return "", "", errors.Wrap(err, "gopenpgp: unable to sign the message")
} }
// We encrypt the signature with the session key // We encrypt the signature with the session key
signaturePlaintext := crypto.NewPlainMessage(detachedSignature.GetBinary()) signaturePlaintext := crypto.NewPlainMessage(detachedSignature.GetBinary())
signatureDataPacket, err := sessionKey.Encrypt(signaturePlaintext) signatureDataPacket, err := sessionKey.Encrypt(signaturePlaintext)
if err != nil { if err != nil {
return "", "", err return "", "", errors.Wrap(err, "gopenpgp: unable to encrypt signature")
} }
// We encrypt the session key // We encrypt the session key
@ -227,11 +226,11 @@ func encryptSignArmoredDetached(
// We join the key packets and datapackets and armor the message // We join the key packets and datapackets and armor the message
ciphertext, err = crypto.NewPGPSplitMessage(keyPacket, messageDataPacket).GetArmored() ciphertext, err = crypto.NewPGPSplitMessage(keyPacket, messageDataPacket).GetArmored()
if err != nil { if err != nil {
return "", "", err return "", "", errors.Wrap(err, "gopenpgp: unable to armor message")
} }
encryptedSignature, err = crypto.NewPGPSplitMessage(keyPacket, signatureDataPacket).GetArmored() encryptedSignature, err = crypto.NewPGPSplitMessage(keyPacket, signatureDataPacket).GetArmored()
if err != nil { if err != nil {
return "", "", err return "", "", errors.Wrap(err, "gopenpgp: unable to armor signature")
} }
return ciphertext, encryptedSignature, nil return ciphertext, encryptedSignature, nil
@ -323,45 +322,44 @@ func DecryptSessionKey(
passphrase, encryptedSessionKey []byte, passphrase, encryptedSessionKey []byte,
) (sessionKey *crypto.SessionKey, err error) { ) (sessionKey *crypto.SessionKey, err error) {
privateKeyObj, err := crypto.NewKeyFromArmored(privateKey) privateKeyObj, err := crypto.NewKeyFromArmored(privateKey)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to read armored key")
} }
privateKeyUnlocked, err := privateKeyObj.Unlock(passphrase) privateKeyUnlocked, err := privateKeyObj.Unlock(passphrase)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to unlock private key")
} }
defer privateKeyUnlocked.ClearPrivateParams() defer privateKeyUnlocked.ClearPrivateParams()
privateKeyRing, err := crypto.NewKeyRing(privateKeyUnlocked) privateKeyRing, err := crypto.NewKeyRing(privateKeyUnlocked)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to create new keyring")
} }
sessionKey, err = privateKeyRing.DecryptSessionKey(encryptedSessionKey) sessionKey, err = privateKeyRing.DecryptSessionKey(encryptedSessionKey)
return if err != nil {
return nil, errors.Wrap(err, "gopenpgp: unable to decrypt session key")
}
return sessionKey, nil
} }
func encryptMessageArmored(key string, message *crypto.PlainMessage) (string, error) { func encryptMessageArmored(key string, message *crypto.PlainMessage) (string, error) {
publicKeyRing, err := createPublicKeyRing(key) publicKeyRing, err := createPublicKeyRing(key)
if err != nil { if err != nil {
return "", err return "", err
} }
pgpMessage, err := publicKeyRing.Encrypt(message, nil) pgpMessage, err := publicKeyRing.Encrypt(message, nil)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to encrypt message")
} }
ciphertext, err := pgpMessage.GetArmored() ciphertext, err := pgpMessage.GetArmored()
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to armor message")
} }
return ciphertext, nil return ciphertext, nil
@ -369,35 +367,30 @@ func encryptMessageArmored(key string, message *crypto.PlainMessage) (string, er
func decryptMessageArmored(privateKey string, passphrase []byte, ciphertext string) (*crypto.PlainMessage, error) { func decryptMessageArmored(privateKey string, passphrase []byte, ciphertext string) (*crypto.PlainMessage, error) {
privateKeyObj, err := crypto.NewKeyFromArmored(privateKey) privateKeyObj, err := crypto.NewKeyFromArmored(privateKey)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to parse private key")
} }
privateKeyUnlocked, err := privateKeyObj.Unlock(passphrase) privateKeyUnlocked, err := privateKeyObj.Unlock(passphrase)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to unlock private key")
} }
defer privateKeyUnlocked.ClearPrivateParams() defer privateKeyUnlocked.ClearPrivateParams()
privateKeyRing, err := crypto.NewKeyRing(privateKeyUnlocked) privateKeyRing, err := crypto.NewKeyRing(privateKeyUnlocked)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to create new keyring")
} }
pgpMessage, err := crypto.NewPGPMessageFromArmored(ciphertext) pgpMessage, err := crypto.NewPGPMessageFromArmored(ciphertext)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to unarmor ciphertext")
} }
message, err := privateKeyRing.Decrypt(pgpMessage, nil, 0) message, err := privateKeyRing.Decrypt(pgpMessage, nil, 0)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to decrypt message")
} }
return message, nil return message, nil
@ -405,29 +398,25 @@ func decryptMessageArmored(privateKey string, passphrase []byte, ciphertext stri
func signDetached(privateKey string, passphrase []byte, message *crypto.PlainMessage) (detachedSignature *crypto.PGPSignature, err error) { func signDetached(privateKey string, passphrase []byte, message *crypto.PlainMessage) (detachedSignature *crypto.PGPSignature, err error) {
privateKeyObj, err := crypto.NewKeyFromArmored(privateKey) privateKeyObj, err := crypto.NewKeyFromArmored(privateKey)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to parse private key")
} }
privateKeyUnlocked, err := privateKeyObj.Unlock(passphrase) privateKeyUnlocked, err := privateKeyObj.Unlock(passphrase)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to unlock key")
} }
defer privateKeyUnlocked.ClearPrivateParams() defer privateKeyUnlocked.ClearPrivateParams()
privateKeyRing, err := crypto.NewKeyRing(privateKeyUnlocked) privateKeyRing, err := crypto.NewKeyRing(privateKeyUnlocked)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to create new keyring")
} }
detachedSignature, err = privateKeyRing.SignDetached(message) detachedSignature, err = privateKeyRing.SignDetached(message)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to sign message")
} }
return detachedSignature, nil return detachedSignature, nil
@ -438,7 +427,7 @@ func verifyDetachedArmored(publicKey string, message *crypto.PlainMessage, armor
// We unarmor the signature // We unarmor the signature
if detachedSignature, err = crypto.NewPGPSignatureFromArmored(armoredSignature); err != nil { if detachedSignature, err = crypto.NewPGPSignatureFromArmored(armoredSignature); err != nil {
return false, err return false, errors.Wrap(err, "gopenpgp: unable to unarmor signature")
} }
// we verify the signature // we verify the signature
return verifyDetached(publicKey, message, detachedSignature) return verifyDetached(publicKey, message, detachedSignature)
@ -471,40 +460,41 @@ func decryptAttachment(
// prepare the private key for decryption // prepare the private key for decryption
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil { if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to parse private key")
} }
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil { if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to unlock private key")
} }
defer unlockedKeyObj.ClearPrivateParams() defer unlockedKeyObj.ClearPrivateParams()
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil { if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to create new keyring")
} }
if message, err = privateKeyRing.DecryptAttachment(packets); err != nil { if message, err = privateKeyRing.DecryptAttachment(packets); err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to decrypt attachment")
} }
return message, nil return message, nil
} }
func createPublicKeyRing( func createPublicKeyRing(publicKey string) (*crypto.KeyRing, error) {
publicKey string,
) (publicKeyRing *crypto.KeyRing, err error) {
publicKeyObj, err := crypto.NewKeyFromArmored(publicKey) publicKeyObj, err := crypto.NewKeyFromArmored(publicKey)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to parse public key")
} }
if publicKeyObj.IsPrivate() { if publicKeyObj.IsPrivate() {
publicKeyObj, err = publicKeyObj.ToPublic() publicKeyObj, err = publicKeyObj.ToPublic()
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to extract public key from private key")
} }
} }
publicKeyRing, err = crypto.NewKeyRing(publicKeyObj) publicKeyRing, err := crypto.NewKeyRing(publicKeyObj)
return if err != nil {
return nil, errors.Wrap(err, "gopenpgp: unable to create new keyring")
}
return publicKeyRing, nil
} }

View file

@ -18,7 +18,8 @@ func TestAESEncryption(t *testing.T) {
} }
_, err = DecryptMessageWithPassword([]byte("Wrong passphrase"), ciphertext) _, err = DecryptMessageWithPassword([]byte("Wrong passphrase"), ciphertext)
assert.EqualError(t, err, "gopenpgp: wrong password in symmetric decryption") assert.EqualError(t, err, "gopenpgp: unable to decrypt message with password: "+
"gopenpgp: error in reading password protected message: gopenpgp: wrong password in symmetric decryption")
decrypted, err := DecryptMessageWithPassword(passphrase, ciphertext) decrypted, err := DecryptMessageWithPassword(passphrase, ciphertext)
if err != nil { if err != nil {
@ -71,7 +72,7 @@ func TestArmoredTextMessageEncryptionVerification(t *testing.T) {
testMailboxPassword, // Password defined in base_test testMailboxPassword, // Password defined in base_test
armored, armored,
) )
assert.EqualError(t, err, "Signature Verification Error: No matching signature") assert.EqualError(t, err, "gopenpgp: unable to decrypt message: Signature Verification Error: No matching signature")
decrypted, err := DecryptVerifyMessageArmored( decrypted, err := DecryptVerifyMessageArmored(
readTestFile("keyring_privateKey", false), readTestFile("keyring_privateKey", false),

View file

@ -2,6 +2,7 @@ package helper
import ( import (
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/pkg/errors"
) )
// UpdatePrivateKeyPassphrase decrypts the given armored privateKey with oldPassphrase, // UpdatePrivateKeyPassphrase decrypts the given armored privateKey with oldPassphrase,
@ -12,21 +13,26 @@ func UpdatePrivateKeyPassphrase(
) (string, error) { ) (string, error) {
key, err := crypto.NewKeyFromArmored(privateKey) key, err := crypto.NewKeyFromArmored(privateKey)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to parse key")
} }
unlocked, err := key.Unlock(oldPassphrase) unlocked, err := key.Unlock(oldPassphrase)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to unlock old key")
} }
defer unlocked.ClearPrivateParams() defer unlocked.ClearPrivateParams()
locked, err := unlocked.Lock(newPassphrase) locked, err := unlocked.Lock(newPassphrase)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to lock new key")
} }
return locked.Armor() armored, err := locked.Armor()
if err != nil {
return "", errors.Wrap(err, "gopenpgp: unable to armor new key")
}
return armored, nil
} }
// GenerateKey generates a key of the given keyType ("rsa" or "x25519"), encrypts it, and returns an armored string. // GenerateKey generates a key of the given keyType ("rsa" or "x25519"), encrypts it, and returns an armored string.
@ -35,13 +41,13 @@ func UpdatePrivateKeyPassphrase(
func GenerateKey(name, email string, passphrase []byte, keyType string, bits int) (string, error) { func GenerateKey(name, email string, passphrase []byte, keyType string, bits int) (string, error) {
key, err := crypto.GenerateKey(name, email, keyType, bits) key, err := crypto.GenerateKey(name, email, keyType, bits)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to generate new key")
} }
defer key.ClearPrivateParams() defer key.ClearPrivateParams()
locked, err := key.Lock(passphrase) locked, err := key.Lock(passphrase)
if err != nil { if err != nil {
return "", err return "", errors.Wrap(err, "gopenpgp: unable to lock new key")
} }
return locked.Armor() return locked.Armor()
@ -50,7 +56,7 @@ func GenerateKey(name, email string, passphrase []byte, keyType string, bits int
func GetSHA256Fingerprints(publicKey string) ([]string, error) { func GetSHA256Fingerprints(publicKey string) ([]string, error) {
key, err := crypto.NewKeyFromArmored(publicKey) key, err := crypto.NewKeyFromArmored(publicKey)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to parse key")
} }
return key.GetSHA256Fingerprints(), nil return key.GetSHA256Fingerprints(), nil

View file

@ -2,8 +2,10 @@ package helper
import ( import (
"encoding/json" "encoding/json"
goerrors "errors"
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/pkg/errors"
) )
type ExplicitVerifyMessage struct { type ExplicitVerifyMessage struct {
@ -24,14 +26,15 @@ func DecryptExplicitVerify(
message, err := privateKeyRing.Decrypt(pgpMessage, publicKeyRing, verifyTime) message, err := privateKeyRing.Decrypt(pgpMessage, publicKeyRing, verifyTime)
if err != nil { if err != nil {
castedErr, isType := err.(crypto.SignatureVerificationError) castedErr := &crypto.SignatureVerificationError{}
isType := goerrors.As(err, castedErr)
if !isType { if !isType {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to decrypt message")
} }
explicitVerify = &ExplicitVerifyMessage{ explicitVerify = &ExplicitVerifyMessage{
Message: message, Message: message,
SignatureVerificationError: &castedErr, SignatureVerificationError: castedErr,
} }
} else { } else {
explicitVerify = &ExplicitVerifyMessage{ explicitVerify = &ExplicitVerifyMessage{
@ -51,7 +54,7 @@ func DecryptAttachment(keyPacket []byte, dataPacket []byte, keyRing *crypto.KeyR
decrypted, err := keyRing.DecryptAttachment(splitMessage) decrypted, err := keyRing.DecryptAttachment(splitMessage)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to decrypt attachment")
} }
return decrypted, nil return decrypted, nil
} }
@ -64,7 +67,7 @@ func EncryptAttachment(plainData []byte, filename string, keyRing *crypto.KeyRin
plainMessage := crypto.NewPlainMessageFromFile(plainData, filename, uint32(crypto.GetUnixTime())) plainMessage := crypto.NewPlainMessageFromFile(plainData, filename, uint32(crypto.GetUnixTime()))
decrypted, err := keyRing.EncryptAttachment(plainMessage, "") decrypted, err := keyRing.EncryptAttachment(plainMessage, "")
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to encrypt attachment")
} }
return decrypted, nil return decrypted, nil
} }
@ -74,7 +77,7 @@ func EncryptAttachment(plainData []byte, filename string, keyRing *crypto.KeyRin
func GetJsonSHA256Fingerprints(publicKey string) ([]byte, error) { func GetJsonSHA256Fingerprints(publicKey string) ([]byte, error) {
key, err := crypto.NewKeyFromArmored(publicKey) key, err := crypto.NewKeyFromArmored(publicKey)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to parse key")
} }
return json.Marshal(key.GetSHA256Fingerprints()) return json.Marshal(key.GetSHA256Fingerprints())
@ -94,5 +97,9 @@ func EncryptSignArmoredDetachedMobile(
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &EncryptSignArmoredDetachedMobileResult{ciphertext, encryptedSignature}, nil
return &EncryptSignArmoredDetachedMobileResult{
Ciphertext: ciphertext,
EncryptedSignature: encryptedSignature,
}, nil
} }

View file

@ -5,6 +5,7 @@ package helper
import ( import (
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/pkg/errors"
) )
// EncryptSignAttachment encrypts an attachment using a detached signature, given a publicKey, a privateKey // EncryptSignAttachment encrypts an attachment using a detached signature, given a publicKey, a privateKey
@ -13,46 +14,36 @@ import (
func EncryptSignAttachment( func EncryptSignAttachment(
publicKey, privateKey string, passphrase []byte, filename string, plainData []byte, publicKey, privateKey string, passphrase []byte, filename string, plainData []byte,
) (keyPacket, dataPacket, signature []byte, err error) { ) (keyPacket, dataPacket, signature []byte, err error) {
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key var privateKeyObj, unlockedKeyObj *crypto.Key
var publicKeyRing, privateKeyRing *crypto.KeyRing var publicKeyRing, privateKeyRing *crypto.KeyRing
var packets *crypto.PGPSplitMessage var packets *crypto.PGPSplitMessage
var signatureObj *crypto.PGPSignature var signatureObj *crypto.PGPSignature
var binMessage = crypto.NewPlainMessageFromFile(plainData, filename, uint32(crypto.GetUnixTime())) var binMessage = crypto.NewPlainMessageFromFile(plainData, filename, uint32(crypto.GetUnixTime()))
if publicKeyObj, err = crypto.NewKeyFromArmored(publicKey); err != nil { if publicKeyRing, err = createPublicKeyRing(publicKey); err != nil {
return nil, nil, nil, err
}
if publicKeyObj.IsPrivate() {
publicKeyObj, err = publicKeyObj.ToPublic()
if err != nil {
return nil, nil, nil, err
}
}
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil { if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
return nil, nil, nil, err return nil, nil, nil, errors.Wrap(err, "gopenpgp: unable to parse private key")
} }
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil { if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
return nil, nil, nil, err return nil, nil, nil, errors.Wrap(err, "gopenpgp: unable to unlock key")
} }
defer unlockedKeyObj.ClearPrivateParams() defer unlockedKeyObj.ClearPrivateParams()
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil { if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
return nil, nil, nil, err return nil, nil, nil, errors.Wrap(err, "gopenpgp: unable to create private keyring")
} }
if packets, err = publicKeyRing.EncryptAttachment(binMessage, ""); err != nil { if packets, err = publicKeyRing.EncryptAttachment(binMessage, ""); err != nil {
return nil, nil, nil, err return nil, nil, nil, errors.Wrap(err, "gopenpgp: unable to encrypt attachment")
} }
if signatureObj, err = privateKeyRing.SignDetached(binMessage); err != nil { if signatureObj, err = privateKeyRing.SignDetached(binMessage); err != nil {
return nil, nil, nil, err return nil, nil, nil, errors.Wrap(err, "gopenpgp: unable to sign attachment")
} }
return packets.GetBinaryKeyPacket(), packets.GetBinaryDataPacket(), signatureObj.GetBinary(), nil return packets.GetBinaryKeyPacket(), packets.GetBinaryDataPacket(), signatureObj.GetBinary(), nil

View file

@ -3,6 +3,7 @@ package internal
import ( import (
"strings" "strings"
"github.com/pkg/errors"
"golang.org/x/crypto/openpgp/armor" "golang.org/x/crypto/openpgp/armor"
) )
@ -11,7 +12,7 @@ func Unarmor(input string) (*armor.Block, error) {
io := strings.NewReader(input) io := strings.NewReader(input)
b, err := armor.Decode(io) b, err := armor.Decode(io)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "gopenpgp: unable to armor")
} }
return b, nil return b, nil
} }