Skip to content

Commit 09a3351

Browse files
committed
Merge PR #72
2 parents 1222228 + 0af7ce9 commit 09a3351

File tree

6 files changed

+74
-14
lines changed

6 files changed

+74
-14
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
- name: Install uv
3737
uses: astral-sh/setup-uv@v5
3838
with:
39-
enable-cache: true
39+
enable-cache: false
4040

4141
- name: Set up Python
4242
uses: actions/setup-python@v5
@@ -70,7 +70,7 @@ jobs:
7070
- name: Install uv
7171
uses: astral-sh/setup-uv@v5
7272
with:
73-
enable-cache: true
73+
enable-cache: false
7474

7575
- name: Set up Python
7676
uses: actions/setup-python@v5
@@ -112,7 +112,7 @@ jobs:
112112
- name: Install uv
113113
uses: astral-sh/setup-uv@v5
114114
with:
115-
enable-cache: true
115+
enable-cache: false
116116

117117
- name: Set up Python
118118
uses: actions/setup-python@v5
@@ -138,7 +138,7 @@ jobs:
138138
- name: Install uv
139139
uses: astral-sh/setup-uv@v5
140140
with:
141-
enable-cache: true
141+
enable-cache: false
142142

143143
- name: Set up Python
144144
uses: actions/setup-python@v5

NEWS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
* Version 3.1.1 (released 2025-06-24)
2+
** Support for compressing X509 certificates before import.
3+
** Simplified parsing of extensions in attestation certificates.
4+
** Changes relevant to maintainers
5+
*** Switched package manager to uv.
6+
*** Replaced Black, flake8 and bandit with ruff, and added pyright.
7+
18
* Version 3.1.0 (released 2024-09-09)
29
** Support for asymmetric wrap (for FW 2.4+).
310
** Support for wrapping ed25519 keys with seed (for FW 2.4+).

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "yubihsm"
3-
version = "3.1.1.dev0"
3+
version = "3.1.2-dev.0"
44
description = "Library for communication with a YubiHSM 2 over HTTP or USB."
55
authors = [{ name = "Dain Nilsson", email = "<dain@yubico.com>" }]
66
readme = "README.adoc"

tests/device/test_wrap.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -664,30 +664,51 @@ def test_export_using_private_wrapkey(self, session):
664664
private_wrapkey.delete()
665665

666666
def test_get_public_key(self, session):
667-
key = rsa.generate_private_key(
667+
import_key = rsa.generate_private_key(
668+
public_exponent=0x10001, key_size=2048, backend=default_backend()
669+
)
670+
export_key = rsa.generate_private_key(
668671
public_exponent=0x10001, key_size=2048, backend=default_backend()
669672
)
670673

671-
wrapkey = WrapKey.put(
674+
export_wrapkey = PublicWrapKey.put(
675+
session,
676+
0,
677+
"Test Get Public Key (PublicWrapKey)",
678+
1,
679+
CAPABILITY.EXPORT_WRAPPED,
680+
CAPABILITY.EXPORTABLE_UNDER_WRAP,
681+
export_key.public_key(),
682+
)
683+
import_wrapkey = WrapKey.put(
672684
session,
673685
0,
674-
"Test Get Public Key",
686+
"Test Get Public Key (WrapKey)",
675687
1,
676688
CAPABILITY.EXPORT_WRAPPED,
677689
ALGORITHM.RSA_2048,
678690
CAPABILITY.NONE,
679-
key,
691+
import_key,
680692
)
681693

682-
pub = wrapkey.get_public_key()
683-
assert pub.public_bytes(
694+
import_pub = import_wrapkey.get_public_key()
695+
export_pub = export_wrapkey.get_public_key()
696+
assert import_pub.public_bytes(
684697
encoding=serialization.Encoding.PEM,
685698
format=serialization.PublicFormat.SubjectPublicKeyInfo,
686-
) == key.public_key().public_bytes(
699+
) == import_key.public_key().public_bytes(
687700
encoding=serialization.Encoding.PEM,
688701
format=serialization.PublicFormat.SubjectPublicKeyInfo,
689702
)
690-
wrapkey.delete()
703+
assert export_pub.public_bytes(
704+
encoding=serialization.Encoding.PEM,
705+
format=serialization.PublicFormat.SubjectPublicKeyInfo,
706+
) == export_key.public_key().public_bytes(
707+
encoding=serialization.Encoding.PEM,
708+
format=serialization.PublicFormat.SubjectPublicKeyInfo,
709+
)
710+
import_wrapkey.delete()
711+
export_wrapkey.delete()
691712

692713
def test_export_ed25519(self, session):
693714
wrapkey = WrapKey.put(

yubihsm/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@
2727
from .core import YubiHsm # noqa F401
2828

2929

30-
__version__ = "3.1.1.dev0"
30+
__version__ = "3.1.2-dev.0"

yubihsm/objects.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ def _get_int(c: x509.Certificate, oid: int) -> int:
135135

136136
@dataclass
137137
class AttestationExtensions:
138+
"""Base attestation extensions.
139+
140+
:ivar firmware_version: YubiHSM firmware version.
141+
:ivar serial: YubiHSM serial number.
142+
"""
143+
138144
firmware_version: Version
139145
serial: int
140146

@@ -157,6 +163,11 @@ def parse(
157163

158164
@dataclass
159165
class DeviceAttestationExtensions(AttestationExtensions):
166+
"""Device attestation extensions. Available on YubiHSM FIPS only.
167+
168+
:ivar fips_certificate: The FIPS certificate.
169+
"""
170+
160171
fips_certificate: Optional[int]
161172

162173
@classmethod
@@ -174,6 +185,17 @@ def parse(cls, certificate: x509.Certificate, *args):
174185

175186
@dataclass
176187
class KeyAttestationExtensions(AttestationExtensions):
188+
"""Key attestation extensions.
189+
190+
:ivar origin: The origin of the key.
191+
:ivar domains: The set of domains assigned to the key object.
192+
:ivar capabilities: The set of capabilities assigned to the key object.
193+
:ivar object_id: The ID of the key object.
194+
:ivar label: The label of the key object.
195+
:ivar fips_approved: (available on YubiHSM FIPS >= 2.4.1 only) True if
196+
the key attestation was generated in FIPS-approved mode.
197+
"""
198+
177199
origin: ORIGIN
178200
domains: int
179201
capabilities: CAPABILITY
@@ -1250,6 +1272,16 @@ def put(
12501272

12511273
return cls._from_command(session, COMMAND.PUT_PUBLIC_WRAP_KEY, msg)
12521274

1275+
def get_public_key(self) -> rsa.RSAPublicKey:
1276+
"""Get the public wrapkey."""
1277+
msg = struct.pack("!HB", self.id, self.object_type)
1278+
ret = self.session.send_secure_cmd(COMMAND.GET_PUBLIC_KEY, msg)
1279+
raw_key = ret[1:]
1280+
num = int.from_bytes(raw_key, "big")
1281+
return rsa.RSAPublicNumbers(e=RSA_PUBLIC_EXPONENT, n=num).public_key(
1282+
backend=default_backend()
1283+
)
1284+
12531285
def _rsa_wrap_cmd_data(
12541286
self,
12551287
obj: YhsmObject,

0 commit comments

Comments
 (0)