-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnanotdf_ecdsa_struct.py
More file actions
126 lines (94 loc) · 3.97 KB
/
nanotdf_ecdsa_struct.py
File metadata and controls
126 lines (94 loc) · 3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"""NanoTDF ECDSA Signature Structure."""
from dataclasses import dataclass, field
class IncorrectNanoTDFECDSASignatureSize(Exception):
"""Exception raised when the signature size is incorrect."""
@dataclass
class NanoTDFECDSAStruct:
"""Class to handle ECDSA signature structure for NanoTDF.
This structure represents an ECDSA signature as required by the NanoTDF format.
It consists of r and s values along with their lengths.
"""
r_length: bytearray = field(default_factory=lambda: bytearray(1))
r_value: bytearray = None
s_length: bytearray = field(default_factory=lambda: bytearray(1))
s_value: bytearray = None
@classmethod
def from_bytes(
cls, ecdsa_signature_value: bytes, key_size: int
) -> "NanoTDFECDSAStruct":
"""Create a NanoTDFECDSAStruct from a byte array.
Args:
ecdsa_signature_value: The signature value as bytes
key_size: The size of the key in bytes
Returns:
A new NanoTDFECDSAStruct
Raises:
IncorrectNanoTDFECDSASignatureSize: If the signature buffer size is invalid
"""
if len(ecdsa_signature_value) != (2 * key_size) + 2:
raise IncorrectNanoTDFECDSASignatureSize(
f"Invalid signature buffer size. Expected {(2 * key_size) + 2}, got {len(ecdsa_signature_value)}"
)
struct_obj = cls()
# Copy value of r_length to signature struct
index = 0
struct_obj.r_length[0] = ecdsa_signature_value[index]
# Copy the contents of r_value to signature struct
index += 1
r_len = struct_obj.r_length[0]
struct_obj.r_value = bytearray(key_size)
struct_obj.r_value[:r_len] = ecdsa_signature_value[index : index + r_len]
# Copy value of s_length to signature struct
index += key_size
struct_obj.s_length[0] = ecdsa_signature_value[index]
# Copy value of s_value
index += 1
s_len = struct_obj.s_length[0]
struct_obj.s_value = bytearray(key_size)
struct_obj.s_value[:s_len] = ecdsa_signature_value[index : index + s_len]
return struct_obj
def as_bytes(self) -> bytes:
"""Convert the signature structure to bytes.
Raises ValueError if r_value or s_value is None.
"""
if self.r_value is None or self.s_value is None:
raise ValueError("r_value and s_value must not be None")
total_size = 1 + len(self.r_value) + 1 + len(self.s_value)
signature = bytearray(total_size)
# Copy value of r_length
index = 0
signature[index] = self.r_length[0]
# Copy the contents of r_value
index += 1
signature[index : index + len(self.r_value)] = self.r_value
# Copy value of s_length
index += len(self.r_value)
signature[index] = self.s_length[0]
# Copy value of s_value
index += 1
signature[index : index + len(self.s_value)] = self.s_value
return bytes(signature)
def get_s_value(self) -> bytearray:
"""Get the s value of the signature."""
return self.s_value
def set_s_value(self, s_value: bytearray) -> None:
"""Set the s value of the signature."""
self.s_value = s_value
def get_s_length(self) -> int:
"""Get the length of the s value."""
return self.s_length[0]
def set_s_length(self, s_length: int) -> None:
"""Set the length of the s value."""
self.s_length[0] = s_length
def get_r_value(self) -> bytearray:
"""Get the r value of the signature."""
return self.r_value
def set_r_value(self, r_value: bytearray) -> None:
"""Set the r value of the signature."""
self.r_value = r_value
def get_r_length(self) -> int:
"""Get the length of the r value."""
return self.r_length[0]
def set_r_length(self, r_length: int) -> None:
"""Set the length of the r value."""
self.r_length[0] = r_length