2018-09-11 11:09:28 +02:00
|
|
|
package armor
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
2018-09-19 11:52:14 +02:00
|
|
|
"errors"
|
2018-09-20 13:36:56 +02:00
|
|
|
"gitlab.com/ProtonMail/go-pm-crypto/internal"
|
|
|
|
|
"gitlab.com/ProtonMail/go-pm-crypto/models"
|
2018-09-11 11:09:28 +02:00
|
|
|
"golang.org/x/crypto/openpgp/armor"
|
|
|
|
|
"golang.org/x/crypto/openpgp/clearsign"
|
|
|
|
|
"golang.org/x/crypto/openpgp/packet"
|
|
|
|
|
"io"
|
2018-09-19 11:52:14 +02:00
|
|
|
"io/ioutil"
|
2018-09-11 11:09:28 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// ArmorKey make bytes input key to armor format
|
|
|
|
|
func ArmorKey(input []byte) (string, error) {
|
|
|
|
|
return ArmorWithType(input, PUBLIC_KEY_HEADER)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ArmorWithType make bytes input to armor format
|
|
|
|
|
func ArmorWithType(input []byte, armorType string) (string, error) {
|
|
|
|
|
var b bytes.Buffer
|
|
|
|
|
w, err := armor.Encode(&b, armorType, internal.ArmorHeaders)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
_, err = w.Write(input)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
w.Close()
|
|
|
|
|
return b.String(), nil
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-19 11:52:14 +02:00
|
|
|
// Unarmor an armored key to bytes key
|
|
|
|
|
func Unarmor(input string) ([]byte, error) {
|
|
|
|
|
b, err := internal.Unarmor(input)
|
2018-09-11 11:09:28 +02:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return ioutil.ReadAll(b.Body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//ReadClearSignedMessage read clear message from a clearsign package
|
|
|
|
|
func ReadClearSignedMessage(signedMessage string) (string, error) {
|
|
|
|
|
modulusBlock, rest := clearsign.Decode([]byte(signedMessage))
|
|
|
|
|
if len(rest) != 0 {
|
|
|
|
|
return "", errors.New("pmapi: extra data after modulus")
|
|
|
|
|
}
|
|
|
|
|
return string(modulusBlock.Bytes), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//SeparateKeyAndData ...
|
|
|
|
|
func SplitArmor(encrypted string) (*models.EncryptedSplit, error) {
|
|
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
|
2018-09-19 11:52:14 +02:00
|
|
|
encryptedRaw, err := Unarmor(encrypted)
|
2018-09-11 11:09:28 +02:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
encryptedReader := bytes.NewReader(encryptedRaw)
|
|
|
|
|
|
|
|
|
|
//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:
|
|
|
|
|
var packetContents []byte
|
|
|
|
|
if packetContents, err = ioutil.ReadAll(p.Contents); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
encodedLength := encodedLength(len(packetContents) + 1)
|
|
|
|
|
var symEncryptedData []byte
|
|
|
|
|
symEncryptedData = append(symEncryptedData, byte(210))
|
|
|
|
|
symEncryptedData = append(symEncryptedData, encodedLength...)
|
|
|
|
|
symEncryptedData = append(symEncryptedData, byte(1))
|
|
|
|
|
symEncryptedData = append(symEncryptedData, packetContents...)
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|