passforios-gopenpgp/armor/armor.go

130 lines
3.1 KiB
Go
Raw Normal View History

package armor
import (
"bytes"
2018-09-19 11:52:14 +02:00
"errors"
2018-11-01 17:03:43 +01:00
"github.com/ProtonMail/go-pm-crypto/internal"
"github.com/ProtonMail/go-pm-crypto/models"
"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"
)
// 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)
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)
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
}