Refactor api (#6)
* Refactor library, remove duplicates * Rebuild structure to use Messages and Signature models * Use PGPSplitMessage * Remove signature model * Various fixes * Add helpers with tests * Fixes, add some docs, add tests * Add attachment helpers * Add helpers Symmetric encryption * Edit docs + examples * Rename kr to keyRing * Various fixes for documentation * Edit JSON handling functions, add decrypt keyring via token * Add proposal changes doc * Fix CI * Drop *Message functions, join CleartextMessage and BinaryMessage * Change canonicalization and trimming only to text signatures * Add cleartextsignature, detach signature from message model, move helpers * Documentation, remove optional parameters * Move verification to separate model * Don't return message in VerifyDetached * Update table of contents in readme * Appease golint * Run go fmt * Rename Encrypt/DecryptMessageWithPassword to ..WithToken These functions shouldn't be used with user-provided passwords, as they don't do any key-stretching. * Change key generation usernames
This commit is contained in:
parent
82d49bf235
commit
e65ed17b41
34 changed files with 2573 additions and 1478 deletions
|
|
@ -2,15 +2,11 @@ package crypto
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
armorUtils "github.com/ProtonMail/gopenpgp/armor"
|
||||
"github.com/ProtonMail/gopenpgp/constants"
|
||||
"github.com/ProtonMail/gopenpgp/models"
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"golang.org/x/crypto/openpgp/packet"
|
||||
)
|
||||
|
|
@ -21,7 +17,7 @@ type AttachmentProcessor struct {
|
|||
w *io.WriteCloser
|
||||
pipe *io.PipeWriter
|
||||
done sync.WaitGroup
|
||||
split *models.EncryptedSplit
|
||||
split *PGPSplitMessage
|
||||
garbageCollector int
|
||||
err error
|
||||
}
|
||||
|
|
@ -34,7 +30,7 @@ func (ap *AttachmentProcessor) Process(plainData []byte) {
|
|||
}
|
||||
|
||||
// Finish closes the attachment and returns the encrypted data
|
||||
func (ap *AttachmentProcessor) Finish() (*models.EncryptedSplit, error) {
|
||||
func (ap *AttachmentProcessor) Finish() (*PGPSplitMessage, error) {
|
||||
if ap.err != nil {
|
||||
return nil, ap.err
|
||||
}
|
||||
|
|
@ -47,10 +43,10 @@ func (ap *AttachmentProcessor) Finish() (*models.EncryptedSplit, error) {
|
|||
return ap.split, nil
|
||||
}
|
||||
|
||||
// encryptAttachment creates an AttachmentProcessor which can be used to encrypt
|
||||
// newAttachmentProcessor creates an AttachmentProcessor which can be used to encrypt
|
||||
// a file. It takes an estimatedSize and fileName as hints about the file.
|
||||
func (pgp *GopenPGP) encryptAttachment(
|
||||
estimatedSize int, fileName string, publicKey *KeyRing, garbageCollector int,
|
||||
func (keyRing *KeyRing) newAttachmentProcessor(
|
||||
estimatedSize int, fileName string, garbageCollector int,
|
||||
) (*AttachmentProcessor, error) {
|
||||
attachmentProc := &AttachmentProcessor{}
|
||||
// You could also add these one at a time if needed.
|
||||
|
|
@ -70,17 +66,18 @@ func (pgp *GopenPGP) encryptAttachment(
|
|||
|
||||
go func() {
|
||||
defer attachmentProc.done.Done()
|
||||
split, splitError := SeparateKeyAndData(nil, reader, estimatedSize, garbageCollector)
|
||||
ciphertext, _ := ioutil.ReadAll(reader)
|
||||
message := NewPGPMessage(ciphertext)
|
||||
split, splitError := message.SeparateKeyAndData(estimatedSize, garbageCollector)
|
||||
if attachmentProc.err != nil {
|
||||
attachmentProc.err = splitError
|
||||
}
|
||||
split.Algo = constants.AES256
|
||||
attachmentProc.split = split
|
||||
}()
|
||||
|
||||
var ew io.WriteCloser
|
||||
var encryptErr error
|
||||
ew, encryptErr = openpgp.Encrypt(writer, publicKey.entities, nil, hints, config)
|
||||
ew, encryptErr = openpgp.Encrypt(writer, keyRing.entities, nil, hints, config)
|
||||
if encryptErr != nil {
|
||||
return nil, encryptErr
|
||||
}
|
||||
|
|
@ -90,15 +87,14 @@ func (pgp *GopenPGP) encryptAttachment(
|
|||
return attachmentProc, nil
|
||||
}
|
||||
|
||||
// EncryptAttachment encrypts a file. fileName
|
||||
func (pgp *GopenPGP) EncryptAttachment(
|
||||
plainData []byte, fileName string, publicKey *KeyRing,
|
||||
) (*models.EncryptedSplit, error) {
|
||||
ap, err := pgp.encryptAttachment(len(plainData), fileName, publicKey, -1)
|
||||
// EncryptAttachment encrypts a file given a PlainMessage and a fileName.
|
||||
// Returns a PGPSplitMessage containing a session key packet and symmetrically encrypted data
|
||||
func (keyRing *KeyRing) EncryptAttachment(message *PlainMessage, fileName string) (*PGPSplitMessage, error) {
|
||||
ap, err := keyRing.newAttachmentProcessor(len(message.GetBinary()), fileName, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ap.Process(plainData)
|
||||
ap.Process(message.GetBinary())
|
||||
split, err := ap.Finish()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -106,47 +102,23 @@ func (pgp *GopenPGP) EncryptAttachment(
|
|||
return split, nil
|
||||
}
|
||||
|
||||
// EncryptAttachmentLowMemory creates an AttachmentProcessor which can be used
|
||||
// NewLowMemoryAttachmentProcessor creates an AttachmentProcessor which can be used
|
||||
// to encrypt a file. It takes an estimatedSize and fileName as hints about the
|
||||
// file. It is optimized for low-memory environments and collects garbage every
|
||||
// megabyte.
|
||||
func (pgp *GopenPGP) EncryptAttachmentLowMemory(
|
||||
estimatedSize int, fileName string, publicKey *KeyRing,
|
||||
func (keyRing *KeyRing) NewLowMemoryAttachmentProcessor(
|
||||
estimatedSize int, fileName string,
|
||||
) (*AttachmentProcessor, error) {
|
||||
return pgp.encryptAttachment(estimatedSize, fileName, publicKey, 1<<20)
|
||||
return keyRing.newAttachmentProcessor(estimatedSize, fileName, 1<<20)
|
||||
}
|
||||
|
||||
// SplitArmor is a helper method which splits an armored message into its
|
||||
// session key packet and symmetrically encrypted data packet.
|
||||
func SplitArmor(encrypted string) (*models.EncryptedSplit, error) {
|
||||
var err error
|
||||
// DecryptAttachment takes a PGPSplitMessage, containing a session key packet and symmetrically encrypted data
|
||||
// and returns a decrypted PlainMessage
|
||||
func (keyRing *KeyRing) DecryptAttachment(message *PGPSplitMessage) (*PlainMessage, error) {
|
||||
privKeyEntries := keyRing.entities
|
||||
|
||||
encryptedRaw, err := armorUtils.Unarmor(encrypted)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encryptedReader := bytes.NewReader(encryptedRaw)
|
||||
|
||||
return SeparateKeyAndData(nil, encryptedReader, len(encrypted), -1)
|
||||
}
|
||||
|
||||
// DecryptAttachment takes a session key packet and symmetrically encrypted data
|
||||
// packet. privateKeys is a KeyRing that can contain multiple keys. The
|
||||
// passphrase is used to unlock keys in privateKeys.
|
||||
func (pgp *GopenPGP) DecryptAttachment(
|
||||
keyPacket, dataPacket []byte,
|
||||
kr *KeyRing, passphrase string,
|
||||
) ([]byte, error) {
|
||||
privKeyEntries := kr.entities
|
||||
|
||||
if err := kr.Unlock([]byte(passphrase)); err != nil {
|
||||
err = fmt.Errorf("gopenpgp: cannot decrypt attachment: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyReader := bytes.NewReader(keyPacket)
|
||||
dataReader := bytes.NewReader(dataPacket)
|
||||
keyReader := bytes.NewReader(message.GetKeyPacket())
|
||||
dataReader := bytes.NewReader(message.GetDataPacket())
|
||||
|
||||
encryptedReader := io.MultiReader(keyReader, dataReader)
|
||||
|
||||
|
|
@ -163,5 +135,5 @@ func (pgp *GopenPGP) DecryptAttachment(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
return NewPlainMessage(b), nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue