Skip to content

Commit

Permalink
Merge pull request #340 from lukpueh/pad-pgp-eddsa-sig
Browse files Browse the repository at this point in the history
Optionally pad OpenPGP EdDSA signature parameters
  • Loading branch information
lukpueh authored Feb 25, 2021
2 parents 760523c + b55fa42 commit 6895306
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 0 deletions.
8 changes: 8 additions & 0 deletions securesystemslib/gpg/eddsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
# EdDSA Point Format (see RFC4880-bis8 13.3.)
ED25519_PUBLIC_KEY_LENGTH = 33
ED25519_PUBLIC_KEY_PREFIX = 0x40
# EdDSA signature byte length (see RFC 8032 5.1.6. (6))
ED25519_SIG_LENGTH = 64



Expand Down Expand Up @@ -140,6 +142,12 @@ def get_signature_params(data):
ptr += 2
s = data[ptr:ptr + s_length]

# Left-zero-pad 'r' and 's' values that are shorter than required by RFC 8032
# (5.1.6.), to make up for omitted leading zeros in RFC 4880 (3.2.) MPIs.
# This is especially important for 's', which is little-endian.
r = r.rjust(ED25519_SIG_LENGTH // 2, b"\x00")
s = s.rjust(ED25519_SIG_LENGTH // 2, b"\x00")

return r + s


Expand Down
Binary file added tests/gpg_keyrings/eddsa/short.sig
Binary file not shown.
21 changes: 21 additions & 0 deletions tests/test_gpg.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
from securesystemslib.gpg.rsa import create_pubkey as rsa_create_pubkey
from securesystemslib.gpg.dsa import create_pubkey as dsa_create_pubkey
from securesystemslib.gpg.eddsa import create_pubkey as eddsa_create_pubkey
from securesystemslib.gpg.eddsa import ED25519_SIG_LENGTH
from securesystemslib.gpg.common import (parse_pubkey_payload,
parse_pubkey_bundle, get_pubkey_bundle, _assign_certified_key_info,
_get_verified_subkeys, parse_signature_packet)
Expand Down Expand Up @@ -778,5 +779,25 @@ def test_gpg_sign_and_verify_object_with_specific_key(self):
self.assertFalse(verify_signature(signature, key_data, wrong_data))


def test_verify_short_signature(self):
"""Correctly verify a special-crafted short signature. """

test_data = b"hello"
signature_path = os.path.join(self.gnupg_home, "short.sig")

# Read special-crafted raw gpg signature that is one byte too short
with open(signature_path, "rb") as f:
signature_data = f.read()

# Check that the signature is padded upon parsing
# NOTE: The returned signature is a hex string and thus twice as long
signature = parse_signature_packet(signature_data)
self.assertTrue(len(signature["signature"]) == (ED25519_SIG_LENGTH * 2))

# Check that the signature can be successfully verified
key = export_pubkey(self.default_keyid, homedir=self.gnupg_home)
self.assertTrue(verify_signature(signature, key, test_data))


if __name__ == "__main__":
unittest.main()

0 comments on commit 6895306

Please sign in to comment.