Skip to content

Commit 801addd

Browse files
Add signature base64 encoding in Envelope
As per DSSE spec, Signatures in Envelope should be base64 encoded. While securesystemslib implementation uses hex signatures for signing and verifying them. Best way to achieve this by using base64 encoded signatures externally and not changing any internal representation of signature. This commit adds two helper method that encodes and converts signature into base64 dict and vice versa. Also, testcases are added and updated as well. Signed-off-by: Pradyumna Krishna <[email protected]>
1 parent 5c7ef18 commit 801addd

File tree

4 files changed

+50
-3
lines changed

4 files changed

+50
-3
lines changed

securesystemslib/dsse.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ def from_dict(cls, data: dict) -> "Envelope":
5959
payload_type = data["payloadType"]
6060

6161
signatures = [
62-
Signature.from_dict(signature) for signature in data["signatures"]
62+
Signature.from_base64_dict(signature)
63+
for signature in data["signatures"]
6364
]
6465

6566
return cls(payload, payload_type, signatures)
@@ -71,7 +72,7 @@ def to_dict(self) -> dict:
7172
"payload": b64enc(self.payload),
7273
"payloadType": self.payload_type,
7374
"signatures": [
74-
signature.to_dict() for signature in self.signatures
75+
signature.to_base64_dict() for signature in self.signatures
7576
],
7677
}
7778

securesystemslib/signer/_signature.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import logging
44
from typing import Any, Dict, Optional
55

6+
from securesystemslib._internal.utils import b64dec, b64enc
7+
68
logger = logging.getLogger(__name__)
79

810

@@ -47,6 +49,31 @@ def __eq__(self, other: Any) -> bool:
4749
and self.unrecognized_fields == other.unrecognized_fields
4850
)
4951

52+
@classmethod
53+
def from_base64_dict(cls, signature_dict: Dict) -> "Signature":
54+
"""Creates a Signature object from its JSON/dict representation
55+
containing base64 encoded signature.
56+
57+
Arguments:
58+
signature_dict:
59+
A dict containing a valid keyid and a signature.
60+
Note that the fields in it should be named "keyid" and "sig"
61+
respectively.
62+
63+
Raises:
64+
KeyError: If any of the "keyid" and "sig" fields are missing from
65+
the signature_dict.
66+
67+
Side Effect:
68+
Destroys the metadata dict passed by reference.
69+
70+
Returns:
71+
A "Signature" instance.
72+
"""
73+
74+
signature_dict["sig"] = b64dec(signature_dict["sig"]).decode("utf-8")
75+
return cls.from_dict(signature_dict)
76+
5077
@classmethod
5178
def from_dict(cls, signature_dict: Dict) -> "Signature":
5279
"""Creates a Signature object from its JSON/dict representation.
@@ -81,3 +108,13 @@ def to_dict(self) -> Dict:
81108
"sig": self.signature,
82109
**self.unrecognized_fields,
83110
}
111+
112+
def to_base64_dict(self) -> Dict:
113+
"""Returns the JSON-serializable dictionary representation of self
114+
containing base64 encoded signature."""
115+
116+
return {
117+
"keyid": self.keyid,
118+
"sig": b64enc(self.signature.encode("utf-8")),
119+
**self.unrecognized_fields,
120+
}

tests/test_dsse.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def setUpClass(cls):
2626

2727
cls.signature_dict = {
2828
"keyid": "11fa391a0ed7a447",
29-
"sig": "30460221009342e4566528fcecf6a7a5",
29+
"sig": "MzA0NjAyMjEwMDkzNDJlNDU2NjUyOGZjZWNmNmE3YTU=",
3030
}
3131
cls.envelope_dict = {
3232
"payload": "aGVsbG8gd29ybGQ=",

tests/test_signer.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,15 @@ def test_signature_from_to_dict(self):
453453

454454
self.assertDictEqual(signature_dict, sig_obj.to_dict())
455455

456+
def test_signature_from_to_base64_dict(self):
457+
signature_dict = {
458+
"sig": "MzA0NjAyMjEwMDkzNDJlNDU2NjUyOGZjZWNmNmE3YTVkNTNlYmFjZGIxZGYxNTFlMjQyZjU1Zjg3NzU4ODM0NjljYjAxZGJjNjYwMjIxMDA4NmI0MjZjYzgyNjcwOWFjZmEyYzNmOTIxNDYxMGNiMGE4MzJkYjk0YmJkMjY2ZmQ3YzU5MzlhNDgwNjRhODUx",
459+
"keyid": "11fa391a0ed7a447cbfeb4b2667e286fc248f64d5e6d0eeed2e5e23f97f9f714",
460+
}
461+
sig_obj = Signature.from_base64_dict(copy.copy(signature_dict))
462+
463+
self.assertDictEqual(signature_dict, sig_obj.to_base64_dict())
464+
456465
def test_signature_eq_(self):
457466
signature_dict = {
458467
"sig": "30460221009342e4566528fcecf6a7a5d53ebacdb1df151e242f55f8775883469cb01dbc6602210086b426cc826709acfa2c3f9214610cb0a832db94bbd266fd7c5939a48064a851",

0 commit comments

Comments
 (0)