keylet 0.4.0__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {keylet-0.4.0 → keylet-0.6.0}/PKG-INFO +3 -3
- {keylet-0.4.0 → keylet-0.6.0}/README.md +2 -2
- {keylet-0.4.0 → keylet-0.6.0}/pyproject.toml +2 -1
- {keylet-0.4.0 → keylet-0.6.0}/src/keylet/tkey.py +1 -4
- {keylet-0.4.0 → keylet-0.6.0}/src/keylet/tkey_sign.py +15 -15
- {keylet-0.4.0 → keylet-0.6.0}/LICENSE +0 -0
- {keylet-0.4.0 → keylet-0.6.0}/src/keylet/__init__.py +0 -0
- {keylet-0.4.0 → keylet-0.6.0}/src/keylet/_serial_hack.py +0 -0
- {keylet-0.4.0 → keylet-0.6.0}/src/keylet/bin/__init__.py +0 -0
- {keylet-0.4.0 → keylet-0.6.0}/src/keylet/bin/cli.py +0 -0
- {keylet-0.4.0 → keylet-0.6.0}/src/keylet/py.typed +0 -0
- {keylet-0.4.0 → keylet-0.6.0}/src/keylet/resources/__init__.py +0 -0
- {keylet-0.4.0 → keylet-0.6.0}/src/keylet/resources/ed25519signer_v3.bin +0 -0
- {keylet-0.4.0 → keylet-0.6.0}/src/keylet/resources/pqsigner_v3.bin +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: keylet
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Client application for Tillitis TKey hardware ML-DSA/Ed25519 signer
|
|
5
5
|
Keywords: ML-DSA,TKey,Tillitis,PQC,sign,signer
|
|
6
6
|
Author: Jussi Kukkonen
|
|
@@ -54,7 +54,7 @@ $ keylet verify --pubkey pub.key README.md
|
|
|
54
54
|
# When using keylet long-term, remember to specify device app digest (keylet default
|
|
55
55
|
# app version may change, but you will need a specific application to keep using the
|
|
56
56
|
# same key)
|
|
57
|
-
$ keylet --passphrase hunter2 --digest
|
|
57
|
+
$ keylet --passphrase hunter2 --digest 2cd8741 sign README.md
|
|
58
58
|
|
|
59
59
|
```
|
|
60
60
|
|
|
@@ -86,7 +86,7 @@ with TKeySign(app=app, secret="hunter2") as signer:
|
|
|
86
86
|
signature = signer.sign(b"my payload")
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
See
|
|
89
|
+
See API Reference in [documentation](https://jku.github.io/keylet/) for more details.
|
|
90
90
|
|
|
91
91
|
## Development
|
|
92
92
|
|
|
@@ -36,7 +36,7 @@ $ keylet verify --pubkey pub.key README.md
|
|
|
36
36
|
# When using keylet long-term, remember to specify device app digest (keylet default
|
|
37
37
|
# app version may change, but you will need a specific application to keep using the
|
|
38
38
|
# same key)
|
|
39
|
-
$ keylet --passphrase hunter2 --digest
|
|
39
|
+
$ keylet --passphrase hunter2 --digest 2cd8741 sign README.md
|
|
40
40
|
|
|
41
41
|
```
|
|
42
42
|
|
|
@@ -68,7 +68,7 @@ with TKeySign(app=app, secret="hunter2") as signer:
|
|
|
68
68
|
signature = signer.sign(b"my payload")
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
See
|
|
71
|
+
See API Reference in [documentation](https://jku.github.io/keylet/) for more details.
|
|
72
72
|
|
|
73
73
|
## Development
|
|
74
74
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "keylet"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.6.0"
|
|
4
4
|
description = "Client application for Tillitis TKey hardware ML-DSA/Ed25519 signer"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -61,6 +61,7 @@ ignore = [
|
|
|
61
61
|
"tests/**" = [
|
|
62
62
|
"S101", # assert is ok in tests
|
|
63
63
|
"S105", # hardcoded password is ok in tests
|
|
64
|
+
"SLF001", # Private member access is ok in tests
|
|
64
65
|
"ARG002", # Unused method argument (common with mocks)
|
|
65
66
|
]
|
|
66
67
|
|
|
@@ -150,10 +150,7 @@ class TKey:
|
|
|
150
150
|
* [Framing protocol](https://dev.tillitis.se/protocol/#framing-protocol)
|
|
151
151
|
"""
|
|
152
152
|
|
|
153
|
-
def __init__(
|
|
154
|
-
self,
|
|
155
|
-
device: str | None,
|
|
156
|
-
) -> None:
|
|
153
|
+
def __init__(self, device: str | None) -> None:
|
|
157
154
|
"""Initialize serial connection to TKey device.
|
|
158
155
|
|
|
159
156
|
Args:
|
|
@@ -15,17 +15,18 @@ from keylet.tkey import Cmd, LenIdx, Rsp, TKey, TKeyError, TKeyUnexpectedAppErro
|
|
|
15
15
|
logger = logging.getLogger(__name__)
|
|
16
16
|
|
|
17
17
|
MU_SIZE = (64).to_bytes(4, byteorder="little")
|
|
18
|
-
|
|
18
|
+
MAX_PAYLOAD_SIZE = 4096
|
|
19
19
|
|
|
20
20
|
# Static registry of signer binaries (filename, version)
|
|
21
21
|
# First binary in each list is the default binary.
|
|
22
22
|
_EMBEDDED_MLDSA_BINS: list[tuple[str, int]] = [
|
|
23
23
|
("pqsigner_v3.bin", 3),
|
|
24
24
|
]
|
|
25
|
-
|
|
26
25
|
_EMBEDDED_ED25519_BINS: list[tuple[str, int]] = [
|
|
27
26
|
("ed25519signer_v3.bin", 3),
|
|
28
27
|
]
|
|
28
|
+
_MLDSA_APP_NAME = ("tk1", "pqsn")
|
|
29
|
+
_ED25519_APP_NAME = ("tk1", "sign")
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
@dataclass
|
|
@@ -48,8 +49,8 @@ class SignApp:
|
|
|
48
49
|
|
|
49
50
|
@property
|
|
50
51
|
def digest(self) -> str:
|
|
51
|
-
"""Return the
|
|
52
|
-
return hashlib.
|
|
52
|
+
"""Return the SHA-512 hex digest of the application binary."""
|
|
53
|
+
return hashlib.sha512(self.binary).hexdigest()
|
|
53
54
|
|
|
54
55
|
@classmethod
|
|
55
56
|
def _find_binary(
|
|
@@ -65,7 +66,7 @@ class SignApp:
|
|
|
65
66
|
continue
|
|
66
67
|
|
|
67
68
|
binary = resources_dir.joinpath(filename).read_bytes()
|
|
68
|
-
file_digest = hashlib.
|
|
69
|
+
file_digest = hashlib.sha512(binary).hexdigest()
|
|
69
70
|
|
|
70
71
|
# Filter by digest if requested
|
|
71
72
|
if digest is not None and not file_digest.startswith(digest.lower()):
|
|
@@ -105,7 +106,7 @@ class SignApp:
|
|
|
105
106
|
|
|
106
107
|
Args:
|
|
107
108
|
version: The version of the signer application to load.
|
|
108
|
-
digest: A
|
|
109
|
+
digest: A SHA-512 hex digest (or prefix) of the target binary.
|
|
109
110
|
|
|
110
111
|
Returns:
|
|
111
112
|
An instance of SignApp configured with the loaded binary.
|
|
@@ -116,7 +117,7 @@ class SignApp:
|
|
|
116
117
|
"""
|
|
117
118
|
|
|
118
119
|
binary, version = cls._find_binary(version, digest, _EMBEDDED_MLDSA_BINS)
|
|
119
|
-
return cls(binary, version,
|
|
120
|
+
return cls(binary, version, _MLDSA_APP_NAME, 2420, 1312)
|
|
120
121
|
|
|
121
122
|
@classmethod
|
|
122
123
|
def load_ed25519(
|
|
@@ -132,11 +133,11 @@ class SignApp:
|
|
|
132
133
|
specific key must provide the binary digest.
|
|
133
134
|
|
|
134
135
|
Warning:
|
|
135
|
-
When Ed25519 is used, there is a
|
|
136
|
+
When Ed25519 is used, there is a 4096B size limit to signing payloads.
|
|
136
137
|
|
|
137
138
|
Args:
|
|
138
139
|
version: The version of the signer application to load.
|
|
139
|
-
digest: A
|
|
140
|
+
digest: A SHA-512 hex digest (or prefix) of the target binary.
|
|
140
141
|
|
|
141
142
|
Returns:
|
|
142
143
|
An instance of SignApp configured with the loaded binary.
|
|
@@ -146,7 +147,7 @@ class SignApp:
|
|
|
146
147
|
is ambiguous (matches multiple binaries).
|
|
147
148
|
"""
|
|
148
149
|
binary, version = cls._find_binary(version, digest, _EMBEDDED_ED25519_BINS)
|
|
149
|
-
return cls(binary, version,
|
|
150
|
+
return cls(binary, version, _ED25519_APP_NAME, 64, 32)
|
|
150
151
|
|
|
151
152
|
|
|
152
153
|
class SignRsp:
|
|
@@ -269,7 +270,7 @@ class TKeySign(TKey):
|
|
|
269
270
|
|
|
270
271
|
Args:
|
|
271
272
|
message: The raw bytes of the message/payload to sign. When Ed25519 keys
|
|
272
|
-
are used, there is a max message size of
|
|
273
|
+
are used, there is a max message size of 4096B. This limitation does
|
|
273
274
|
not apply to ML-DSA as FIPS 204 external mu is used.
|
|
274
275
|
pub_key: The public key bytes (only needed for ML-DSA). If not provided,
|
|
275
276
|
key is retrieved from device.
|
|
@@ -282,8 +283,7 @@ class TKeySign(TKey):
|
|
|
282
283
|
TKeyIOError: If writing or reading from the serial port fails.
|
|
283
284
|
TKeyProtocolError: If there is a framing or protocol mismatch.
|
|
284
285
|
"""
|
|
285
|
-
|
|
286
|
-
if self.name in [("tk1", "pqsn"), ("tk1", "pqnt")]:
|
|
286
|
+
if self.name == _MLDSA_APP_NAME:
|
|
287
287
|
# Compute FIPS 204 external mu
|
|
288
288
|
if pub_key is None:
|
|
289
289
|
pub_key = self.get_pubkey()
|
|
@@ -293,8 +293,8 @@ class TKeySign(TKey):
|
|
|
293
293
|
payload = message
|
|
294
294
|
|
|
295
295
|
# Set size
|
|
296
|
-
if len(payload) >
|
|
297
|
-
raise ValueError(f"Payload too large {len(payload)} >
|
|
296
|
+
if len(payload) > MAX_PAYLOAD_SIZE:
|
|
297
|
+
raise ValueError(f"Payload too large {len(payload)} > {MAX_PAYLOAD_SIZE}]")
|
|
298
298
|
self.send(SignCmd.SET_SIZE, len(payload).to_bytes(4, byteorder="little"))
|
|
299
299
|
|
|
300
300
|
# Load data in chunks
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|