Add a streaming api to KeyRing and SessionKey (#131)
* barebone streaming functionality * encryption needs to return a writecloser * added eof check * workaround for reader problem with copies * separate mobile wrappers from main api * add a clone in the read result to avoid memory corruption * refactor to reuse code, and fix verification * have to give the verify key at the start of the decryption * enfore readAll before signature verification * streaming api for SessionKey * add split message stream apis * name interface params * fix streaming api so it's supported by go-mobile * hide internal writeCloser * fix nil access * added detached sigs methods * started unit testing * unit testing and fixed a bug where key and data packets where inverted * remove unecessary error wrapping * figured out closing order and error handling * add GC calls to mobile writer and reader * remove debugging values and arrays * writer with builtin sha256 * unit testing the mobile helpers * comments and linting * Typo in error Co-authored-by: wussler <aron@wussler.it> * Add GetKeyPacket doc Co-authored-by: wussler <aron@wussler.it> * Add rfc reference in comments Co-authored-by: wussler <aron@wussler.it> * small improvements * add compatibility tests with normal methods * remove unecessary copies in the tests * update go-crypto to the merged changes commit * update comments of core internal functions * remove unused nolint comment * group message metadata in a struct * fix comments * change default values for metadata * change the mobile reader wrapper to fit the behavior of java * remove gc calls in the wrappers to avoid performance penalties * bring back the former Go2MobileReader to be used for ios * Update crypto/keyring_streaming.go Co-authored-by: wussler <aron@wussler.it> * return an error when verifying an embedded sig with no keyring * Update crypto/sessionkey_streaming.go Co-authored-by: wussler <aron@wussler.it> * linter error * update changelog * update changelog Co-authored-by: wussler <aron@wussler.it>
This commit is contained in:
parent
7380f7391f
commit
c46ed8ed9e
11 changed files with 1718 additions and 97 deletions
105
crypto/sessionkey_streaming.go
Normal file
105
crypto/sessionkey_streaming.go
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type signAndEncryptWriteCloser struct {
|
||||
signWriter WriteCloser
|
||||
encryptWriter WriteCloser
|
||||
}
|
||||
|
||||
func (w *signAndEncryptWriteCloser) Write(b []byte) (int, error) {
|
||||
return w.signWriter.Write(b)
|
||||
}
|
||||
|
||||
func (w *signAndEncryptWriteCloser) Close() error {
|
||||
if err := w.signWriter.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return w.encryptWriter.Close()
|
||||
}
|
||||
|
||||
// EncryptStream 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.
|
||||
func (sk *SessionKey) EncryptStream(
|
||||
dataPacketWriter Writer,
|
||||
plainMessageMetadata *PlainMessageMetadata,
|
||||
signKeyRing *KeyRing,
|
||||
) (plainMessageWriter WriteCloser, err error) {
|
||||
dc, err := sk.GetCipherFunc()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "gopenpgp: unable to encrypt with session key")
|
||||
}
|
||||
|
||||
config := &packet.Config{
|
||||
Time: getTimeGenerator(),
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
encryptWriter, signWriter, err := encryptStreamWithSessionKey(
|
||||
plainMessageMetadata.IsBinary,
|
||||
plainMessageMetadata.Filename,
|
||||
uint32(plainMessageMetadata.ModTime),
|
||||
dataPacketWriter,
|
||||
sk,
|
||||
signEntity,
|
||||
config,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if signWriter != nil {
|
||||
plainMessageWriter = &signAndEncryptWriteCloser{signWriter, encryptWriter}
|
||||
} else {
|
||||
plainMessageWriter = encryptWriter
|
||||
}
|
||||
return plainMessageWriter, err
|
||||
}
|
||||
|
||||
// DecryptStream 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.
|
||||
func (sk *SessionKey) DecryptStream(
|
||||
dataPacketReader Reader,
|
||||
verifyKeyRing *KeyRing,
|
||||
verifyTime int64,
|
||||
) (plainMessage *PlainMessageReader, err error) {
|
||||
messageDetails, err := decryptStreamWithSessionKey(
|
||||
sk,
|
||||
dataPacketReader,
|
||||
verifyKeyRing,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "gopenpgp: error in reading message")
|
||||
}
|
||||
|
||||
return &PlainMessageReader{
|
||||
messageDetails,
|
||||
verifyKeyRing,
|
||||
verifyTime,
|
||||
false,
|
||||
}, err
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue