From 1dc0808cd73465db36c96854ffcef2fa544e1686 Mon Sep 17 00:00:00 2001 From: Lukas Burkhalter Date: Wed, 22 Nov 2023 14:50:53 +0100 Subject: [PATCH] refactor(packet): Implement feedback for private and pubic key packet --- openpgp/packet/packet.go | 2 + openpgp/packet/private_key.go | 2 +- openpgp/packet/public_key.go | 71 +++++++++++++++++------------------ openpgp/packet/signature.go | 10 ++--- 4 files changed, 41 insertions(+), 44 deletions(-) diff --git a/openpgp/packet/packet.go b/openpgp/packet/packet.go index aea52cabc..da12fbce0 100644 --- a/openpgp/packet/packet.go +++ b/openpgp/packet/packet.go @@ -666,6 +666,8 @@ const ( keyVersionSize = 1 // keyIdSize is the length in bytes of the key identifier value. keyIdSize = 8 + // timestampSize is the length in bytes of encoded timestamps. + timestampSize = 4 // fingerprintSizeV6 is the length in bytes of the key fingerprint in v6. fingerprintSizeV6 = 32 // fingerprintSize is the length in bytes of the key fingerprint. diff --git a/openpgp/packet/private_key.go b/openpgp/packet/private_key.go index 3f67b8c0a..cf7819f77 100644 --- a/openpgp/packet/private_key.go +++ b/openpgp/packet/private_key.go @@ -839,7 +839,7 @@ func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { case PubKeyAlgoEd448: return pk.parseEd448PrivateKey(data) default: - err = errors.InvalidArgumentError("unknown private key type") + err = errors.StructuralError("unknown private key type") return } } diff --git a/openpgp/packet/public_key.go b/openpgp/packet/public_key.go index 3be8e04fe..dcc5e7771 100644 --- a/openpgp/packet/public_key.go +++ b/openpgp/packet/public_key.go @@ -32,9 +32,6 @@ import ( "github.com/ProtonMail/go-crypto/openpgp/x448" ) -type kdfHashFunction byte -type kdfAlgorithm byte - // PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. type PublicKey struct { Version int @@ -570,9 +567,15 @@ func (pk *PublicKey) SerializeForHash(w io.Writer) error { // RFC 4880, section 5.2.4. func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) { var pLength = pk.algorithmSpecificByteCount() + // version, timestamp, algorithm + pLength += versionSize + timestampSize + algorithmSize if pk.Version >= 5 { - pLength += 10 // version, timestamp (4), algorithm, key octet count (4). + // key octet count (4). + pLength += 4 w.Write([]byte{ + // When a v4 signature is made over a key, the hash data starts with the octet 0x99, followed by a two-octet length + // of the key, and then the body of the key packet. When a v6 signature is made over a key, the hash data starts + // with the salt, then octet 0x9B, followed by a four-octet length of the key, and then the body of the key packet. 0x95 + byte(pk.Version), byte(pLength >> 24), byte(pLength >> 16), @@ -581,12 +584,11 @@ func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) { }) return } - pLength += 6 w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) } func (pk *PublicKey) Serialize(w io.Writer) (err error) { - length := 6 // 6 byte header + length := uint32(versionSize + timestampSize + algorithmSize) // 6 byte header length += pk.algorithmSpecificByteCount() if pk.Version >= 5 { length += 4 // octet key count @@ -595,38 +597,38 @@ func (pk *PublicKey) Serialize(w io.Writer) (err error) { if pk.IsSubkey { packetType = packetTypePublicSubkey } - err = serializeHeader(w, packetType, length) + err = serializeHeader(w, packetType, int(length)) if err != nil { return } return pk.serializeWithoutHeaders(w) } -func (pk *PublicKey) algorithmSpecificByteCount() int { - length := 0 +func (pk *PublicKey) algorithmSpecificByteCount() uint32 { + length := uint32(0) switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - length += int(pk.n.EncodedLength()) - length += int(pk.e.EncodedLength()) + length += uint32(pk.n.EncodedLength()) + length += uint32(pk.e.EncodedLength()) case PubKeyAlgoDSA: - length += int(pk.p.EncodedLength()) - length += int(pk.q.EncodedLength()) - length += int(pk.g.EncodedLength()) - length += int(pk.y.EncodedLength()) + length += uint32(pk.p.EncodedLength()) + length += uint32(pk.q.EncodedLength()) + length += uint32(pk.g.EncodedLength()) + length += uint32(pk.y.EncodedLength()) case PubKeyAlgoElGamal: - length += int(pk.p.EncodedLength()) - length += int(pk.g.EncodedLength()) - length += int(pk.y.EncodedLength()) + length += uint32(pk.p.EncodedLength()) + length += uint32(pk.g.EncodedLength()) + length += uint32(pk.y.EncodedLength()) case PubKeyAlgoECDSA: - length += int(pk.oid.EncodedLength()) - length += int(pk.p.EncodedLength()) + length += uint32(pk.oid.EncodedLength()) + length += uint32(pk.p.EncodedLength()) case PubKeyAlgoECDH: - length += int(pk.oid.EncodedLength()) - length += int(pk.p.EncodedLength()) - length += int(pk.kdf.EncodedLength()) + length += uint32(pk.oid.EncodedLength()) + length += uint32(pk.p.EncodedLength()) + length += uint32(pk.kdf.EncodedLength()) case PubKeyAlgoEdDSA: - length += int(pk.oid.EncodedLength()) - length += int(pk.p.EncodedLength()) + length += uint32(pk.oid.EncodedLength()) + length += uint32(pk.p.EncodedLength()) case PubKeyAlgoX25519: length += x25519.KeySize case PubKeyAlgoX448: @@ -897,8 +899,7 @@ func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signed *Pub // userIdSignatureHash returns a Hash of the message that needs to be signed // to assert that pk is a valid key for id. -func userIdSignatureHash(id string, pk *PublicKey, hash hash.Hash) (h hash.Hash, err error) { - h = hash +func userIdSignatureHash(id string, pk *PublicKey, h hash.Hash) (err error) { // RFC 4880, section 5.2.4 pk.SerializeSignaturePrefix(h) @@ -913,13 +914,11 @@ func userIdSignatureHash(id string, pk *PublicKey, hash hash.Hash) (h hash.Hash, h.Write(buf[:]) h.Write([]byte(id)) - return + return nil } // directSignatureHash returns a Hash of the message that needs to be signed -func directKeySignatureHash(pk *PublicKey, hash hash.Hash) (h hash.Hash, err error) { - h = hash - +func directKeySignatureHash(pk *PublicKey, h hash.Hash) (err error) { // RFC 4880, section 5.2.4 pk.SerializeSignaturePrefix(h) pk.serializeWithoutHeaders(h) @@ -930,12 +929,11 @@ func directKeySignatureHash(pk *PublicKey, hash hash.Hash) (h hash.Hash, err err // VerifyUserIdSignature returns nil iff sig is a valid signature, made by this // public key, that id is the identity of pub. func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { - preparedHash, err := sig.PrepareVerify() + h, err := sig.PrepareVerify() if err != nil { return err } - h, err := userIdSignatureHash(id, pub, preparedHash) - if err != nil { + if err := userIdSignatureHash(id, pub, h); err != nil { return err } return pk.VerifySignature(h, sig) @@ -944,12 +942,11 @@ func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signa // VerifyUserIdSignature returns nil iff sig is a valid signature, made by this // public key func (pk *PublicKey) VerifyDirectKeySignature(sig *Signature) (err error) { - preparedHash, err := sig.PrepareVerify() + h, err := sig.PrepareVerify() if err != nil { return err } - h, err := directKeySignatureHash(pk, preparedHash) - if err != nil { + if err := directKeySignatureHash(pk, h); err != nil { return err } return pk.VerifySignature(h, sig) diff --git a/openpgp/packet/signature.go b/openpgp/packet/signature.go index 0e7c43600..81b6c2ab5 100644 --- a/openpgp/packet/signature.go +++ b/openpgp/packet/signature.go @@ -952,11 +952,10 @@ func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, co if err != nil { return err } - h, err := userIdSignatureHash(id, pub, prepareHash) - if err != nil { + if err := userIdSignatureHash(id, pub, prepareHash); err != nil { return err } - return sig.Sign(h, priv, config) + return sig.Sign(prepareHash, priv, config) } // SignUserId computes a signature from priv @@ -971,11 +970,10 @@ func (sig *Signature) SignDirectKeyBinding(pub *PublicKey, priv *PrivateKey, con if err != nil { return err } - h, err := directKeySignatureHash(pub, prepareHash) - if err != nil { + if err := directKeySignatureHash(pub, prepareHash); err != nil { return err } - return sig.Sign(h, priv, config) + return sig.Sign(prepareHash, priv, config) } // CrossSignKey computes a signature from signingKey on pub hashed using hashKey. On success,