2018-09-11 11:09:28 +02:00
|
|
|
package crypto
|
2018-06-04 16:05:14 -07:00
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
2020-07-15 16:17:49 +07:00
|
|
|
"strconv"
|
2019-12-27 19:35:43 +01:00
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2018-06-04 16:05:14 -07:00
|
|
|
|
2020-12-08 18:34:39 +01:00
|
|
|
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
2018-06-04 16:05:14 -07:00
|
|
|
)
|
|
|
|
|
|
2020-11-13 14:13:11 +01:00
|
|
|
// DecryptSessionKey returns the decrypted session key from one or multiple binary encrypted session key packets.
|
2019-12-27 19:35:43 +01:00
|
|
|
func (keyRing *KeyRing) DecryptSessionKey(keyPacket []byte) (*SessionKey, error) {
|
2018-06-04 16:05:14 -07:00
|
|
|
var p packet.Packet
|
2020-11-13 14:13:11 +01:00
|
|
|
var ek *packet.EncryptedKey
|
2018-06-04 16:05:14 -07:00
|
|
|
|
2020-11-13 14:13:11 +01:00
|
|
|
var err error
|
|
|
|
|
var hasPacket = false
|
2018-06-04 16:05:14 -07:00
|
|
|
var decryptErr error
|
|
|
|
|
|
2020-11-13 14:13:11 +01:00
|
|
|
keyReader := bytes.NewReader(keyPacket)
|
|
|
|
|
packets := packet.NewReader(keyReader)
|
|
|
|
|
|
|
|
|
|
Loop:
|
|
|
|
|
for {
|
|
|
|
|
if p, err = packets.Next(); err != nil {
|
2018-06-04 16:05:14 -07:00
|
|
|
break
|
|
|
|
|
}
|
2020-11-13 14:13:11 +01:00
|
|
|
|
|
|
|
|
switch p := p.(type) {
|
|
|
|
|
case *packet.EncryptedKey:
|
|
|
|
|
hasPacket = true
|
|
|
|
|
ek = p
|
|
|
|
|
|
|
|
|
|
for _, key := range keyRing.entities.DecryptionKeys() {
|
|
|
|
|
priv := key.PrivateKey
|
|
|
|
|
if priv.Encrypted {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if decryptErr = ek.Decrypt(priv, nil); decryptErr == nil {
|
|
|
|
|
break Loop
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case *packet.SymmetricallyEncrypted,
|
|
|
|
|
*packet.AEADEncrypted,
|
|
|
|
|
*packet.Compressed,
|
|
|
|
|
*packet.LiteralData:
|
|
|
|
|
break Loop
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
continue Loop
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !hasPacket {
|
2021-03-09 19:06:35 +01:00
|
|
|
return nil, errors.Wrap(err, "gopenpgp: couldn't find a session key packet")
|
2018-06-04 16:05:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if decryptErr != nil {
|
2020-10-29 12:42:32 +01:00
|
|
|
return nil, errors.Wrap(decryptErr, "gopenpgp: error in decrypting")
|
2018-06-04 16:05:14 -07:00
|
|
|
}
|
|
|
|
|
|
2021-03-09 19:06:35 +01:00
|
|
|
if ek == nil || ek.Key == nil {
|
|
|
|
|
return nil, errors.New("gopenpgp: unable to decrypt session key: no valid decryption key")
|
2018-06-04 16:05:14 -07:00
|
|
|
}
|
2019-06-03 17:00:01 +02:00
|
|
|
|
2019-12-27 19:35:43 +01:00
|
|
|
return newSessionKeyFromEncrypted(ek)
|
2018-06-04 16:05:14 -07:00
|
|
|
}
|
|
|
|
|
|
2019-06-03 17:00:01 +02:00
|
|
|
// EncryptSessionKey encrypts the session key with the unarmored
|
2019-05-15 13:40:19 +02:00
|
|
|
// publicKey and returns a binary public-key encrypted session key packet.
|
2019-12-27 19:35:43 +01:00
|
|
|
func (keyRing *KeyRing) EncryptSessionKey(sk *SessionKey) ([]byte, error) {
|
2018-06-04 16:05:14 -07:00
|
|
|
outbuf := &bytes.Buffer{}
|
2019-12-27 19:35:43 +01:00
|
|
|
cf, err := sk.GetCipherFunc()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, errors.Wrap(err, "gopenpgp: unable to encrypt session key")
|
|
|
|
|
}
|
2018-06-04 16:05:14 -07:00
|
|
|
|
2020-07-15 16:17:49 +07:00
|
|
|
pubKeys := make([]*packet.PublicKey, 0, len(keyRing.entities))
|
2019-12-27 19:35:43 +01:00
|
|
|
for _, e := range keyRing.entities {
|
2020-07-15 16:17:49 +07:00
|
|
|
encryptionKey, ok := e.EncryptionKey(getNow())
|
|
|
|
|
if !ok {
|
|
|
|
|
return nil, errors.New("gopenpgp: encryption key is unavailable for key id " + strconv.FormatUint(e.PrimaryKey.KeyId, 16))
|
2018-06-04 16:05:14 -07:00
|
|
|
}
|
2020-07-15 16:17:49 +07:00
|
|
|
pubKeys = append(pubKeys, encryptionKey.PublicKey)
|
2018-06-04 16:05:14 -07:00
|
|
|
}
|
2020-07-10 00:31:57 +07:00
|
|
|
if len(pubKeys) == 0 {
|
2018-06-04 16:05:14 -07:00
|
|
|
return nil, errors.New("cannot set key: no public key available")
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-10 00:31:57 +07:00
|
|
|
for _, pub := range pubKeys {
|
|
|
|
|
if err := packet.SerializeEncryptedKey(outbuf, pub, cf, sk.Key, nil); err != nil {
|
2020-10-29 12:42:32 +01:00
|
|
|
return nil, errors.Wrap(err, "gopenpgp: cannot set key")
|
2020-07-10 00:31:57 +07:00
|
|
|
}
|
2018-06-04 16:05:14 -07:00
|
|
|
}
|
|
|
|
|
return outbuf.Bytes(), nil
|
|
|
|
|
}
|