passforios-gopenpgp/session.go
2018-06-04 17:50:26 -07:00

358 lines
8 KiB
Go

package pm
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"strings"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet"
)
//RandomToken ...
func RandomToken() ([]byte, error) {
config := &packet.Config{DefaultCipher: packet.CipherAES256}
keySize := config.DefaultCipher.KeySize()
symKey := make([]byte, keySize)
if _, err := io.ReadFull(config.Random(), symKey); err != nil {
return nil, err
}
return symKey, nil
}
// RandomTokenWith ...
func RandomTokenWith(size int) ([]byte, error) {
config := &packet.Config{DefaultCipher: packet.CipherAES256}
symKey := make([]byte, size)
if _, err := io.ReadFull(config.Random(), symKey); err != nil {
return nil, err
}
return symKey, nil
}
//GetSessionFromKeyPacketBinkeys get session key no encoding in and out
func GetSessionFromKeyPacketBinkeys(keyPackage []byte, privateKey []byte, passphrase string) (*SessionSplit, error) {
keyReader := bytes.NewReader(keyPackage)
packets := packet.NewReader(keyReader)
var p packet.Packet
var err error
if p, err = packets.Next(); err != nil {
return nil, err
}
ek := p.(*packet.EncryptedKey)
privKey := bytes.NewReader(privateKey)
privKeyEntries, err := openpgp.ReadKeyRing(privKey)
if err != nil {
return nil, err
}
rawPwd := []byte(passphrase)
var decryptErr error
for _, key := range privKeyEntries.DecryptionKeys() {
priv := key.PrivateKey
if priv.Encrypted {
if err := priv.Decrypt(rawPwd); err != nil {
continue
}
}
if decryptErr = ek.Decrypt(priv, nil); decryptErr == nil {
break
}
}
if decryptErr != nil {
return nil, err
}
return getSessionSplit(ek)
}
//GetSessionFromKeyPacket get session key no encoding in and out
func GetSessionFromKeyPacket(keyPackage []byte, privateKey string, passphrase string) (*SessionSplit, error) {
keyReader := bytes.NewReader(keyPackage)
packets := packet.NewReader(keyReader)
var p packet.Packet
var err error
if p, err = packets.Next(); err != nil {
return nil, err
}
ek := p.(*packet.EncryptedKey)
privKey := strings.NewReader(privateKey)
privKeyEntries, err := openpgp.ReadArmoredKeyRing(privKey)
if err != nil {
return nil, err
}
rawPwd := []byte(passphrase)
var decryptErr error
for _, key := range privKeyEntries.DecryptionKeys() {
priv := key.PrivateKey
if priv.Encrypted {
if err := priv.Decrypt(rawPwd); err != nil {
continue
}
}
if decryptErr = ek.Decrypt(priv, nil); decryptErr == nil {
break
}
}
if decryptErr != nil {
return nil, err
}
return getSessionSplit(ek)
}
//KeyPacketWithPublicKey ...
func KeyPacketWithPublicKey(sessionSplit *SessionSplit, publicKey string) ([]byte, error) {
pubkeyRaw, err := UnArmor(publicKey)
if err != nil {
return nil, err
}
return KeyPacketWithPublicKeyBin(sessionSplit, pubkeyRaw)
}
// KeyPacketWithPublicKeyBin ...
func KeyPacketWithPublicKeyBin(sessionSplit *SessionSplit, publicKey []byte) ([]byte, error) {
publicKeyReader := bytes.NewReader(publicKey)
pubKeyEntries, err := openpgp.ReadKeyRing(publicKeyReader)
outbuf := &bytes.Buffer{}
cf := cipherFunc(sessionSplit.Algo)
if len(pubKeyEntries) == 0 {
return nil, errors.New("cannot set key: key ring is empty")
}
var pub *packet.PublicKey
for _, e := range pubKeyEntries {
for _, subKey := range e.Subkeys {
if !subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications {
pub = subKey.PublicKey
break
}
}
if pub == nil && len(e.Identities) > 0 {
var i *openpgp.Identity
for _, i = range e.Identities {
break
}
if i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptStorage || i.SelfSignature.FlagEncryptCommunications {
pub = e.PrimaryKey
}
}
if pub != nil {
break
}
}
if pub == nil {
return nil, errors.New("cannot set key: no public key available")
}
if err = packet.SerializeEncryptedKey(outbuf, pub, cf, sessionSplit.Session, nil); err != nil {
err = fmt.Errorf("pmapi: cannot set key: %v", err)
return nil, errors.New("cannot set key: key ring is empty")
}
return outbuf.Bytes(), nil
}
//GetSessionFromSymmetricPacket ...
func GetSessionFromSymmetricPacket(keyPackage []byte, password string) (*SessionSplit, error) {
keyReader := bytes.NewReader(keyPackage)
packets := packet.NewReader(keyReader)
var symKeys []*packet.SymmetricKeyEncrypted
for {
var p packet.Packet
var err error
if p, err = packets.Next(); err != nil {
break
}
switch p := p.(type) {
case *packet.SymmetricKeyEncrypted:
symKeys = append(symKeys, p)
}
}
pwdRaw := []byte(password)
// Try the symmetric passphrase first
if len(symKeys) != 0 && pwdRaw != nil {
for _, s := range symKeys {
key, cipherFunc, err := s.Decrypt(pwdRaw)
if err == nil {
return &SessionSplit{
Session: key,
Algo: getAlgo(cipherFunc),
}, nil
}
}
}
return nil, errors.New("password incorrect")
}
// SymmetricKeyPacketWithPassword ...
func SymmetricKeyPacketWithPassword(sessionSplit *SessionSplit, password string) ([]byte, error) {
outbuf := &bytes.Buffer{}
cf := cipherFunc(sessionSplit.Algo)
if len(password) <= 0 {
return nil, errors.New("password can't be empty")
}
pwdRaw := []byte(password)
config := &packet.Config{
DefaultCipher: cf,
}
err := packet.SerializeSymmetricKeyEncryptedReuseKey(outbuf, sessionSplit.Session, pwdRaw, config)
if err != nil {
return nil, err
}
return outbuf.Bytes(), nil
}
//symKeyAlgos ...
var symKeyAlgos = map[string]packet.CipherFunction{
"3des": packet.Cipher3DES,
"cast5": packet.CipherCAST5,
"aes128": packet.CipherAES128,
"aes192": packet.CipherAES192,
"aes256": packet.CipherAES256,
}
// Get cipher function.
func cipherFunc(algo string) packet.CipherFunction {
cf, ok := symKeyAlgos[algo]
if ok {
return cf
}
return packet.CipherAES256
}
func getSessionSplit(ek *packet.EncryptedKey) (*SessionSplit, error) {
if ek == nil {
return nil, errors.New("can't decrypt key packet")
}
algo := "aes256"
for k, v := range symKeyAlgos {
if v == ek.CipherFunc {
algo = k
break
}
}
return &SessionSplit{
Session: ek.Key,
Algo: algo,
}, nil
}
func getAlgo(cipher packet.CipherFunction) string {
algo := "aes256"
for k, v := range symKeyAlgos {
if v == cipher {
algo = k
break
}
}
return algo
}
//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
}
//SeparateKeyAndData ...
func SeparateKeyAndData(encrypted string) (*EncryptedSplit, error) {
var err error
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 := &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
}