Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pynitrokey for 
openSUSE:Factory checked in at 2024-07-16 22:04:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pynitrokey (Old)
 and      /work/SRC/openSUSE:Factory/.python-pynitrokey.new.17339 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pynitrokey"

Tue Jul 16 22:04:14 2024 rev:10 rq:1187698 version:0.4.48

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pynitrokey/python-pynitrokey.changes      
2024-04-21 20:28:26.048459901 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-pynitrokey.new.17339/python-pynitrokey.changes
   2024-07-16 22:04:15.345878909 +0200
@@ -1,0 +2,10 @@
+Sat Jul 13 12:07:09 UTC 2024 - Johannes Kastl 
<opensuse_buildserv...@ojkastl.de>
+
+- update to 0.4.48:
+  * nethsm: Improve base64 handling and add key import from PEM by
+    @robin-nitrokey in #539
+  * fido2: Add get-info subcommand by @robin-nitrokey in #545
+  * nk3/update: add pre_bootloader_hint for update process by
+    @daringer in #546
+
+-------------------------------------------------------------------

Old:
----
  pynitrokey-0.4.47.tar.gz

New:
----
  pynitrokey-0.4.48.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pynitrokey.spec ++++++
--- /var/tmp/diff_new_pack.dGdZs3/_old  2024-07-16 22:04:16.105906647 +0200
+++ /var/tmp/diff_new_pack.dGdZs3/_new  2024-07-16 22:04:16.109906793 +0200
@@ -23,7 +23,7 @@
 %endif
 
 Name:           python-pynitrokey
-Version:        0.4.47
+Version:        0.4.48
 Release:        0
 Summary:        Python Library for Nitrokey devices
 License:        Apache-2.0 OR MIT
@@ -46,7 +46,7 @@
 BuildRequires:  %{python_module frozendict >= 2.3.4}
 # "fido2 >=1.1.0,<2"
 BuildRequires:  %{python_module fido2 >= 1.1.0 with %python-fido2 < 2}
-BuildRequires:  %{python_module nethsm >= 1.0.0 with %python-nethsm < 2}
+BuildRequires:  %{python_module nethsm >= 1.1.0 with %python-nethsm < 2}
 BuildRequires:  %{python_module nkdfu}
 #"python-dateutil ~= 2.7.0"
 BuildRequires:  %{python_module python-dateutil >= 2.7.0}
@@ -86,7 +86,7 @@
 Requires:       python-typing_extensions >= 4.3.0
 Requires:       python-urllib3 >= 1.26.7
 Requires:       (python-fido2 >= 1.1.0 with python-fido2 < 2)
-Requires:       (python-nethsm >= 0.5.0 with python-nethsm < 2)
+Requires:       (python-nethsm >= 1.1.0 with python-nethsm < 2)
 Requires:       (python-spsdk >= 2.0 with python-spsdk < 2.2)
 Requires(post): update-alternatives
 Requires(postun): update-alternatives

++++++ pynitrokey-0.4.47.tar.gz -> pynitrokey-0.4.48.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pynitrokey-0.4.47/PKG-INFO 
new/pynitrokey-0.4.48/PKG-INFO
--- old/pynitrokey-0.4.47/PKG-INFO      1970-01-01 01:00:00.000000000 +0100
+++ new/pynitrokey-0.4.48/PKG-INFO      1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pynitrokey
-Version: 0.4.47
+Version: 0.4.48
 Summary: Python Library for Nitrokey devices.
 Author-email: Nitrokey <p...@nitrokey.com>
 Requires-Python: >=3.9
@@ -33,7 +33,7 @@
 Requires-Dist: protobuf >=3.17.3, < 4.0.0
 Requires-Dist: click-aliases
 Requires-Dist: semver
-Requires-Dist: nethsm >= 1.0.0,<2
+Requires-Dist: nethsm >= 1.1.0,<2
 Requires-Dist: black >=22.1.0,<23 ; extra == "dev"
 Requires-Dist: flake8 ; extra == "dev"
 Requires-Dist: flit >=3.2,<4 ; extra == "dev"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pynitrokey-0.4.47/pynitrokey/VERSION 
new/pynitrokey-0.4.48/pynitrokey/VERSION
--- old/pynitrokey-0.4.47/pynitrokey/VERSION    2024-04-17 13:42:18.000000000 
+0200
+++ new/pynitrokey-0.4.48/pynitrokey/VERSION    2024-07-10 11:06:44.000000000 
+0200
@@ -1 +1 @@
-0.4.47
+0.4.48
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pynitrokey-0.4.47/pynitrokey/cli/fido2.py 
new/pynitrokey-0.4.48/pynitrokey/cli/fido2.py
--- old/pynitrokey-0.4.47/pynitrokey/cli/fido2.py       2024-04-17 
13:42:18.000000000 +0200
+++ new/pynitrokey-0.4.48/pynitrokey/cli/fido2.py       2024-07-10 
11:06:44.000000000 +0200
@@ -12,6 +12,7 @@
 import platform
 import struct
 import sys
+from dataclasses import fields
 from time import sleep, time
 from typing import List, Literal, Optional
 
@@ -25,10 +26,11 @@
 from fido2.client import ClientError as Fido2ClientError
 from fido2.ctap import CtapError
 from fido2.ctap1 import ApduError
-from fido2.ctap2.base import Ctap2
+from fido2.ctap2.base import Ctap2, Info
 from fido2.ctap2.credman import CredentialManagement
 from fido2.ctap2.pin import ClientPin, PinProtocol
 from fido2.hid import CtapHidDevice
+from fido2.webauthn import Aaguid
 
 import pynitrokey
 import pynitrokey.fido2 as nkfido2
@@ -206,6 +208,35 @@
     "--serial",
     help="Serial number of Nitrokey to use. Prefix with 'device=' to provide 
device file, e.g. 'device=/dev/hidraw5'.",
 )
+def get_info(serial: Optional[str]) -> None:
+    """Execute the CTAP2 GET_INFO command and print the response."""
+    p = nkfido2.find(serial)
+    if p.ctap2 is None:
+        print("CTAP2 not supported")
+        return
+
+    info = p.ctap2.send_cbor(Ctap2.CMD.GET_INFO)
+    for i, field in enumerate(fields(Info)):
+        key = i + 1
+        if key in info:
+            value = info[i + 1]
+
+            if field.name == "aaguid":
+                if isinstance(value, bytes):
+                    try:
+                        value = Aaguid(value)
+                    except:
+                        value = value.hex()
+
+            print(f"{field.name}: {value}")
+
+
+@click.command()
+@click.option(
+    "-s",
+    "--serial",
+    help="Serial number of Nitrokey to use. Prefix with 'device=' to provide 
device file, e.g. 'device=/dev/hidraw5'.",
+)
 @click.option("--pin", help="provide PIN instead of asking the user", 
default=None)
 def list_credentials(serial: str, pin: str) -> None:
     """List all credentials saved on the key as well as the amount of 
remaining slots."""
@@ -850,6 +881,7 @@
 fido2.add_command(reboot)
 fido2.add_command(list)
 
+fido2.add_command(get_info)
 fido2.add_command(list_credentials)
 fido2.add_command(delete_credential)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pynitrokey-0.4.47/pynitrokey/cli/nethsm.py 
new/pynitrokey-0.4.48/pynitrokey/cli/nethsm.py
--- old/pynitrokey-0.4.47/pynitrokey/cli/nethsm.py      2024-04-17 
13:42:18.000000000 +0200
+++ new/pynitrokey-0.4.48/pynitrokey/cli/nethsm.py      2024-07-10 
11:06:44.000000000 +0200
@@ -37,6 +37,10 @@
     return click.Choice([variant.value for variant in enum_cls], 
case_sensitive=False)
 
 
+def base64_input(s: str) -> Base64:
+    return Base64.from_encoded(s, ignore_whitespace=True)
+
+
 API_CERTIFICATE_MIME_TYPE = "application/x-pem-file"
 KEY_CERTIFICATE_MIME_TYPES = [
     "application/x-pem-file",
@@ -688,9 +692,9 @@
         if not public_exponent:
             public_exponent = prompt_str("Public exponent")
         private_key = nethsm_sdk.RsaPrivateKey(
-            prime_p=Base64.from_encoded(prime_p),
-            prime_q=Base64.from_encoded(prime_q),
-            public_exponent=Base64.from_encoded(public_exponent),
+            prime_p=base64_input(prime_p),
+            prime_q=base64_input(prime_q),
+            public_exponent=base64_input(public_exponent),
         )
     else:
         if prime_p:
@@ -703,7 +707,7 @@
             )
         if not data:
             data = prompt_str("Key data")
-        private_key = 
nethsm_sdk.GenericPrivateKey(data=Base64.from_encoded(data))
+        private_key = nethsm_sdk.GenericPrivateKey(data=base64_input(data))
 
     with connect(ctx) as nethsm:
         key_id = nethsm.add_key(
@@ -718,6 +722,56 @@
 
 @nethsm.command()
 @click.option(
+    "-m",
+    "--mechanism",
+    "mechanisms",
+    type=MECHANISM_TYPE,
+    multiple=True,
+    help="The mechanisms for the new key",
+)
+@click.option(
+    "--tags",
+    type=str,
+    multiple=True,
+    help="The tags for the new key",
+)
+@click.option(
+    "-k",
+    "--key-id",
+    help="The ID of the new key",
+)
+@click.argument("filename")
+@click.pass_context
+def import_key(
+    ctx: Context,
+    mechanisms: list[str],
+    tags: list[str],
+    key_id: Optional[str],
+    filename: str,
+) -> None:
+    """Import a key pair from a PEM file into the NetHSM.
+
+    If the key ID is not set, it is generated by the NetHSM.
+
+    This command requires authentication as a user with the Administrator
+    role."""
+    mechanisms = list(mechanisms)
+
+    with open(filename) as f:
+        private_key = f.read()
+
+    with connect(ctx) as nethsm:
+        key_id = nethsm.add_key_pem(
+            key_id=key_id,
+            mechanisms=[nethsm_sdk.KeyMechanism.from_string(m) for m in 
mechanisms],
+            tags=tags,
+            private_key=private_key,
+        )
+        print(f"Key {key_id} added to NetHSM {nethsm.host}")
+
+
+@nethsm.command()
+@click.option(
     "type",
     "-t",
     "--type",
@@ -1543,9 +1597,9 @@
     with connect(ctx) as nethsm:
         encrypted = nethsm.encrypt(
             key_id,
-            Base64.from_encoded(data),
+            base64_input(data),
             nethsm_sdk.EncryptMode.from_string(mode),
-            iv=Base64.from_encoded(iv) if iv else None,
+            iv=base64_input(iv) if iv else None,
         )
         print(f"Encrypted: {encrypted.encrypted.data}")
         print(f"Initialization vector: {encrypted.iv.data}")
@@ -1586,9 +1640,9 @@
     with connect(ctx) as nethsm:
         decrypted = nethsm.decrypt(
             key_id,
-            Base64.from_encoded(data),
+            base64_input(data),
             nethsm_sdk.DecryptMode.from_string(mode),
-            Base64.from_encoded(iv) if iv else None,
+            base64_input(iv) if iv else None,
         )
         print(decrypted.data)
 
@@ -1620,6 +1674,6 @@
     This command requires authentication as a user with the Operator role."""
     with connect(ctx) as nethsm:
         signature = nethsm.sign(
-            key_id, Base64.from_encoded(data), 
nethsm_sdk.SignMode.from_string(mode)
+            key_id, base64_input(data), nethsm_sdk.SignMode.from_string(mode)
         )
         print(signature.data)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pynitrokey-0.4.47/pynitrokey/cli/nk3/update.py 
new/pynitrokey-0.4.48/pynitrokey/cli/nk3/update.py
--- old/pynitrokey-0.4.47/pynitrokey/cli/nk3/update.py  2024-04-17 
13:42:18.000000000 +0200
+++ new/pynitrokey-0.4.48/pynitrokey/cli/nk3/update.py  2024-07-10 
11:06:44.000000000 +0200
@@ -95,6 +95,9 @@
         )
         return Abort()
 
+    def pre_bootloader_hint(self) -> None:
+        pass
+
     def request_bootloader_confirmation(self) -> None:
         local_print("")
         local_print(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pynitrokey-0.4.47/pynitrokey/nk3/updates.py 
new/pynitrokey-0.4.48/pynitrokey/nk3/updates.py
--- old/pynitrokey-0.4.47/pynitrokey/nk3/updates.py     2024-04-17 
13:42:18.000000000 +0200
+++ new/pynitrokey-0.4.48/pynitrokey/nk3/updates.py     2024-07-10 
11:06:44.000000000 +0200
@@ -126,7 +126,11 @@
         pass
 
     @abstractmethod
-    def request_repeated_update(self) -> Exception:
+    def request_repeated_update(self) -> Optional[Exception]:
+        pass
+
+    @abstractmethod
+    def pre_bootloader_hint(self) -> None:
         pass
 
     @abstractmethod
@@ -329,11 +333,14 @@
             # needed for udev to properly handle new device
             time.sleep(1)
 
-            if platform.system() == "Darwin":
+            maybe_exc = self.ui.request_repeated_update()
+            if platform.system() == "Darwin" and maybe_exc is not None:
                 # Currently there is an issue with device enumeration after 
reboot on macOS, see
                 # <https://github.com/Nitrokey/pynitrokey/issues/145>.  To 
avoid this issue, we
                 # cancel the command now and ask the user to run it again.
-                raise self.ui.request_repeated_update()
+                raise maybe_exc
+
+            self.ui.pre_bootloader_hint()
 
             exc = None
             for t in Retries(3):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pynitrokey-0.4.47/pyproject.toml 
new/pynitrokey-0.4.48/pyproject.toml
--- old/pynitrokey-0.4.47/pyproject.toml        2024-04-17 13:42:18.000000000 
+0200
+++ new/pynitrokey-0.4.48/pyproject.toml        2024-07-10 11:06:44.000000000 
+0200
@@ -40,7 +40,7 @@
   "protobuf >=3.17.3, < 4.0.0",
   "click-aliases",
   "semver",
-  "nethsm >= 1.0.0,<2",
+  "nethsm >= 1.1.0,<2",
 ]
 dynamic = ["version", "description"]
 

Reply via email to