Skip to content

Commit

Permalink
feat(crypto): Add option to decrypt with signature keys
Browse files Browse the repository at this point in the history
- Refactors config handling in decryption
- Adds option in decryption to allow to decrypt with signature keys
  • Loading branch information
lubux committed Nov 25, 2024
1 parent 0f3b745 commit 1db926f
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 32 deletions.
60 changes: 35 additions & 25 deletions crypto/decryption_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,16 @@ func NewPGPSplitReader(pgpMessage Reader, pgpEncryptedSignature Reader) *pgpSpli
// decryptStream decrypts the stream either with the secret keys or a password.
func (dh *decryptionHandle) decryptStream(encryptedMessage Reader) (plainMessage *VerifyDataReader, err error) {
var entries openpgp.EntityList
checkPacketSequence := !dh.DisableStrictMessageParsing
config := dh.profile.EncryptionConfig()
config.CacheSessionKey = dh.RetrieveSessionKey
config.CheckPacketSequence = &checkPacketSequence

config := dh.decryptionConfig(dh.clock().Unix())
if dh.DecryptionKeyRing != nil {
entries = dh.DecryptionKeyRing.entities
checkIntendedRecipients := !dh.DisableIntendedRecipients
config.CheckIntendedRecipients = &checkIntendedRecipients
}
config.InsecureAllowUnauthenticatedMessages = dh.DisableUnauthenticatedMessagesCheck

if dh.VerifyKeyRing != nil {
entries = append(entries, dh.VerifyKeyRing.entities...)
}
verifyTime := dh.clock().Unix()

config.Time = NewConstantClock(verifyTime)
if dh.VerificationContext != nil {
config.KnownNotations = map[string]bool{constants.SignatureContextName: true}
}
Expand Down Expand Up @@ -150,8 +144,9 @@ func (dh *decryptionHandle) decryptStreamWithSessionAndParse(messageReader io.Re
return nil, 0, errors.Wrap(err, "gopenpgp: unable to decrypt message with session key")
}

config := dh.profile.EncryptionConfig()
config.Time = NewConstantClock(dh.clock().Unix())
config := dh.decryptionConfig(dh.clock().Unix())
checkPacketSequence := false
config.CheckPacketSequence = &checkPacketSequence

if dh.VerificationContext != nil {
config.KnownNotations = map[string]bool{constants.SignatureContextName: true}
Expand All @@ -164,11 +159,6 @@ func (dh *decryptionHandle) decryptStreamWithSessionAndParse(messageReader io.Re
if dh.DecryptionKeyRing != nil {
keyring = append(keyring, dh.DecryptionKeyRing.entities...)
}
checkIntendedRecipients := !dh.DisableIntendedRecipients
checkPacketSequence := false
config.CheckIntendedRecipients = &checkIntendedRecipients
config.CheckPacketSequence = &checkPacketSequence
config.InsecureAllowUnauthenticatedMessages = dh.DisableUnauthenticatedMessagesCheck
md, err := openpgp.ReadMessage(decrypted, keyring, nil, config)
if err != nil {
return nil, 0, errors.Wrap(err, "gopenpgp: unable to decode symmetric packet")
Expand Down Expand Up @@ -244,11 +234,7 @@ func (dh *decryptionHandle) decryptStreamAndVerifyDetached(encryptedData, encryp
}
} else {
// Password or private keys
checkPacketSequence := !dh.DisableStrictMessageParsing
config := dh.profile.EncryptionConfig()
config.CacheSessionKey = dh.RetrieveSessionKey
config.Time = NewConstantClock(verifyTime)
config.CheckPacketSequence = &checkPacketSequence
config := dh.decryptionConfig(verifyTime)
var entries openpgp.EntityList
if dh.DecryptionKeyRing != nil {
entries = append(entries, dh.DecryptionKeyRing.entities...)
Expand Down Expand Up @@ -293,10 +279,7 @@ func (dh *decryptionHandle) decryptStreamAndVerifyDetached(encryptedData, encryp
}
}

checkIntendedRecipients := !dh.DisableIntendedRecipients
config := dh.profile.EncryptionConfig()
config.CheckIntendedRecipients = &checkIntendedRecipients
config.InsecureAllowUnauthenticatedMessages = dh.DisableUnauthenticatedMessagesCheck
config := dh.decryptionConfig(verifyTime)

// Verifying reader that wraps the decryption readers to verify the signature
sigVerifyReader, err := verifyingDetachedReader(
Expand Down Expand Up @@ -345,3 +328,30 @@ func createPasswordPrompt(password []byte) func(keys []openpgp.Key, symmetric bo
return nil, errors.New("gopenpgp: wrong password in symmetric decryption")
}
}

func (dh *decryptionHandle) decryptionConfig(configTime int64) *packet.Config {
config := dh.profile.EncryptionConfig()

// Check intended recipients in signatures.
checkIntendedRecipients := !dh.DisableIntendedRecipients
config.CheckIntendedRecipients = &checkIntendedRecipients

// Check for valid packet sequence
checkPacketSequence := !dh.DisableStrictMessageParsing
config.CheckPacketSequence = &checkPacketSequence

// Allow message decryption of PGP messages with no integrity tag.
config.InsecureAllowUnauthenticatedMessages = dh.DisableUnauthenticatedMessagesCheck

// Allow message decryption with signature keys.
if dh.DisableNoSignatureKeyForDecryption {
config.InsecureAllowDecryptionWithSigningKeys = dh.DisableNoSignatureKeyForDecryption
}

// Should the session key be returned.
config.CacheSessionKey = dh.RetrieveSessionKey

// Set time.
config.Time = NewConstantClock(configTime)
return config
}
1 change: 1 addition & 0 deletions crypto/decryption_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type decryptionHandle struct {
DisableStrictMessageParsing bool
DisableAutomaticTextSanitize bool
DisableUnauthenticatedMessagesCheck bool
DisableNoSignatureKeyForDecryption bool
RetrieveSessionKey bool
IsUTF8 bool
clock Clock
Expand Down
12 changes: 12 additions & 0 deletions crypto/decryption_handle_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,18 @@ func (dpb *DecryptionHandleBuilder) DisableUnauthenticatedMessagesCheck() *Decry
return dpb
}

// AllowSignOnlyDecryptionKeys enables decryption of messages using keys
// that are designated solely as signing keys.
// While using the same key for both encryption and signing is discouraged
// due to reduced security, this flag is useful for decrypting legacy messages.
// This is because some older libraries did not respect key flags when
// selecting a key for encryption.
// SECURITY HAZARD: Use with care.
func (dpb *DecryptionHandleBuilder) AllowSignOnlyDecryptionKeys() *DecryptionHandleBuilder {
dpb.handle.DisableNoSignatureKeyForDecryption = true
return dpb
}

// RetrieveSessionKey sets the flag to indicate if the session key used for decryption
// should be returned to the caller of the decryption function.
func (dpb *DecryptionHandleBuilder) RetrieveSessionKey() *DecryptionHandleBuilder {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/ProtonMail/gopenpgp/v3
go 1.17

require (
github.com/ProtonMail/go-crypto v1.1.2
github.com/ProtonMail/go-crypto v1.1.3
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.7.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/ProtonMail/go-crypto v1.1.2 h1:A7JbD57ThNqh7XjmHE+PXpQ3Dqt3BrSAC0AL0Go3KS0=
github.com/ProtonMail/go-crypto v1.1.2/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k=
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
Expand Down
11 changes: 7 additions & 4 deletions profile/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ type Custom struct {
DisableIntendedRecipients bool
// AllowWeakRSA is a flag to disable checks for weak rsa keys.
AllowWeakRSA bool
// AllowSingingKeyInDecryption is a flag to enable to decrypt with signing keys for compatibility reasons.
AllowSingingKeyInDecryption bool
}

// Custom implements the profile interfaces:
Expand All @@ -68,10 +70,11 @@ func (p *Custom) KeyGenerationConfig(securityLevel int8) *packet.Config {

func (p *Custom) EncryptionConfig() *packet.Config {
config := &packet.Config{
DefaultHash: p.Hash,
DefaultCipher: p.CipherEncryption,
AEADConfig: p.AeadEncryption,
S2KConfig: p.S2kEncryption,
DefaultHash: p.Hash,
DefaultCipher: p.CipherEncryption,
AEADConfig: p.AeadEncryption,
S2KConfig: p.S2kEncryption,
InsecureAllowDecryptionWithSigningKeys: p.AllowSingingKeyInDecryption,
}
if p.DisableIntendedRecipients {
intendedRecipients := false
Expand Down

0 comments on commit 1db926f

Please sign in to comment.