Fix compilation for gomobile iOS (#17)
* Move signature verification to errors * Move cleartext messages to ClearTextMessage struct * Fix documentation
This commit is contained in:
parent
552ce9554f
commit
9195b9ae92
16 changed files with 311 additions and 296 deletions
|
|
@ -3,18 +3,11 @@ package crypto
|
|||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/openpgp"
|
||||
pgpErrors "golang.org/x/crypto/openpgp/errors"
|
||||
"golang.org/x/crypto/openpgp/packet"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/constants"
|
||||
"github.com/ProtonMail/gopenpgp/internal"
|
||||
)
|
||||
|
||||
// Encrypt encrypts a PlainMessage, outputs a PGPMessage.
|
||||
|
|
@ -36,13 +29,10 @@ func (keyRing *KeyRing) Encrypt(message *PlainMessage, privateKey *KeyRing) (*PG
|
|||
// verifyTime : Time at verification (necessary only if verifyKey is not nil)
|
||||
func (keyRing *KeyRing) Decrypt(
|
||||
message *PGPMessage, verifyKey *KeyRing, verifyTime int64,
|
||||
) (*PlainMessage, *Verification, error) {
|
||||
decrypted, verifyStatus, err := asymmetricDecrypt(message.NewReader(), keyRing, verifyKey, verifyTime)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
) (*PlainMessage, error) {
|
||||
decrypted, err := asymmetricDecrypt(message.NewReader(), keyRing, verifyKey, verifyTime)
|
||||
|
||||
return NewPlainMessage(decrypted), newVerification(verifyStatus), nil
|
||||
return NewPlainMessage(decrypted), err
|
||||
}
|
||||
|
||||
// SignDetached generates and returns a PGPSignature for a given PlainMessage
|
||||
|
|
@ -63,18 +53,16 @@ func (keyRing *KeyRing) SignDetached(message *PlainMessage) (*PGPSignature, erro
|
|||
}
|
||||
|
||||
// VerifyDetached verifies a PlainMessage with embedded a PGPSignature
|
||||
// and returns a Verification with the filled Verified field.
|
||||
// and returns a SignatureVerificationError if fails
|
||||
func (keyRing *KeyRing) VerifyDetached(
|
||||
message *PlainMessage, signature *PGPSignature, verifyTime int64,
|
||||
) (*Verification, error) {
|
||||
var err error
|
||||
verifyVal, err := verifySignature(
|
||||
) (error) {
|
||||
return verifySignature(
|
||||
keyRing.GetEntities(),
|
||||
message.NewReader(),
|
||||
signature.GetBinary(),
|
||||
verifyTime,
|
||||
)
|
||||
return newVerification(verifyVal), err
|
||||
}
|
||||
|
||||
// ------ INTERNAL FUNCTIONS -------
|
||||
|
|
@ -123,7 +111,7 @@ func asymmetricEncrypt(data []byte, publicKey *KeyRing, privateKey *KeyRing, isB
|
|||
// Core for decryption+verification functions
|
||||
func asymmetricDecrypt(
|
||||
encryptedIO io.Reader, privateKey *KeyRing, verifyKey *KeyRing, verifyTime int64,
|
||||
) (plaintext []byte, verified int, err error) {
|
||||
) (plaintext []byte, err error) {
|
||||
privKeyEntries := privateKey.GetEntities()
|
||||
var additionalEntries openpgp.EntityList
|
||||
|
||||
|
|
@ -139,12 +127,12 @@ func asymmetricDecrypt(
|
|||
|
||||
messageDetails, err := openpgp.ReadMessage(encryptedIO, privKeyEntries, nil, config)
|
||||
if err != nil {
|
||||
return nil, constants.SIGNATURE_NOT_SIGNED, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(messageDetails.UnverifiedBody)
|
||||
if err != nil {
|
||||
return nil, constants.SIGNATURE_NOT_SIGNED, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if verifyKey != nil {
|
||||
|
|
@ -152,104 +140,8 @@ func asymmetricDecrypt(
|
|||
}
|
||||
|
||||
if verifyKey != nil {
|
||||
verifyStatus, verifyError := verifyDetailsSignature(messageDetails, verifyKey)
|
||||
|
||||
if verifyStatus == constants.SIGNATURE_FAILED {
|
||||
return nil, verifyStatus, errors.New(verifyError)
|
||||
}
|
||||
|
||||
return body, verifyStatus, nil
|
||||
return body, verifyDetailsSignature(messageDetails, verifyKey)
|
||||
}
|
||||
|
||||
return body, constants.SIGNATURE_NOT_SIGNED, nil
|
||||
}
|
||||
|
||||
// processSignatureExpiration handles signature time verification manually, so we can add a margin to the
|
||||
// creationTime check.
|
||||
func processSignatureExpiration(md *openpgp.MessageDetails, verifyTime int64) {
|
||||
if md.SignatureError == pgpErrors.ErrSignatureExpired {
|
||||
if verifyTime > 0 {
|
||||
created := md.Signature.CreationTime.Unix()
|
||||
expires := int64(math.MaxInt64)
|
||||
if md.Signature.SigLifetimeSecs != nil {
|
||||
expires = int64(*md.Signature.SigLifetimeSecs) + created
|
||||
}
|
||||
if created-internal.CreationTimeOffset <= verifyTime && verifyTime <= expires {
|
||||
md.SignatureError = nil
|
||||
}
|
||||
} else {
|
||||
// verifyTime = 0: time check disabled, everything is okay
|
||||
md.SignatureError = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify signature from message details
|
||||
func verifyDetailsSignature(md *openpgp.MessageDetails, verifierKey *KeyRing) (int, string) {
|
||||
if md.IsSigned {
|
||||
if md.SignedBy != nil {
|
||||
if len(verifierKey.entities) > 0 {
|
||||
matches := verifierKey.entities.KeysById(md.SignedByKeyId)
|
||||
if len(matches) > 0 {
|
||||
if md.SignatureError == nil {
|
||||
return constants.SIGNATURE_OK, ""
|
||||
}
|
||||
return constants.SIGNATURE_FAILED, md.SignatureError.Error()
|
||||
}
|
||||
} else {
|
||||
return constants.SIGNATURE_NO_VERIFIER, ""
|
||||
}
|
||||
} else {
|
||||
return constants.SIGNATURE_NO_VERIFIER, ""
|
||||
}
|
||||
}
|
||||
|
||||
return constants.SIGNATURE_NOT_SIGNED, ""
|
||||
}
|
||||
|
||||
// verifySignature verifies if a signature is valid with the entity list
|
||||
func verifySignature(
|
||||
pubKeyEntries openpgp.EntityList, origText io.Reader, signature []byte, verifyTime int64) (int, error) {
|
||||
config := &packet.Config{}
|
||||
if verifyTime == 0 {
|
||||
config.Time = func() time.Time {
|
||||
return time.Unix(0, 0)
|
||||
}
|
||||
} else {
|
||||
config.Time = func() time.Time {
|
||||
return time.Unix(verifyTime+internal.CreationTimeOffset, 0)
|
||||
}
|
||||
}
|
||||
signatureReader := bytes.NewReader(signature)
|
||||
|
||||
signer, err := openpgp.CheckDetachedSignature(pubKeyEntries, origText, signatureReader, config)
|
||||
|
||||
if err == pgpErrors.ErrSignatureExpired && signer != nil {
|
||||
if verifyTime > 0 { // if verifyTime = 0: time check disabled, everything is okay
|
||||
// Maybe the creation time offset pushed it over the edge
|
||||
// Retry with the actual verification time
|
||||
config.Time = func() time.Time {
|
||||
return time.Unix(verifyTime, 0)
|
||||
}
|
||||
|
||||
_, err = signatureReader.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return constants.SIGNATURE_FAILED, err
|
||||
}
|
||||
|
||||
signer, err = openpgp.CheckDetachedSignature(pubKeyEntries, origText, signatureReader, config)
|
||||
if err != nil {
|
||||
return constants.SIGNATURE_FAILED, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if signer == nil {
|
||||
return constants.SIGNATURE_FAILED, errors.New("gopenpgp: signer is empty")
|
||||
}
|
||||
// if signer.PrimaryKey.KeyId != signed.PrimaryKey.KeyId {
|
||||
// // t.Errorf("wrong signer got:%x want:%x", signer.PrimaryKey.KeyId, 0)
|
||||
// return false, errors.New("signer is nil")
|
||||
// }
|
||||
return constants.SIGNATURE_OK, nil
|
||||
return body, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue