1 | ''' |
---|
2 | Ed25519 keys and helpers. |
---|
3 | |
---|
4 | Key Formatting |
---|
5 | -------------- |
---|
6 | |
---|
7 | - in base32, keys are 52 chars long (both signing and verifying keys) |
---|
8 | - in base62, keys is 43 chars long |
---|
9 | - in base64, keys is 43 chars long |
---|
10 | |
---|
11 | We can't use base64 because we want to reserve punctuation and preserve |
---|
12 | cut-and-pasteability. The base62 encoding is shorter than the base32 form, |
---|
13 | but the minor usability improvement is not worth the documentation and |
---|
14 | specification confusion of using a non-standard encoding. So we stick with |
---|
15 | base32. |
---|
16 | ''' |
---|
17 | |
---|
18 | from cryptography.exceptions import ( |
---|
19 | InvalidSignature, |
---|
20 | ) |
---|
21 | from cryptography.hazmat.primitives.asymmetric.ed25519 import ( |
---|
22 | Ed25519PrivateKey, |
---|
23 | Ed25519PublicKey, |
---|
24 | ) |
---|
25 | from cryptography.hazmat.primitives.serialization import ( |
---|
26 | Encoding, |
---|
27 | PrivateFormat, |
---|
28 | NoEncryption, |
---|
29 | PublicFormat, |
---|
30 | ) |
---|
31 | |
---|
32 | from allmydata.crypto.util import remove_prefix |
---|
33 | from allmydata.crypto.error import BadSignature |
---|
34 | |
---|
35 | from allmydata.util.base32 import ( |
---|
36 | a2b, |
---|
37 | b2a, |
---|
38 | ) |
---|
39 | |
---|
40 | PRIVATE_KEY_PREFIX = b'priv-v0-' |
---|
41 | PUBLIC_KEY_PREFIX = b'pub-v0-' |
---|
42 | |
---|
43 | |
---|
44 | def create_signing_keypair(): |
---|
45 | """ |
---|
46 | Creates a new ed25519 keypair. |
---|
47 | |
---|
48 | :returns: 2-tuple of (private_key, public_key) |
---|
49 | """ |
---|
50 | private_key = Ed25519PrivateKey.generate() |
---|
51 | return private_key, private_key.public_key() |
---|
52 | |
---|
53 | |
---|
54 | def verifying_key_from_signing_key(private_key): |
---|
55 | """ |
---|
56 | :returns: the public key associated to the given `private_key` |
---|
57 | """ |
---|
58 | _validate_private_key(private_key) |
---|
59 | return private_key.public_key() |
---|
60 | |
---|
61 | |
---|
62 | def sign_data(private_key, data: bytes) -> bytes: |
---|
63 | """ |
---|
64 | Sign the given data using the given private key |
---|
65 | |
---|
66 | :param private_key: the private part returned from |
---|
67 | `create_signing_keypair` or from |
---|
68 | `signing_keypair_from_string` |
---|
69 | |
---|
70 | :param bytes data: the data to sign |
---|
71 | |
---|
72 | :returns: bytes representing the signature |
---|
73 | """ |
---|
74 | |
---|
75 | _validate_private_key(private_key) |
---|
76 | if not isinstance(data, bytes): |
---|
77 | raise ValueError('data must be bytes') |
---|
78 | return private_key.sign(data) |
---|
79 | |
---|
80 | |
---|
81 | def string_from_signing_key(private_key): |
---|
82 | """ |
---|
83 | Encode a private key to a string of bytes |
---|
84 | |
---|
85 | :param private_key: the private part returned from |
---|
86 | `create_signing_keypair` or from |
---|
87 | `signing_keypair_from_string` |
---|
88 | |
---|
89 | :returns: byte-string representing this key |
---|
90 | """ |
---|
91 | _validate_private_key(private_key) |
---|
92 | raw_key_bytes = private_key.private_bytes( |
---|
93 | Encoding.Raw, |
---|
94 | PrivateFormat.Raw, |
---|
95 | NoEncryption(), |
---|
96 | ) |
---|
97 | return PRIVATE_KEY_PREFIX + b2a(raw_key_bytes) |
---|
98 | |
---|
99 | |
---|
100 | def signing_keypair_from_string(private_key_bytes: bytes): |
---|
101 | """ |
---|
102 | Load a signing keypair from a string of bytes (which includes the |
---|
103 | PRIVATE_KEY_PREFIX) |
---|
104 | |
---|
105 | :returns: a 2-tuple of (private_key, public_key) |
---|
106 | """ |
---|
107 | |
---|
108 | if not isinstance(private_key_bytes, bytes): |
---|
109 | raise ValueError('private_key_bytes must be bytes') |
---|
110 | |
---|
111 | private_key = Ed25519PrivateKey.from_private_bytes( |
---|
112 | a2b(remove_prefix(private_key_bytes, PRIVATE_KEY_PREFIX)) |
---|
113 | ) |
---|
114 | return private_key, private_key.public_key() |
---|
115 | |
---|
116 | |
---|
117 | def verify_signature(public_key, alleged_signature: bytes, data: bytes): |
---|
118 | """ |
---|
119 | :param public_key: a verifying key |
---|
120 | |
---|
121 | :param bytes alleged_signature: the bytes of the alleged signature |
---|
122 | |
---|
123 | :param bytes data: the data which was allegedly signed |
---|
124 | |
---|
125 | :raises: BadSignature if the signature is bad |
---|
126 | :returns: None (or raises an exception). |
---|
127 | """ |
---|
128 | |
---|
129 | if not isinstance(alleged_signature, bytes): |
---|
130 | raise ValueError('alleged_signature must be bytes') |
---|
131 | |
---|
132 | if not isinstance(data, bytes): |
---|
133 | raise ValueError('data must be bytes') |
---|
134 | |
---|
135 | _validate_public_key(public_key) |
---|
136 | try: |
---|
137 | public_key.verify(alleged_signature, data) |
---|
138 | except InvalidSignature: |
---|
139 | raise BadSignature() |
---|
140 | |
---|
141 | |
---|
142 | def verifying_key_from_string(public_key_bytes): |
---|
143 | """ |
---|
144 | Load a verifying key from a string of bytes (which includes the |
---|
145 | PUBLIC_KEY_PREFIX) |
---|
146 | |
---|
147 | :returns: a public_key |
---|
148 | """ |
---|
149 | if not isinstance(public_key_bytes, bytes): |
---|
150 | raise ValueError('public_key_bytes must be bytes') |
---|
151 | |
---|
152 | return Ed25519PublicKey.from_public_bytes( |
---|
153 | a2b(remove_prefix(public_key_bytes, PUBLIC_KEY_PREFIX)) |
---|
154 | ) |
---|
155 | |
---|
156 | |
---|
157 | def string_from_verifying_key(public_key) -> bytes: |
---|
158 | """ |
---|
159 | Encode a public key to a string of bytes |
---|
160 | |
---|
161 | :param public_key: the public part of a keypair |
---|
162 | |
---|
163 | :returns: byte-string representing this key |
---|
164 | """ |
---|
165 | _validate_public_key(public_key) |
---|
166 | raw_key_bytes = public_key.public_bytes( |
---|
167 | Encoding.Raw, |
---|
168 | PublicFormat.Raw, |
---|
169 | ) |
---|
170 | return PUBLIC_KEY_PREFIX + b2a(raw_key_bytes) |
---|
171 | |
---|
172 | |
---|
173 | def _validate_public_key(public_key: Ed25519PublicKey): |
---|
174 | """ |
---|
175 | Internal helper. Verify that `public_key` is an appropriate object |
---|
176 | """ |
---|
177 | if not isinstance(public_key, Ed25519PublicKey): |
---|
178 | raise ValueError('public_key must be an Ed25519PublicKey') |
---|
179 | return None |
---|
180 | |
---|
181 | |
---|
182 | def _validate_private_key(private_key: Ed25519PrivateKey): |
---|
183 | """ |
---|
184 | Internal helper. Verify that `private_key` is an appropriate object |
---|
185 | """ |
---|
186 | if not isinstance(private_key, Ed25519PrivateKey): |
---|
187 | raise ValueError('private_key must be an Ed25519PrivateKey') |
---|
188 | return None |
---|