Add signature context for embedded signatures

This commit is contained in:
M. Thiercelin 2023-04-06 11:38:15 +02:00
parent 49211b24ff
commit 97323a4c2b
No known key found for this signature in database
GPG key ID: 29581E7E24EBEC0A
11 changed files with 931 additions and 169 deletions

View file

@ -1,9 +1,6 @@
package crypto
import (
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/ProtonMail/gopenpgp/v2/constants"
"github.com/pkg/errors"
)
@ -31,14 +28,31 @@ func (sk *SessionKey) EncryptStream(
plainMessageMetadata *PlainMessageMetadata,
signKeyRing *KeyRing,
) (plainMessageWriter WriteCloser, err error) {
config := &packet.Config{
Time: getTimeGenerator(),
}
return sk.encryptStreamWithConfig(
config,
return sk.encryptStream(
dataPacketWriter,
plainMessageMetadata,
signKeyRing,
false,
nil,
)
}
// EncryptStreamWithContext is used to encrypt data as a Writer.
// It takes a writer for the encrypted data packet and returns a writer for the plaintext data.
// If signKeyRing is not nil, it is used to do an embedded signature.
// * signingContext : (optional) the context for the signature.
func (sk *SessionKey) EncryptStreamWithContext(
dataPacketWriter Writer,
plainMessageMetadata *PlainMessageMetadata,
signKeyRing *KeyRing,
signingContext *SigningContext,
) (plainMessageWriter WriteCloser, err error) {
return sk.encryptStream(
dataPacketWriter,
plainMessageMetadata,
signKeyRing,
false,
signingContext,
)
}
@ -46,60 +60,55 @@ func (sk *SessionKey) EncryptStream(
// The plaintext data is compressed before being encrypted.
// It takes a writer for the encrypted data packet and returns a writer for the plaintext data.
// If signKeyRing is not nil, it is used to do an embedded signature.
// * signingContext : (optional) the context for the signature.
func (sk *SessionKey) EncryptStreamWithCompression(
dataPacketWriter Writer,
plainMessageMetadata *PlainMessageMetadata,
signKeyRing *KeyRing,
) (plainMessageWriter WriteCloser, err error) {
config := &packet.Config{
Time: getTimeGenerator(),
DefaultCompressionAlgo: constants.DefaultCompression,
CompressionConfig: &packet.CompressionConfig{Level: constants.DefaultCompressionLevel},
}
return sk.encryptStreamWithConfig(
config,
return sk.encryptStream(
dataPacketWriter,
plainMessageMetadata,
signKeyRing,
true,
nil,
)
}
func (sk *SessionKey) encryptStreamWithConfig(
config *packet.Config,
// EncryptStreamWithContextAndCompression is used to encrypt data as a Writer.
// The plaintext data is compressed before being encrypted.
// It takes a writer for the encrypted data packet and returns a writer for the plaintext data.
// If signKeyRing is not nil, it is used to do an embedded signature.
// * signingContext : (optional) the context for the signature.
func (sk *SessionKey) EncryptStreamWithContextAndCompression(
dataPacketWriter Writer,
plainMessageMetadata *PlainMessageMetadata,
signKeyRing *KeyRing,
signingContext *SigningContext,
) (plainMessageWriter WriteCloser, err error) {
dc, err := sk.GetCipherFunc()
if err != nil {
return nil, errors.Wrap(err, "gopenpgp: unable to encrypt with session key")
}
config.DefaultCipher = dc
var signEntity *openpgp.Entity
if signKeyRing != nil {
signEntity, err = signKeyRing.getSigningEntity()
if err != nil {
return nil, errors.Wrap(err, "gopenpgp: unable to sign")
}
}
if plainMessageMetadata == nil {
// Use sensible default metadata
plainMessageMetadata = &PlainMessageMetadata{
IsBinary: true,
Filename: "",
ModTime: GetUnixTime(),
}
}
return sk.encryptStream(
dataPacketWriter,
plainMessageMetadata,
signKeyRing,
true,
signingContext,
)
}
func (sk *SessionKey) encryptStream(
dataPacketWriter Writer,
plainMessageMetadata *PlainMessageMetadata,
signKeyRing *KeyRing,
compress bool,
signingContext *SigningContext,
) (plainMessageWriter WriteCloser, err error) {
encryptWriter, signWriter, err := encryptStreamWithSessionKey(
plainMessageMetadata.IsBinary,
plainMessageMetadata.Filename,
uint32(plainMessageMetadata.ModTime),
plainMessageMetadata,
dataPacketWriter,
sk,
signEntity,
config,
signKeyRing,
compress,
signingContext,
)
if err != nil {
@ -123,10 +132,48 @@ func (sk *SessionKey) DecryptStream(
verifyKeyRing *KeyRing,
verifyTime int64,
) (plainMessage *PlainMessageReader, err error) {
messageDetails, err := decryptStreamWithSessionKey(
return decryptStreamWithSessionKeyAndContext(
sk,
dataPacketReader,
verifyKeyRing,
verifyTime,
nil,
)
}
// DecryptStreamWithContext is used to decrypt a data packet as a Reader.
// It takes a reader for the data packet
// and returns a PlainMessageReader for the plaintext data.
// If verifyKeyRing is not nil, PlainMessageReader.VerifySignature() will
// verify the embedded signature with the given key ring and verification time.
// * verificationContext (optional): context for the signature verification.
func (sk *SessionKey) DecryptStreamWithContext(
dataPacketReader Reader,
verifyKeyRing *KeyRing,
verifyTime int64,
verificationContext *VerificationContext,
) (plainMessage *PlainMessageReader, err error) {
return decryptStreamWithSessionKeyAndContext(
sk,
dataPacketReader,
verifyKeyRing,
verifyTime,
verificationContext,
)
}
func decryptStreamWithSessionKeyAndContext(
sessionKey *SessionKey,
dataPacketReader Reader,
verifyKeyRing *KeyRing,
verifyTime int64,
verificationContext *VerificationContext,
) (plainMessage *PlainMessageReader, err error) {
messageDetails, err := decryptStreamWithSessionKey(
sessionKey,
dataPacketReader,
verifyKeyRing,
verificationContext,
)
if err != nil {
return nil, errors.Wrap(err, "gopenpgp: error in reading message")
@ -137,5 +184,6 @@ func (sk *SessionKey) DecryptStream(
verifyKeyRing,
verifyTime,
false,
verificationContext,
}, err
}