diff --git a/CHANGELOG.md b/CHANGELOG.md index 002b91d5..0c58bb6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Added +- Methods for generating an verifying encrypted detached signatures +```go +(signingKeyRing *KeyRing) SignDetachedEncrypted(message *PlainMessage, encryptionKeyRing *KeyRing) (encryptedSignature *PGPMessage, err error) +(verifyingKeyRing *KeyRing) VerifyDetachedEncrypted(message *PlainMessage, encryptedSignature *PGPMessage, decryptionKeyRing *KeyRing, verifyTime int64) error +``` + ## [2.1.3] 2020-12-09 ### Added - `helper.FreeOSMemory()` to explicitly call the GC and release the memory to the OS diff --git a/crypto/keyring_message.go b/crypto/keyring_message.go index 44bdf02c..eb6ef07b 100644 --- a/crypto/keyring_message.go +++ b/crypto/keyring_message.go @@ -76,7 +76,7 @@ func (keyRing *KeyRing) SignDetached(message *PlainMessage) (*PGPSignature, erro return NewPGPSignature(outBuf.Bytes()), nil } -// VerifyDetached verifies a PlainMessage with embedded a PGPSignature +// VerifyDetached verifies a PlainMessage with a detached PGPSignature // and returns a SignatureVerificationError if fails. func (keyRing *KeyRing) VerifyDetached(message *PlainMessage, signature *PGPSignature, verifyTime int64) error { return verifySignature( @@ -87,6 +87,36 @@ func (keyRing *KeyRing) VerifyDetached(message *PlainMessage, signature *PGPSign ) } +// SignDetachedEncrypted generates and returns a PGPMessage +// containing an encrypted detached signature for a given PlainMessage. +func (keyRing *KeyRing) SignDetachedEncrypted(message *PlainMessage, encryptionKeyRing *KeyRing) (encryptedSignature *PGPMessage, err error) { + if encryptionKeyRing == nil { + return nil, errors.New("gopenpgp: no encryption key ring provided") + } + signature, err := keyRing.SignDetached(message) + if err != nil { + return nil, err + } + plainMessage := NewPlainMessage(signature.GetBinary()) + encryptedSignature, err = encryptionKeyRing.Encrypt(plainMessage, nil) + return +} + +// VerifyDetachedEncrypted verifies a PlainMessage +// with a PGPMessage containing an encrypted detached signature +// and returns a SignatureVerificationError if fails. +func (keyRing *KeyRing) VerifyDetachedEncrypted(message *PlainMessage, encryptedSignature *PGPMessage, decryptionKeyRing *KeyRing, verifyTime int64) error { + if decryptionKeyRing == nil { + return errors.New("gopenpgp: no decryption key ring provided") + } + plainMessage, err := decryptionKeyRing.Decrypt(encryptedSignature, nil, 0) + if err != nil { + return err + } + signature := NewPGPSignature(plainMessage.GetBinary()) + return keyRing.VerifyDetached(message, signature, verifyTime) +} + // ------ INTERNAL FUNCTIONS ------- // Core for encryption+signature functions. diff --git a/crypto/keyring_test.go b/crypto/keyring_test.go index 2fd1535c..e64d8800 100644 --- a/crypto/keyring_test.go +++ b/crypto/keyring_test.go @@ -197,3 +197,28 @@ func TestClearPrivateParams(t *testing.T) { assert.False(t, key.ClearPrivateParams()) } } + +func TestEncryptedDetachedSignature(t *testing.T) { + keyRingPrivate, err := keyRingTestPrivate.Copy() + if err != nil { + t.Fatal("Expected no error while copying keyring, got:", err) + } + keyRingPublic, err := keyRingTestPublic.Copy() + if err != nil { + t.Fatal("Expected no error while copying keyring, got:", err) + } + message := NewPlainMessageFromString("Hello World!") + encSign, err := keyRingPrivate.SignDetachedEncrypted(message, keyRingPublic) + if err != nil { + t.Fatal("Expected no error while encryptedSigning, got:", err) + } + err = keyRingPublic.VerifyDetachedEncrypted(message, encSign, keyRingPrivate, 0) + if err != nil { + t.Fatal("Expected no error while verifying encSignature, got:", err) + } + message2 := NewPlainMessageFromString("Bye!") + err = keyRingPublic.VerifyDetachedEncrypted(message2, encSign, keyRingPrivate, 0) + if err == nil { + t.Fatal("Expected an error while verifying bad encSignature, got nil") + } +}