Skip to content

Commit

Permalink
Bind PQC packets to v6
Browse files Browse the repository at this point in the history
  • Loading branch information
wussler committed May 17, 2023
1 parent 4d9ba00 commit eea5d0b
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 217 deletions.
6 changes: 3 additions & 3 deletions openpgp/key_generation.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ func newSigner(config *packet.Config) (signer interface{}, err error) {
case packet.PubKeyAlgoDilithium3p256, packet.PubKeyAlgoDilithium5p384, packet.PubKeyAlgoDilithium3Brainpool256,
packet.PubKeyAlgoDilithium5Brainpool384:
if !config.V6() {
return nil, goerrors.New("openpgp: cannot create a non-v5 dilithium_ecdsa key")
return nil, goerrors.New("openpgp: cannot create a non-v6 dilithium_ecdsa key")
}

c, err := packet.GetECDSACurveFromAlgID(config.PublicKeyAlgorithm())
Expand All @@ -325,7 +325,7 @@ func newSigner(config *packet.Config) (signer interface{}, err error) {
return dilithium_ecdsa.GenerateKey(config.Random(), uint8(config.PublicKeyAlgorithm()), c, d)
case packet.PubKeyAlgoDilithium3Ed25519, packet.PubKeyAlgoDilithium5Ed448:
if !config.V6() {
return nil, goerrors.New("openpgp: cannot create a non-v5 dilithium_eddsa key")
return nil, goerrors.New("openpgp: cannot create a non-v6 dilithium_eddsa key")
}

c, err := packet.GetEdDSACurveFromAlgID(config.PublicKeyAlgorithm())
Expand Down Expand Up @@ -396,7 +396,7 @@ func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
case packet.PubKeyAlgoKyber768X25519, packet.PubKeyAlgoKyber1024X448, packet.PubKeyAlgoKyber768P256,
packet.PubKeyAlgoKyber1024P384, packet.PubKeyAlgoKyber768Brainpool256, packet.PubKeyAlgoKyber1024Brainpool384:
if !config.V6() {
return nil, goerrors.New("openpgp: cannot create a non-v5 kyber_ecdh key")
return nil, goerrors.New("openpgp: cannot create a non-v6 kyber_ecdh key")
}

c, err := packet.GetECDHCurveFromAlgID(pubKeyAlgo)
Expand Down
210 changes: 1 addition & 209 deletions openpgp/keys_v5_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,10 @@ package openpgp

import (
"bytes"
"crypto"
"crypto/rand"
"github.com/ProtonMail/go-crypto/openpgp/dilithium_ecdsa"
"github.com/ProtonMail/go-crypto/openpgp/dilithium_eddsa"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/kyber_ecdh"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/ProtonMail/go-crypto/openpgp/sphincs_plus"
"github.com/ProtonMail/go-crypto/openpgp/armor"
"io/ioutil"
"strings"
"testing"
"time"

"github.com/ProtonMail/go-crypto/openpgp/armor"
)

var foreignKeys = []string{
Expand Down Expand Up @@ -211,201 +201,3 @@ func checkSerializeRead(t *testing.T, e *Entity) {
}
checkV5Key(t, el[0])
}

func TestGeneratePqKey(t *testing.T) {
randomPassword := make([]byte, 128)
_, err := rand.Read(randomPassword)
if err != nil {
t.Fatal(err)
}

asymmAlgos := map[string] packet.PublicKeyAlgorithm{
"Dilithium3_Ed25519": packet.PubKeyAlgoDilithium3Ed25519,
"Dilithium5_Ed448": packet.PubKeyAlgoDilithium5Ed448,
"Dilithium3_P256": packet.PubKeyAlgoDilithium3p256,
"Dilithium5_P384":packet.PubKeyAlgoDilithium5p384,
"Dilithium3_Brainpool256": packet.PubKeyAlgoDilithium3Brainpool256,
"Dilithium5_Brainpool384":packet.PubKeyAlgoDilithium5Brainpool384,
"SphincsPlus_simple_SHA2":packet.PubKeyAlgoSphincsPlusSha2,
"SphincsPlus_simple_SHAKE":packet.PubKeyAlgoSphincsPlusShake,
}

for name, algo := range asymmAlgos {
t.Run(name, func(t *testing.T) {
config := &packet.Config{
DefaultHash: crypto.SHA512,
Algorithm: algo,
V6Keys: true,
Time: func() time.Time {
parsed, _ := time.Parse("2006-01-02", "2013-07-01")
return parsed
},
}

entity, err := NewEntity("Golang Gopher", "Test Key", "[email protected]", config)
if err != nil {
t.Fatal(err)
}

serializedEntity := bytes.NewBuffer(nil)
err = entity.SerializePrivate(serializedEntity, nil)
if err != nil {
t.Fatalf("Failed to serialize entity: %s", err)
}

read, err := ReadEntity(packet.NewReader(bytes.NewBuffer(serializedEntity.Bytes())))
if err != nil {
t.Fatalf("Failed to parse entity: %s", err)
}

if read.PrimaryKey.PubKeyAlgo != algo {
t.Fatalf("Expected subkey algorithm: %v, got: %v", algo, read.PrimaryKey.PubKeyAlgo)
}

if err = read.PrivateKey.Encrypt(randomPassword); err != nil {
t.Fatal(err)
}

if err := read.PrivateKey.Decrypt(randomPassword); err != nil {
t.Fatal("Valid Dilithium key was marked as invalid: ", err)
}

if err = read.PrivateKey.Encrypt(randomPassword); err != nil {
t.Fatal(err)
}

// Corrupt public Dilithium in primary key
if pk, ok := read.PrivateKey.PublicKey.PublicKey.(*dilithium_ecdsa.PublicKey); ok {
bin := pk.PublicDilithium.Bytes()
bin[5] ^= 1
pk.PublicDilithium = pk.Dilithium.PublicKeyFromBytes(bin)
}

if pk, ok := read.PrivateKey.PublicKey.PublicKey.(*dilithium_eddsa.PublicKey); ok {
bin := pk.PublicDilithium.Bytes()
bin[5] ^= 1
pk.PublicDilithium = pk.Dilithium.PublicKeyFromBytes(bin)
}

if pk, ok := read.PrivateKey.PublicKey.PublicKey.(*sphincs_plus.PublicKey); ok {
pk.PublicData.PKseed[5] ^= 1
}

err = read.PrivateKey.Decrypt(randomPassword)
if _, ok := err.(errors.KeyInvalidError); !ok {
t.Fatal("Failed to detect invalid Dilithium key")
}

testKyberSubkey(t, read.Subkeys[0], randomPassword)
})
}
}

func testKyberSubkey(t *testing.T, subkey Subkey, randomPassword []byte) {
var err error
if err = subkey.PrivateKey.Encrypt(randomPassword); err != nil {
t.Fatal(err)
}

if err = subkey.PrivateKey.Decrypt(randomPassword); err != nil {
t.Fatal("Valid Kyber key was marked as invalid: ", err)
}

if err = subkey.PrivateKey.Encrypt(randomPassword); err != nil {
t.Fatal(err)
}

// Corrupt public Kyber in primary key
if pk, ok := subkey.PublicKey.PublicKey.(*kyber_ecdh.PublicKey); ok {
bin, _ := pk.PublicKyber.MarshalBinary()
bin[5] ^= 1
if pk.PublicKyber, err = pk.Kyber.UnmarshalBinaryPublicKey(bin); err != nil {
t.Fatal("unable to corrupt key")
}
} else {
t.Fatal("Invalid subkey")
}

err = subkey.PrivateKey.Decrypt(randomPassword)
if _, ok := err.(errors.KeyInvalidError); !ok {
t.Fatal("Failed to detect invalid kyber key")
}
}


func TestAddKyberSubkey(t *testing.T) {
eddsaConfig := &packet.Config{
DefaultHash: crypto.SHA512,
Algorithm: packet.PubKeyAlgoEdDSA,
V6Keys: true,
Time: func() time.Time {
parsed, _ := time.Parse("2006-01-02", "2013-07-01")
return parsed
},
}

entity, err := NewEntity("Golang Gopher", "Test Key", "[email protected]", eddsaConfig)
if err != nil {
t.Fatal(err)
}

asymmAlgos := map[string] packet.PublicKeyAlgorithm{
"Kyber768_X25519": packet.PubKeyAlgoKyber768X25519,
"Kyber1024_X448": packet.PubKeyAlgoKyber1024X448,
"Kyber768_P256": packet.PubKeyAlgoKyber768P256,
"Kyber1024_P384":packet.PubKeyAlgoKyber1024P384,
"Kyber768_Brainpool256": packet.PubKeyAlgoKyber768Brainpool256,
"Kyber1024_Brainpool384":packet.PubKeyAlgoKyber1024Brainpool384,
}

for name, algo := range asymmAlgos {
// Remove existing subkeys
entity.Subkeys = []Subkey{}

t.Run(name, func(t *testing.T) {
kyberConfig := &packet.Config{
DefaultHash: crypto.SHA512,
Algorithm: algo,
V6Keys: true,
Time: func() time.Time {
parsed, _ := time.Parse("2006-01-02", "2013-07-01")
return parsed
},
}

err = entity.AddEncryptionSubkey(kyberConfig)
if err != nil {
t.Fatal(err)
}

if len(entity.Subkeys) != 1 {
t.Fatalf("Expected 1 subkey, got %d", len(entity.Subkeys))
}

if entity.Subkeys[0].PublicKey.PubKeyAlgo != algo {
t.Fatalf("Expected subkey algorithm: %v, got: %v", packet.PubKeyAlgoEdDSA,
entity.Subkeys[0].PublicKey.PubKeyAlgo)
}

serializedEntity := bytes.NewBuffer(nil)
err = entity.SerializePrivate(serializedEntity, nil)
if err != nil {
t.Fatalf("Failed to serialize entity: %s", err)
}

read, err := ReadEntity(packet.NewReader(bytes.NewBuffer(serializedEntity.Bytes())))
if err != nil {
t.Fatal(err)
}

if len(read.Subkeys) != 1 {
t.Fatalf("Expected 1 subkey, got %d", len(entity.Subkeys))
}

if read.Subkeys[0].PublicKey.PubKeyAlgo != algo {
t.Fatalf("Expected subkey algorithm: %v, got: %v", packet.PubKeyAlgoEdDSA,
entity.Subkeys[0].PublicKey.PubKeyAlgo)
}
})
}
}
Loading

0 comments on commit eea5d0b

Please sign in to comment.