Skip to content

Commit

Permalink
SSlibKey: remove SSlibKey.from_pem
Browse files Browse the repository at this point in the history
The more flexible SSLibKey.from_crypto can be used instead.

The additional call to pyca/crypto's "from pem" method can
easily be done in application code.

This commit updates tests and docs to use from_crypto instead.

Signed-off-by: Lukas Puehringer <[email protected]>
  • Loading branch information
lukpueh committed Nov 23, 2023
1 parent a887a29 commit fc4b070
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 59 deletions.
6 changes: 5 additions & 1 deletion docs/CRYPTO_SIGNER.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,17 @@ os.environ.update({
```python
import os
from securesystemslib.signer import SSlibKey, Signer, CryptoSigner, SIGNER_FOR_URI_SCHEME
from cryptography.hazmat.primitives.serialization import load_pem_public_key


# NOTE: Registration becomes obsolete once CryptoSigner is the default file signer
SIGNER_FOR_URI_SCHEME.update({CryptoSigner.FILE_URI_SCHEME: CryptoSigner})

# Read signer details
uri = os.environ["SIGNER_URI"]
public_key = SSlibKey.from_pem(os.environ["SIGNER_PUBLIC"].encode())
public_key = SSlibKey.from_crypto(
load_pem_public_key(os.environ["SIGNER_PUBLIC"].encode())
)
secrets_handler = lambda sec: os.environ["SIGNER_SECRET"]

# Load and sign
Expand Down
36 changes: 0 additions & 36 deletions securesystemslib/signer/_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,42 +324,6 @@ def from_crypto(

return SSlibKey(keyid, keytype, scheme, keyval)

@classmethod
def from_pem(
cls,
pem: bytes,
scheme: Optional[str] = None,
keyid: Optional[str] = None,
) -> "SSlibKey":
"""Load SSlibKey from PEM.
NOTE: pyca/cryptography is used to decode the PEM payload. The expected
(and tested) format is subjectPublicKeyInfo (RFC 5280). Other formats
may but are not guaranteed to work.
Args:
pem: Public key PEM data.
scheme: SSlibKey signing scheme. Defaults are "rsassa-pss-sha256",
"ecdsa-sha2-nistp256", and "ed25519" according to the keytype
keyid: Key identifier. If not passed, a default keyid is computed.
Raises:
UnsupportedLibraryError: pyca/cryptography not installed
ValueError: Key type not supported
ValueError, \
cryptography.exceptions.UnsupportedAlgorithm:
pyca/cryptography deserialization failed
Returns:
SSlibKey
"""
if CRYPTO_IMPORT_ERROR:
raise UnsupportedLibraryError(CRYPTO_IMPORT_ERROR)

public_key = load_pem_public_key(pem)
return cls.from_crypto(public_key, keyid, scheme)

@staticmethod
def _get_hash_algorithm(name: str) -> "HashAlgorithm":
"""Helper to return hash algorithm for name."""
Expand Down
5 changes: 0 additions & 5 deletions tests/check_public_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,11 +313,6 @@ def test_sslib_key_from_crypto(self):
with self.assertRaises(UnsupportedLibraryError):
SSlibKey.from_crypto("mock pyca/crypto pubkey") # type: ignore

def test_sslib_key_from_pem(self):
"""Assert raise UnsupportedLibraryError on SSlibKey.from_pem()."""
with self.assertRaises(UnsupportedLibraryError):
SSlibKey.from_pem(b"fail")

def test_crypto_signer_from_priv_key_uri(self):
"""Assert raise UnsupportedLibraryError on 'from_priv_key_uri'."""

Expand Down
23 changes: 15 additions & 8 deletions tests/test_migrate_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from pathlib import Path
from unittest.mock import patch

from cryptography.hazmat.primitives.serialization import load_pem_public_key

from docs.migrate_key import main as migrate_key_cli
from securesystemslib.exceptions import UnverifiedSignatureError
from securesystemslib.interface import (
Expand Down Expand Up @@ -53,11 +55,16 @@ def setUpClass(cls):
def tearDownClass(cls):
shutil.rmtree(cls.new_keys)

def _from_file(self, algo):
with open(self.new_keys / f"{algo}_public", "rb") as f:
pem = f.read()
return load_pem_public_key(pem)

def test_migrated_keys(self):
for algo in ["rsa", "ecdsa", "ed25519"]:
# Load public key
with open(self.new_keys / f"{algo}_public", "rb") as f:
public_key = SSlibKey.from_pem(f.read())
crypto_key = self._from_file(algo)
public_key = SSlibKey.from_crypto(crypto_key)

# Load unencrypted private key
path = self.new_keys / f"{algo}_private_unencrypted"
Expand Down Expand Up @@ -109,12 +116,12 @@ def test_old_signature_verifies_with_new_key(self):
signer = SSlibSigner(private_key)

# Load new public key
with open(self.new_keys / f"{algo}_public", "rb") as f:
# NOTE: The new auto-keyid would differ from the old keyid.
# Set it explicitly, to verify signatures with old keyid below
public_key = SSlibKey.from_pem(
f.read(), keyid=private_key["keyid"]
)
crypto_key = self._from_file(algo)
# NOTE: The new auto-keyid would differ from the old keyid.
# Set it explicitly, to verify signatures with old keyid below
public_key = SSlibKey.from_crypto(
crypto_key, keyid=private_key["keyid"]
)

# Sign and test signature
sig = signer.sign(b"data")
Expand Down
23 changes: 14 additions & 9 deletions tests/test_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
from pathlib import Path
from typing import Any, Dict, Optional

from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.primitives.serialization import (
load_pem_private_key,
load_pem_public_key,
)

import securesystemslib.keys as KEYS
from securesystemslib.exceptions import (
Expand Down Expand Up @@ -289,8 +292,8 @@ def to_dict(self) -> Dict[str, Any]:
class TestSSlibKey(unittest.TestCase):
"""SSlibKey tests."""

def test_from_pem(self):
"""Test load PEM/subjectPublicKeyInfo for each SSlibKey keytype"""
def test_from_crypto(self):
"""Test load pyca/cryptography public key for each SSlibKey keytype"""
test_data = [
(
"rsa",
Expand All @@ -312,19 +315,21 @@ def test_from_pem(self):
def _from_file(path):
with open(path, "rb") as f:
pem = f.read()
return pem

crypto_key = load_pem_public_key(pem)
return crypto_key

for keytype, default_scheme, default_keyid in test_data:
pem = _from_file(PEMS_DIR / f"{keytype}_public.pem")
key = SSlibKey.from_pem(pem)
crypto_key = _from_file(PEMS_DIR / f"{keytype}_public.pem")
key = SSlibKey.from_crypto(crypto_key)
self.assertEqual(key.keytype, keytype)
self.assertEqual(key.scheme, default_scheme)
self.assertEqual(key.keyid, default_keyid)

# Test with non-default scheme/keyid
pem = _from_file(PEMS_DIR / "rsa_public.pem")
key = SSlibKey.from_pem(
pem,
crypto_key = _from_file(PEMS_DIR / "rsa_public.pem")
key = SSlibKey.from_crypto(
crypto_key,
scheme="rsa-pkcs1v15-sha224",
keyid="abcdef",
)
Expand Down

0 comments on commit fc4b070

Please sign in to comment.