Skip to content

Commit

Permalink
Refactor models.gpg api
Browse files Browse the repository at this point in the history
models.gpg apis made non-public and moved to models._signer
All ``_LegacyGPGSignature``, ``_LegacyGPGSigner``, and
``_LegacyGPGKey`` are renamed ``GPGSignature``, ``GPGSigner`` and
``GPGKey`` respectively.

Tests are updated accordingly.

Signed-off-by: Pradyumna Krishna <[email protected]>
  • Loading branch information
PradyumnaKrishna committed Feb 4, 2023
1 parent da9cd0d commit 71d7b15
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 41 deletions.
41 changes: 19 additions & 22 deletions in_toto/models/gpg.py → in_toto/models/_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

"""
<Program Name>
gpg.py
_signer.py
<Author>
Pradyumna Krishna <[email protected]>
Expand All @@ -28,7 +28,7 @@
from securesystemslib.signer import Key, Signature, Signer, SecretsHandler


class _LegacyGPGSignature(Signature):
class GPGSignature(Signature):
"""A container class containing information about a gpg signature.
Besides the signature, it also contains other meta information
needed to uniquely identify the key used to generate the signature.
Expand All @@ -49,8 +49,8 @@ def __init__(
self.other_headers = other_headers

@classmethod
def from_dict(cls, signature_dict: Dict) -> "_LegacyGPGSignature":
"""Creates a ``_LegacyGPGSignature`` object from its JSON/dict
def from_dict(cls, signature_dict: Dict) -> "GPGSignature":
"""Creates a ``GPGSignature`` object from its JSON/dict
representation.
Arguments:
Expand All @@ -60,7 +60,7 @@ def from_dict(cls, signature_dict: Dict) -> "_LegacyGPGSignature":
KeyError: If any of the "keyid", "sig" or "other_headers" fields
are missing from the signature_dict.
Returns:
``_LegacyGPGSignature`` instance.
``GPGSignature`` instance.
"""

return cls(
Expand All @@ -78,7 +78,7 @@ def to_dict(self) -> Dict:
}


class _LegacyGPGSigner(Signer):
class GPGSigner(Signer):
"""A in-toto gpg implementation of the ``Signer`` interface.
Provides a sign method to generate a cryptographic signature with gpg, using
an RSA, DSA or EdDSA private key identified by the keyid on the instance.
Expand All @@ -104,21 +104,18 @@ def from_priv_key_uri(
priv_key_uri: str,
public_key: Key,
secrets_handler: Optional[SecretsHandler] = None
) -> "_LegacyGPGSigner":
) -> "GPGSigner":

raise NotImplementedError(
"Incompatible with private key URIs") # pragma: no cover


def sign(self, payload: bytes) -> _LegacyGPGSignature:
"""Signs a given payload by the key assigned to the ``_LegacyGPGSigner``
def sign(self, payload: bytes) -> GPGSignature:
"""Signs a given payload by the key assigned to the ``GPGSigner``
instance. Calls the gpg command line utility to sign the passed content
with the key identified by the passed keyid from the gpg keyring at the
passed homedir.
The executed base command is defined in
securesystemslib.gpg.constants.GPG_SIGN_COMMAND.
Arguments:
payload: The bytes to be signed.
Raises:
Expand All @@ -134,15 +131,15 @@ def sign(self, payload: bytes) -> _LegacyGPGSignature:
securesystemslib.gpg.exceptions.KeyNotFoundError: the used gpg version is
not fully supported and no public key can be found for short keyid.
Returns:
Returns a ``_LegacyGPGSignature`` class instance.
Returns a ``GPGSignature`` class instance.
"""

sig_dict = gpg.create_signature(payload, self.keyid, self.homedir)
return _LegacyGPGSignature(**sig_dict)
return GPGSignature(**sig_dict)


@dataclass
class _LegacyGPGKey(Key):
class GPGKey(Key):
"""A container class representing public key portion of a GPG key.
Provides a verify method to verify a cryptographic signature with a
gpg-style rsa, dsa or ecdsa public key on the instance.
Expand All @@ -168,11 +165,11 @@ class _LegacyGPGKey(Key):
keyid: str
creation_time: Optional[int] = None
validity_period: Optional[int] = None
subkeys: Optional[Dict[str, "_LegacyGPGKey"]] = None
subkeys: Optional[Dict[str, "GPGKey"]] = None

@classmethod
def from_dict(cls, keyid: str, key_dict: Dict[str, Any]):
"""Creates ``_LegacyGPGKey`` object from its json/dict representation.
"""Creates ``GPGKey`` object from its json/dict representation.
Raises:
KeyError, TypeError: Invalid arguments.
"""
Expand All @@ -181,7 +178,7 @@ def from_dict(cls, keyid: str, key_dict: Dict[str, Any]):
gpg_subkeys = None
if subkeys_dict:
gpg_subkeys = {
_keyid: _LegacyGPGKey.from_dict(_keyid, subkey_dict)
_keyid: GPGKey.from_dict(_keyid, subkey_dict)
for (_keyid, subkey_dict) in subkeys_dict.items()
}

Expand Down Expand Up @@ -229,21 +226,21 @@ def to_dict(self):

@classmethod
def from_keyring(cls, keyid, homedir=None):
"""Creates ``_LegacyGPGKey`` object from GnuPG Keyring."""
"""Creates ``GPGKey`` object from GnuPG Keyring."""

pubkey_dict = gpg.export_pubkey(keyid, homedir)
return cls.from_dict(keyid, pubkey_dict)

def verify_signature(
self,
signature: _LegacyGPGSignature,
signature: GPGSignature,
data: bytes
) -> None:
"""Verifies a given payload by the key assigned to the _LegacyGPGKey
"""Verifies a given payload by the key assigned to the GPGKey
instance.
Arguments:
signature: A ``_LegacyGPGSignature`` class instance.
signature: A ``GPGSignature`` class instance.
data: The bytes to be verified.
"""

Expand Down
38 changes: 19 additions & 19 deletions tests/models/test_gpg.py → tests/models/test_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

"""
<Program Name>
test_gpg.py
test_signer.py
<Author>
Pradyumna Krishna <[email protected]>
Expand All @@ -17,7 +17,7 @@
See LICENSE for licensing information.
<Purpose>
Test _LegacyGPGKey, _LegacyGPGSigner and _LegacyGPGSignature class methods.
Test GPGKey, GPGSigner and GPGSignature class methods.
"""

import unittest
Expand All @@ -27,8 +27,8 @@
from securesystemslib.exceptions import (
UnverifiedSignatureError, VerificationError)

from in_toto.models.gpg import (_LegacyGPGKey, _LegacyGPGSignature,
_LegacyGPGSigner)
from in_toto.models._signer import (GPGKey, GPGSignature,
GPGSigner)

from tests.common import GPGKeysMixin, TmpDirMixin

Expand Down Expand Up @@ -59,18 +59,18 @@ def test_gpg_sign_and_verify_object_with_default_key(self):
"""Create and verify a signature using the default key on the keyring."""

# Create a signature.
signer = _LegacyGPGSigner(homedir=self.gnupg_home)
signer = GPGSigner(homedir=self.gnupg_home)
signature = signer.sign(self.test_data)

# Generate Key from gnupg keyring.
key = _LegacyGPGKey.from_keyring(self.default_keyid, self.gnupg_home)
key = GPGKey.from_keyring(self.default_keyid, self.gnupg_home)

key.verify_signature(signature, self.test_data)
with self.assertRaises(UnverifiedSignatureError):
key.verify_signature(signature, self.wrong_data)

# Generate Key from dict.
key = _LegacyGPGKey.from_legacy_dict(self.default_key_dict)
key = GPGKey.from_legacy_dict(self.default_key_dict)

key.verify_signature(signature, self.test_data)
with self.assertRaises(UnverifiedSignatureError):
Expand All @@ -80,19 +80,19 @@ def test_gpg_sign_and_verify_object(self):
"""Create and verify a signature using the specific key on the keyring."""

# Create a signature.
signer = _LegacyGPGSigner(self.signing_subkey_keyid, self.gnupg_home)
signer = GPGSigner(self.signing_subkey_keyid, self.gnupg_home)
signature = signer.sign(self.test_data)

# Generate Key from gnupg keyring.
key = _LegacyGPGKey.from_keyring(self.signing_subkey_keyid, self.gnupg_home)
key = GPGKey.from_keyring(self.signing_subkey_keyid, self.gnupg_home)

key.verify_signature(signature, self.test_data)
with self.assertRaises(UnverifiedSignatureError):
key.verify_signature(signature, self.wrong_data)

# Generate Key from dict.
key_dict = export_pubkey(self.signing_subkey_keyid, self.gnupg_home)
key = _LegacyGPGKey.from_dict(key_dict["keyid"], key_dict)
key = GPGKey.from_dict(key_dict["keyid"], key_dict)

key.verify_signature(signature, self.test_data)
with self.assertRaises(UnverifiedSignatureError):
Expand All @@ -102,15 +102,15 @@ def test_verify_using_expired_keyid(self):
"""Creates and verifies a signature using expired key on the keyring."""

# Create a signature.
signer = _LegacyGPGSigner(self.signing_subkey_keyid, self.gnupg_home)
signer = GPGSigner(self.signing_subkey_keyid, self.gnupg_home)
signature = signer.sign(self.test_data)

# Verify signature using expired key.
key = _LegacyGPGKey.from_keyring(self.expired_keyid, self.gnupg_home)
key = GPGKey.from_keyring(self.expired_keyid, self.gnupg_home)
with self.assertRaises(VerificationError):
key.verify_signature(signature, self.test_data)

def test_gpg_signer_serialization(self):
def test_gpg_signature_serialization(self):
"""Tests from_dict and to_dict methods of GPGSignature."""

sig_dict = {
Expand All @@ -119,32 +119,32 @@ def test_gpg_signer_serialization(self):
"other_headers": "d8f8a89b5d71f07b842a",
}

signature = _LegacyGPGSignature.from_dict(sig_dict)
signature = GPGSignature.from_dict(sig_dict)
self.assertEqual(sig_dict, signature.to_dict())

def test_gpg_key_serialization(self):
"""Test to check serialization methods of GPGKey."""

# Test loading and dumping of GPGKey.
key = _LegacyGPGKey.from_legacy_dict(self.default_key_dict)
key = GPGKey.from_legacy_dict(self.default_key_dict)
self.assertEqual(key.to_dict(), self.default_key_dict)

# Test loading and dumping of GPGKey from keyring.
key = _LegacyGPGKey.from_keyring(self.default_keyid, self.gnupg_home)
key = GPGKey.from_keyring(self.default_keyid, self.gnupg_home)
self.assertEqual(key.to_dict(), self.default_key_dict)

def test_gpg_key_equality(self):
"""Test to check equality between two GPGKey."""

# Generate two GPGkey.
key1 = _LegacyGPGKey.from_legacy_dict(self.default_key_dict)
key2 = _LegacyGPGKey.from_legacy_dict(self.default_key_dict)
key1 = GPGKey.from_legacy_dict(self.default_key_dict)
key2 = GPGKey.from_legacy_dict(self.default_key_dict)

self.assertNotEqual(self.default_key_dict, key1)
self.assertEqual(key2, key1)

# Assert equality of key created from dict of first GPGKey.
key2 = _LegacyGPGKey.from_legacy_dict(key1.to_dict())
key2 = GPGKey.from_legacy_dict(key1.to_dict())
self.assertEqual(key2, key1)

# Assert Inequalities.
Expand Down

0 comments on commit 71d7b15

Please sign in to comment.