crypto/openpgp: add serialization for encrypted key packets
The new function allows an existing encrypted key packet to be serialized to a Writer. Change-Id: I20d82ca473d8ae738d239068626897c1ff868a15 Reviewed-on: https://go-review.googlesource.com/3167 Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
committed by
Adam Langley
parent
9fb97e878d
commit
ecf53cc131
@@ -7,11 +7,12 @@ package packet
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"encoding/binary"
|
||||
"golang.org/x/crypto/openpgp/elgamal"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"io"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/crypto/openpgp/elgamal"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
const encryptedKeyVersion = 3
|
||||
@@ -24,7 +25,7 @@ type EncryptedKey struct {
|
||||
CipherFunc CipherFunction // only valid after a successful Decrypt
|
||||
Key []byte // only valid after a successful Decrypt
|
||||
|
||||
encryptedMPI1, encryptedMPI2 []byte
|
||||
encryptedMPI1, encryptedMPI2 parsedMPI
|
||||
}
|
||||
|
||||
func (e *EncryptedKey) parse(r io.Reader) (err error) {
|
||||
@@ -40,13 +41,13 @@ func (e *EncryptedKey) parse(r io.Reader) (err error) {
|
||||
e.Algo = PublicKeyAlgorithm(buf[9])
|
||||
switch e.Algo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
e.encryptedMPI1, _, err = readMPI(r)
|
||||
e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
|
||||
case PubKeyAlgoElGamal:
|
||||
e.encryptedMPI1, _, err = readMPI(r)
|
||||
e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e.encryptedMPI2, _, err = readMPI(r)
|
||||
e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r)
|
||||
}
|
||||
_, err = consumeAll(r)
|
||||
return
|
||||
@@ -71,10 +72,10 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
|
||||
// padding oracle attacks.
|
||||
switch priv.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1)
|
||||
b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes)
|
||||
case PubKeyAlgoElGamal:
|
||||
c1 := new(big.Int).SetBytes(e.encryptedMPI1)
|
||||
c2 := new(big.Int).SetBytes(e.encryptedMPI2)
|
||||
c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
|
||||
c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
|
||||
b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
|
||||
default:
|
||||
err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
|
||||
@@ -95,6 +96,36 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Serialize writes the encrypted key packet, e, to w.
|
||||
func (e *EncryptedKey) Serialize(w io.Writer) error {
|
||||
var mpiLen int
|
||||
switch e.Algo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
mpiLen = 2 + len(e.encryptedMPI1.bytes)
|
||||
case PubKeyAlgoElGamal:
|
||||
mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes)
|
||||
default:
|
||||
return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
|
||||
}
|
||||
|
||||
serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
|
||||
|
||||
w.Write([]byte{encryptedKeyVersion})
|
||||
binary.Write(w, binary.BigEndian, e.KeyId)
|
||||
w.Write([]byte{byte(e.Algo)})
|
||||
|
||||
switch e.Algo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
writeMPIs(w, e.encryptedMPI1)
|
||||
case PubKeyAlgoElGamal:
|
||||
writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2)
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SerializeEncryptedKey serializes an encrypted key packet to w that contains
|
||||
// key, encrypted to pub.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
|
||||
@@ -7,6 +7,7 @@ package packet
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rsa"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
@@ -123,3 +124,23 @@ func TestEncryptingEncryptedKey(t *testing.T) {
|
||||
t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSerializingEncryptedKey(t *testing.T) {
|
||||
const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
|
||||
|
||||
p, err := Read(readerFromHex(encryptedKeyHex))
|
||||
if err != nil {
|
||||
t.Fatalf("error from Read: %s", err)
|
||||
}
|
||||
ek, ok := p.(*EncryptedKey)
|
||||
if !ok {
|
||||
t.Fatalf("didn't parse an EncryptedKey, got %#v", p)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
ek.Serialize(&buf)
|
||||
|
||||
if bufHex := hex.EncodeToString(buf.Bytes()); bufHex != encryptedKeyHex {
|
||||
t.Fatalf("serialization of encrypted key differed from original. Original was %s, but reserialized as %s", encryptedKeyHex, bufHex)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user