Optimize encrypt attachment

This commit is contained in:
Kay Lukas 2018-10-26 15:08:49 +02:00
parent 0456595f68
commit 9dfb46fe45
24 changed files with 726 additions and 94 deletions

View file

@ -0,0 +1,105 @@
package internal
import (
"bytes"
"golang.org/x/crypto/openpgp/packet"
"gitlab.com/ProtonMail/go-pm-crypto/models"
"io"
)
func SplitPackets(encryptedReader io.Reader, estimatedLength int) (*models.EncryptedSplit, error){
var err error
//kr *KeyRing, r io.Reader) (key *SymmetricKey, symEncryptedData []byte,
packets := packet.NewReader(encryptedReader)
outSplit := &models.EncryptedSplit{}
// Save encrypted key and signature apart
var ek *packet.EncryptedKey
// var decryptErr error
for {
var p packet.Packet
if p, err = packets.Next(); err == io.EOF {
err = nil
break
}
switch p := p.(type) {
case *packet.EncryptedKey:
// We got an encrypted key. Try to decrypt it with each available key
if ek != nil && ek.Key != nil {
break
}
ek = p
break
case *packet.SymmetricallyEncrypted:
// The code below is optimized to not
var b bytes.Buffer
// 128 is an estimation of the size difference between input and output, the size difference is most probably
// 16 bytes at a maximum though.
b.Grow(128 + estimatedLength)
// empty encoded length + start byte
b.Write(make([]byte, 6))
b.WriteByte(byte(1))
actualLength := 1
block := make([]byte, 128)
for {
n, err := p.Contents.Read(block)
if err == io.EOF {
break
}
b.Write(block[:n])
actualLength += n
}
// quick encoding
symEncryptedData := b.Bytes()
if actualLength < 192 {
symEncryptedData[4] = byte(210)
symEncryptedData[5] = byte(actualLength)
symEncryptedData = symEncryptedData[4:]
} else if actualLength < 8384 {
actualLength = actualLength - 192
symEncryptedData[3] = byte(210)
symEncryptedData[4] = 192+byte(actualLength>>8)
symEncryptedData[5] = byte(actualLength)
symEncryptedData = symEncryptedData[3:]
} else {
symEncryptedData[0] = byte(210)
symEncryptedData[1] = byte(255)
symEncryptedData[2] = byte(actualLength>>24)
symEncryptedData[3] = byte(actualLength>>16)
symEncryptedData[4] = byte(actualLength>>8)
symEncryptedData[5] = byte(actualLength)
}
outSplit.DataPacket = symEncryptedData
break
}
}
var buf bytes.Buffer
ek.Serialize(&buf)
outSplit.KeyPacket = buf.Bytes()
return outSplit, err
}
//encode length based on 4.2.2. in the RFC
func encodedLength(length int) (b []byte) {
if length < 192 {
b = append(b, byte(length))
} else if length < 8384 {
length = length - 192
b = append(b, 192+byte(length>>8))
b = append(b, byte(length))
} else {
b = append(b, byte(255))
b = append(b, byte(length>>24))
b = append(b, byte(length>>16))
b = append(b, byte(length>>8))
b = append(b, byte(length))
}
return
}