Skip to content

Commit

Permalink
Add references and clean code
Browse files Browse the repository at this point in the history
  • Loading branch information
wussler committed Dec 27, 2022
1 parent 5e0fd67 commit 5f2b117
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 94 deletions.
6 changes: 6 additions & 0 deletions openpgp/dilithium_ecdsa/dilithium_ecdsa.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Package dilithium_ecdsa implements hybrid Dilithium + ECDSA encryption, suitable for OpenPGP, experimental.
// It follows the specs https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#name-composite-signature-schemes-3
package dilithium_ecdsa

import (
Expand Down Expand Up @@ -67,6 +68,8 @@ func GenerateKey(rand io.Reader, algId uint8, c ecc.ECDSACurve, d dilithium.Mode
return
}

// Sign generates a Dilithium + ECDSA composite signature as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-5.2.2
func Sign(rand io.Reader, priv *PrivateKey, message []byte) (dSig, ecR, ecS []byte, err error) {
r, s, err := priv.PublicKey.Curve.Sign(rand, priv.PublicKey.X, priv.PublicKey.Y, priv.SecretEC, message)
if err != nil {
Expand All @@ -84,13 +87,16 @@ func Sign(rand io.Reader, priv *PrivateKey, message []byte) (dSig, ecR, ecS []by
return
}

// Verify verifies a Dilithium + ECDSA composite signature as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-5.2.3
func Verify(pub *PublicKey, message, dSig, ecR, ecS []byte) bool {
r := pub.Curve.UnmarshalFieldInteger(ecR)
s := pub.Curve.UnmarshalFieldInteger(ecS)

return pub.Curve.Verify(pub.X, pub.Y, message, r, s) && pub.Dilithium.Verify(pub.PublicDilithium, message, dSig)
}

// Validate checks that the public key corresponds to the private key
func Validate(priv *PrivateKey) (err error) {
if err = priv.PublicKey.Curve.ValidateECDSA(priv.PublicKey.X, priv.PublicKey.Y, priv.SecretEC.Bytes()); err != nil {
return err
Expand Down
6 changes: 6 additions & 0 deletions openpgp/dilithium_eddsa/dilithium_eddsa.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Package dilithium_eddsa implements hybrid Dilithium + EdDSA encryption, suitable for OpenPGP, experimental.
// It follows the specs https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#name-composite-signature-schemes-3
package dilithium_eddsa

import (
Expand Down Expand Up @@ -41,6 +42,8 @@ func GenerateKey(rand io.Reader, algId uint8, c ecc.EdDSACurve, d dilithium.Mode
return
}

// Sign generates a Dilithium + EdDSA composite signature as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-5.2.2
func Sign(priv *PrivateKey, message []byte) (dSig, ecSig []byte, err error) {
ecSig, err = priv.PublicKey.Curve.Sign(priv.PublicKey.PublicPoint, priv.SecretEC, message)
if err != nil {
Expand All @@ -55,10 +58,13 @@ func Sign(priv *PrivateKey, message []byte) (dSig, ecSig []byte, err error) {
return
}

// Verify verifies a Dilithium + EdDSA composite signature as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-5.2.3
func Verify(pub *PublicKey, message, dSig, ecSig []byte) bool {
return pub.Curve.Verify(pub.PublicPoint, message, ecSig) && pub.Dilithium.Verify(pub.PublicDilithium, message, dSig)
}

// Validate checks that the public key corresponds to the private key
func Validate(priv *PrivateKey) (err error) {
if err = priv.PublicKey.Curve.ValidateEdDSA(priv.PublicKey.PublicPoint, priv.SecretEC); err != nil {
return err
Expand Down
5 changes: 3 additions & 2 deletions openpgp/kyber_ecdh/kyber_ecdh.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Package kyber_ecdh implements hybrid Kyber + ECDH encryption, suitable for OpenPGP, experimental.
// It follows the spec https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-4
package kyber_ecdh

import (
Expand Down Expand Up @@ -112,7 +113,7 @@ func Decrypt(priv *PrivateKey, kEphemeral, ecEphemeral, ciphertext, publicKeyHas

msg, err = keywrap.Unwrap(z, ciphertext)

return msg, nil
return msg, err
}

// buildKey implements the composite KDF as specified in
Expand All @@ -134,7 +135,7 @@ func buildKey(pub *PublicKey, eccKeyShare, kyberKeyShare, publicKeyHash []byte)
return k.Sum(nil), nil
}


// Validate checks that the public key corresponds to the private key
func Validate(priv *PrivateKey) (err error) {
if err = priv.PublicKey.Curve.ValidateECDH(priv.PublicKey.PublicPoint, priv.SecretEC); err != nil {
return err
Expand Down
2 changes: 2 additions & 0 deletions openpgp/packet/encrypted_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ func (e *EncryptedKey) parse(r io.Reader) (err error) {
return
}

// readKyberECDHKey reads Kyber + ECC PKESK as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-4.3.1
func (e *EncryptedKey) readKyberECDHKey(r io.Reader, lenEcc, lenKyber int) (err error){
e.encryptedMPI1 = encoding.NewEmptyOctetArray(lenEcc)
if _, err = e.encryptedMPI1.ReadFrom(r); err != nil {
Expand Down
32 changes: 14 additions & 18 deletions openpgp/packet/private_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -564,30 +564,20 @@ func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
return pk.parseECDHPrivateKey(data)
case PubKeyAlgoEdDSA:
return pk.parseEdDSAPrivateKey(data)
case PubKeyAlgoKyber768X25519, PubKeyAlgoKyber768P256, PubKeyAlgoKyber768Brainpool256:
return pk.parseKyberECDHPrivateKey(data, 32, 2400)
case PubKeyAlgoKyber1024X448:
return pk.parseKyberECDHPrivateKey(data, 56, 3168)
case PubKeyAlgoKyber1024P384, PubKeyAlgoKyber1024Brainpool384:
return pk.parseKyberECDHPrivateKey(data, 48, 3168)
case PubKeyAlgoDilithium3Ed25519:
return pk.parseDilithiumEdDSAPrivateKey(data, 32, 4000)
case PubKeyAlgoDilithium5Ed448:
return pk.parseDilithiumEdDSAPrivateKey(data, 57, 4864)
case PubKeyAlgoDilithium3p256:
case PubKeyAlgoDilithium3p256, PubKeyAlgoDilithium3Brainpool256:
return pk.parseDilithiumECDSAPrivateKey(data, 32, 4000)
case PubKeyAlgoDilithium5p384:
case PubKeyAlgoDilithium5p384, PubKeyAlgoDilithium5Brainpool384:
return pk.parseDilithiumECDSAPrivateKey(data, 48, 4864)
case PubKeyAlgoDilithium3Brainpool256:
return pk.parseDilithiumECDSAPrivateKey(data, 32, 4000)
case PubKeyAlgoDilithium5Brainpool384:
return pk.parseDilithiumECDSAPrivateKey(data, 48, 4864)
case PubKeyAlgoKyber768X25519:
return pk.parseKyberECDHPrivateKey(data, 32, 2400)
case PubKeyAlgoKyber1024X448:
return pk.parseKyberECDHPrivateKey(data, 56, 3168)
case PubKeyAlgoKyber768P256:
return pk.parseKyberECDHPrivateKey(data, 32, 2400)
case PubKeyAlgoKyber1024P384:
return pk.parseKyberECDHPrivateKey(data, 48, 3168)
case PubKeyAlgoKyber768Brainpool256:
return pk.parseKyberECDHPrivateKey(data, 32, 2400)
case PubKeyAlgoKyber1024Brainpool384:
return pk.parseKyberECDHPrivateKey(data, 48, 3168)
}
panic("impossible")
}
Expand Down Expand Up @@ -734,6 +724,8 @@ func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
return nil
}

// parseDilithiumECDSAPrivateKey parses a Dilithium + ECDSA private key as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-5.3.2
func (pk *PrivateKey) parseDilithiumECDSAPrivateKey(data []byte, ecLen, dLen int) (err error) {
if pk.Version != 5 {
return goerrors.New("openpgp: cannot parse non-v5 dilithium_ecdsa key")
Expand Down Expand Up @@ -767,6 +759,8 @@ func (pk *PrivateKey) parseDilithiumECDSAPrivateKey(data []byte, ecLen, dLen int
return nil
}

// parseDilithiumEdDSAPrivateKey parses a Dilithium + EdDSA private key as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-5.3.2
func (pk *PrivateKey) parseDilithiumEdDSAPrivateKey(data []byte, ecLen, dLen int) (err error) {
if pk.Version != 5 {
return goerrors.New("openpgp: cannot parse non-v5 dilithium_eddsa key")
Expand Down Expand Up @@ -796,6 +790,8 @@ func (pk *PrivateKey) parseDilithiumEdDSAPrivateKey(data []byte, ecLen, dLen int
return nil
}

// parseKyberECDHPrivateKey parses a Kyber + ECC private key as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-4.3.2
func (pk *PrivateKey) parseKyberECDHPrivateKey(data []byte, ecLen, kLen int) (err error) {
if pk.Version != 5 {
return goerrors.New("openpgp: cannot parse non-v5 kyber_ecdh key")
Expand Down
34 changes: 16 additions & 18 deletions openpgp/packet/public_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,30 +271,22 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
err = pk.parseECDH(r)
case PubKeyAlgoEdDSA:
err = pk.parseEdDSA(r)
case PubKeyAlgoDilithium3Ed25519:
err = pk.parseDilithiumEdDSA(r, 32, 1952)
case PubKeyAlgoDilithium5Ed448:
err = pk.parseDilithiumEdDSA(r, 57, 2592)
case PubKeyAlgoDilithium3p256:
err = pk.parseDilithiumECDSA(r, 65, 1952)
case PubKeyAlgoDilithium5p384:
err = pk.parseDilithiumECDSA(r, 97, 2592)
case PubKeyAlgoDilithium3Brainpool256:
err = pk.parseDilithiumECDSA(r, 65, 1952)
case PubKeyAlgoDilithium5Brainpool384:
err = pk.parseDilithiumECDSA(r, 97, 2592)
case PubKeyAlgoKyber768X25519:
err = pk.parseKyberECDH(r, 32, 1184)
case PubKeyAlgoKyber1024X448:
err = pk.parseKyberECDH(r, 56, 1568)
case PubKeyAlgoKyber768P256:
err = pk.parseKyberECDH(r, 65, 1184)
case PubKeyAlgoKyber1024P384:
err = pk.parseKyberECDH(r, 97, 1568)
case PubKeyAlgoKyber768Brainpool256:
case PubKeyAlgoKyber768P256, PubKeyAlgoKyber768Brainpool256:
err = pk.parseKyberECDH(r, 65, 1184)
case PubKeyAlgoKyber1024Brainpool384:
case PubKeyAlgoKyber1024P384, PubKeyAlgoKyber1024Brainpool384:
err = pk.parseKyberECDH(r, 97, 1568)
case PubKeyAlgoDilithium3Ed25519:
err = pk.parseDilithiumEdDSA(r, 32, 1952)
case PubKeyAlgoDilithium5Ed448:
err = pk.parseDilithiumEdDSA(r, 57, 2592)
case PubKeyAlgoDilithium3p256, PubKeyAlgoDilithium3Brainpool256:
err = pk.parseDilithiumECDSA(r, 65, 1952)
case PubKeyAlgoDilithium5p384, PubKeyAlgoDilithium5Brainpool384:
err = pk.parseDilithiumECDSA(r, 97, 2592)
default:
err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
}
Expand Down Expand Up @@ -482,6 +474,8 @@ func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
return
}

// parseKyberECDH parses a Kyber + ECC public key as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-4.3.2
func (pk *PublicKey) parseKyberECDH(r io.Reader, ecLen, kLen int) (err error) {
pk.p = encoding.NewEmptyOctetArray(ecLen)
if _, err = pk.p.ReadFrom(r); err != nil {
Expand Down Expand Up @@ -551,6 +545,8 @@ func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) {
return
}

// parseKyberECDH parses a Dilithium + ECDSA public key as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-5.3.2
func (pk *PublicKey) parseDilithiumECDSA(r io.Reader, ecLen, dLen int) (err error) {
pk.p = encoding.NewEmptyOctetArray(ecLen)
if _, err = pk.p.ReadFrom(r); err != nil {
Expand Down Expand Up @@ -585,6 +581,8 @@ func (pk *PublicKey) parseDilithiumECDSA(r io.Reader, ecLen, dLen int) (err erro
return
}

// parseKyberECDH parses a Dilithium + EdDSA public key as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-5.3.2
func (pk *PublicKey) parseDilithiumEdDSA(r io.Reader, ecLen, dLen int) (err error) {
pk.p = encoding.NewEmptyOctetArray(ecLen)
if _, err = pk.p.ReadFrom(r); err != nil {
Expand Down
91 changes: 35 additions & 56 deletions openpgp/packet/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,76 +199,55 @@ func (sig *Signature) parse(r io.Reader) (err error) {
return
}
case PubKeyAlgoDilithium3Ed25519:
sig.EdDSASigR = encoding.NewEmptyOctetArray(64)
if _, err = sig.EdDSASigR.ReadFrom(r); err != nil {
if err = sig.parseDilithiumEddsaSignature(r, 64, 3293); err != nil {
return
}

sig.DilithumSig = encoding.NewEmptyOctetArray(3293)
_, err = sig.DilithumSig.ReadFrom(r)
case PubKeyAlgoDilithium5Ed448:
sig.EdDSASigR = encoding.NewEmptyOctetArray(114)
if _, err = sig.EdDSASigR.ReadFrom(r); err != nil {
return
}

sig.DilithumSig = encoding.NewEmptyOctetArray(4595)
_, err = sig.DilithumSig.ReadFrom(r)
case PubKeyAlgoDilithium3p256:
sig.ECDSASigR = encoding.NewEmptyOctetArray(32)
if _, err = sig.ECDSASigR.ReadFrom(r); err != nil {
return
}

sig.ECDSASigS = encoding.NewEmptyOctetArray(32)
if _, err = sig.ECDSASigS.ReadFrom(r); err != nil {
if err = sig.parseDilithiumEddsaSignature(r, 114, 4595); err != nil {
return
}

sig.DilithumSig = encoding.NewEmptyOctetArray(3293)
_, err = sig.DilithumSig.ReadFrom(r)
case PubKeyAlgoDilithium5p384:
sig.ECDSASigR = encoding.NewEmptyOctetArray(48)
if _, err = sig.ECDSASigR.ReadFrom(r); err != nil {
return
}

sig.ECDSASigS = encoding.NewEmptyOctetArray(48)
if _, err = sig.ECDSASigS.ReadFrom(r); err != nil {
case PubKeyAlgoDilithium3p256, PubKeyAlgoDilithium3Brainpool256:
if err = sig.parseDilithiumEcdsaSignature(r, 32, 3293); err != nil {
return
}

sig.DilithumSig = encoding.NewEmptyOctetArray(4595)
_, err = sig.DilithumSig.ReadFrom(r)
case PubKeyAlgoDilithium3Brainpool256:
sig.ECDSASigR = encoding.NewEmptyOctetArray(32)
if _, err = sig.ECDSASigR.ReadFrom(r); err != nil {
case PubKeyAlgoDilithium5p384, PubKeyAlgoDilithium5Brainpool384:
if err = sig.parseDilithiumEcdsaSignature(r, 48, 4595); err != nil {
return
}
default:
panic("unreachable")
}
return
}

sig.ECDSASigS = encoding.NewEmptyOctetArray(32)
if _, err = sig.ECDSASigS.ReadFrom(r); err != nil {
return
}
// parseDilithiumEddsaSignature parses a Dilithium + EdDSA signature as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-5.3.1
func (sig *Signature) parseDilithiumEddsaSignature(r io.Reader, ecLen, dLen int) (err error) {
sig.EdDSASigR = encoding.NewEmptyOctetArray(ecLen)
if _, err = sig.EdDSASigR.ReadFrom(r); err != nil {
return
}

sig.DilithumSig = encoding.NewEmptyOctetArray(3293)
_, err = sig.DilithumSig.ReadFrom(r)
case PubKeyAlgoDilithium5Brainpool384:
sig.ECDSASigR = encoding.NewEmptyOctetArray(48)
if _, err = sig.ECDSASigR.ReadFrom(r); err != nil {
return
}
sig.DilithumSig = encoding.NewEmptyOctetArray(dLen)
_, err = sig.DilithumSig.ReadFrom(r)
return
}

sig.ECDSASigS = encoding.NewEmptyOctetArray(48)
if _, err = sig.ECDSASigS.ReadFrom(r); err != nil {
return
}
// parseDilithiumEcdsaSignature parses a Dilithium + ECDSA signature as specified in
// https://www.ietf.org/archive/id/draft-wussler-openpgp-pqc-00.html#section-5.3.1
func (sig *Signature) parseDilithiumEcdsaSignature(r io.Reader, ecLen, dLen int) (err error) {
sig.ECDSASigR = encoding.NewEmptyOctetArray(ecLen)
if _, err = sig.ECDSASigR.ReadFrom(r); err != nil {
return
}

sig.DilithumSig = encoding.NewEmptyOctetArray(4595)
_, err = sig.DilithumSig.ReadFrom(r)
default:
panic("unreachable")
sig.ECDSASigS = encoding.NewEmptyOctetArray(ecLen)
if _, err = sig.ECDSASigS.ReadFrom(r); err != nil {
return
}

sig.DilithumSig = encoding.NewEmptyOctetArray(dLen)
_, err = sig.DilithumSig.ReadFrom(r)
return
}

Expand Down

0 comments on commit 5f2b117

Please sign in to comment.