Skip to content

Commit

Permalink
refactor(packet): Implement feedback for private and pubic key packet
Browse files Browse the repository at this point in the history
  • Loading branch information
lubux committed Nov 22, 2023
1 parent ddb84e3 commit 1dc0808
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 44 deletions.
2 changes: 2 additions & 0 deletions openpgp/packet/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion openpgp/packet/private_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
71 changes: 34 additions & 37 deletions openpgp/packet/public_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand All @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
10 changes: 4 additions & 6 deletions openpgp/packet/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down

0 comments on commit 1dc0808

Please sign in to comment.