0
# Cryptographic Operations
1
2
Cryptographic key management, signature verification, multibase encoding/decoding, and DID key generation for secure AT Protocol communications. These operations ensure data integrity, authentication, and secure communication within the AT Protocol ecosystem.
3
4
## Capabilities
5
6
### Key Management
7
8
#### Multikey
9
10
Cryptographic key representation supporting multiple key types and algorithms for AT Protocol operations.
11
12
```python { .api }
13
class Multikey:
14
"""
15
Cryptographic key representation with algorithm specification.
16
17
Attributes:
18
jwt_alg (str): JWT algorithm identifier (e.g., 'ES256K', 'Ed25519')
19
key_bytes (bytes): Raw key material
20
"""
21
jwt_alg: str
22
key_bytes: bytes
23
24
@classmethod
25
def from_str(cls, multikey: str) -> 'Multikey':
26
"""
27
Parse Multikey from string representation.
28
29
Args:
30
multikey (str): Multikey string (e.g., multibase encoded)
31
32
Returns:
33
Multikey: Parsed key object
34
35
Raises:
36
ValueError: If multikey format is invalid
37
"""
38
39
def to_str(self) -> str:
40
"""
41
Format Multikey as string.
42
43
Returns:
44
str: Multikey string representation
45
"""
46
47
@property
48
def algorithm(self) -> str:
49
"""Get the cryptographic algorithm."""
50
51
@property
52
def key_type(self) -> str:
53
"""Get the key type (e.g., 'secp256k1', 'ed25519')."""
54
55
def public_key_bytes(self) -> bytes:
56
"""
57
Extract public key bytes.
58
59
Returns:
60
bytes: Public key material
61
"""
62
```
63
64
Usage example:
65
66
```python
67
from atproto import Multikey
68
69
# Parse multikey from string
70
multikey_str = "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
71
multikey = Multikey.from_str(multikey_str)
72
73
print(f"Algorithm: {multikey.jwt_alg}")
74
print(f"Key type: {multikey.key_type}")
75
print(f"Key bytes length: {len(multikey.key_bytes)}")
76
77
# Convert back to string
78
key_str = multikey.to_str()
79
assert key_str == multikey_str
80
```
81
82
#### DID Key Generation
83
84
Generate DID keys from cryptographic key material for decentralized identity operations.
85
86
```python { .api }
87
def get_did_key(key: Union[Multikey, bytes, str]) -> str:
88
"""
89
Generate DID key from cryptographic key material.
90
91
Args:
92
key (Union[Multikey, bytes, str]): Key material in various formats
93
94
Returns:
95
str: DID key string (e.g., "did:key:z6MkhaXgB...")
96
97
Raises:
98
ValueError: If key format is unsupported
99
"""
100
```
101
102
Usage example:
103
104
```python
105
from atproto import get_did_key, Multikey
106
107
# Generate DID key from Multikey
108
multikey = Multikey.from_str("z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK")
109
did_key = get_did_key(multikey)
110
print(f"DID key: {did_key}")
111
112
# Generate DID key from raw bytes
113
key_bytes = b'\x01\x02\x03...' # Your key bytes
114
did_key = get_did_key(key_bytes)
115
print(f"DID key from bytes: {did_key}")
116
```
117
118
### Multibase Encoding
119
120
Multibase provides self-describing base encodings for binary data, enabling interoperability across different encoding schemes.
121
122
#### Encoding to Multibase
123
124
```python { .api }
125
def bytes_to_multibase(encoding: str, data: bytes) -> str:
126
"""
127
Encode bytes to multibase format.
128
129
Args:
130
encoding (str): Multibase encoding character:
131
- 'z' for base58btc
132
- 'f' for base16 (hex)
133
- 'b' for base32
134
- 'u' for base64url
135
- 'm' for base64
136
data (bytes): Data to encode
137
138
Returns:
139
str: Multibase encoded string
140
141
Raises:
142
ValueError: If encoding is unsupported
143
"""
144
```
145
146
#### Decoding from Multibase
147
148
```python { .api }
149
def multibase_to_bytes(data: str) -> bytes:
150
"""
151
Decode multibase string to bytes.
152
153
Args:
154
data (str): Multibase encoded string (first character indicates encoding)
155
156
Returns:
157
bytes: Decoded data
158
159
Raises:
160
ValueError: If multibase format is invalid or encoding unsupported
161
"""
162
```
163
164
Usage examples:
165
166
```python
167
from atproto import bytes_to_multibase, multibase_to_bytes
168
169
# Original data
170
original_data = b"Hello, AT Protocol!"
171
172
# Encode to different multibase formats
173
base58_encoded = bytes_to_multibase('z', original_data)
174
print(f"Base58: {base58_encoded}")
175
176
base32_encoded = bytes_to_multibase('b', original_data)
177
print(f"Base32: {base32_encoded}")
178
179
base64_encoded = bytes_to_multibase('m', original_data)
180
print(f"Base64: {base64_encoded}")
181
182
# Decode back to bytes
183
decoded_from_base58 = multibase_to_bytes(base58_encoded)
184
decoded_from_base32 = multibase_to_bytes(base32_encoded)
185
decoded_from_base64 = multibase_to_bytes(base64_encoded)
186
187
# All should equal original data
188
assert decoded_from_base58 == original_data
189
assert decoded_from_base32 == original_data
190
assert decoded_from_base64 == original_data
191
192
# The encoding is self-describing
193
print(f"Base58 prefix: {base58_encoded[0]}") # 'z'
194
print(f"Base32 prefix: {base32_encoded[0]}") # 'b'
195
print(f"Base64 prefix: {base64_encoded[0]}") # 'm'
196
```
197
198
### Signature Verification
199
200
Verify cryptographic signatures using DID keys to ensure message authenticity and integrity.
201
202
```python { .api }
203
def verify_signature(did_key: str, signing_input: bytes, signature: bytes) -> bool:
204
"""
205
Verify cryptographic signature using DID key.
206
207
Args:
208
did_key (str): DID key for verification (e.g., "did:key:z6Mk...")
209
signing_input (bytes): Original data that was signed
210
signature (bytes): Signature to verify
211
212
Returns:
213
bool: True if signature is valid, False otherwise
214
215
Raises:
216
ValueError: If DID key format is invalid
217
UnsupportedAlgorithmError: If key algorithm is not supported
218
"""
219
```
220
221
Usage example:
222
223
```python
224
from atproto import verify_signature, get_did_key
225
226
# Example verification scenario
227
did_key = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
228
message = b"This message was signed"
229
signature = b"\x01\x02\x03..." # Actual signature bytes
230
231
# Verify the signature
232
is_valid = verify_signature(did_key, message, signature)
233
234
if is_valid:
235
print("✓ Signature is valid - message is authentic")
236
else:
237
print("✗ Signature is invalid - message may be tampered")
238
239
# Common use case: JWT signature verification
240
jwt_header = b'{"alg":"ES256K","typ":"JWT"}'
241
jwt_payload = b'{"iss":"did:plc:alice","sub":"did:plc:alice"}'
242
jwt_signing_input = base64_encode(jwt_header) + b'.' + base64_encode(jwt_payload)
243
244
jwt_signature = b"\x30\x45..." # JWT signature bytes
245
is_jwt_valid = verify_signature(did_key, jwt_signing_input, jwt_signature)
246
```
247
248
### Key Format Conversion
249
250
Utilities for converting between different key formats used in AT Protocol.
251
252
```python { .api }
253
def multikey_to_did_key(multikey: Union[str, Multikey]) -> str:
254
"""
255
Convert Multikey to DID key format.
256
257
Args:
258
multikey (Union[str, Multikey]): Multikey to convert
259
260
Returns:
261
str: DID key string
262
"""
263
264
def did_key_to_multikey(did_key: str) -> Multikey:
265
"""
266
Extract Multikey from DID key.
267
268
Args:
269
did_key (str): DID key string
270
271
Returns:
272
Multikey: Extracted multikey
273
274
Raises:
275
ValueError: If DID key format is invalid
276
"""
277
278
def public_key_to_multikey(public_key: bytes, algorithm: str) -> Multikey:
279
"""
280
Create Multikey from raw public key bytes.
281
282
Args:
283
public_key (bytes): Raw public key bytes
284
algorithm (str): Key algorithm ('secp256k1', 'ed25519', etc.)
285
286
Returns:
287
Multikey: Constructed multikey
288
289
Raises:
290
ValueError: If algorithm is unsupported
291
"""
292
```
293
294
Usage examples:
295
296
```python
297
from atproto import (
298
Multikey, multikey_to_did_key, did_key_to_multikey,
299
public_key_to_multikey
300
)
301
302
# Convert between formats
303
multikey_str = "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
304
multikey = Multikey.from_str(multikey_str)
305
306
# Multikey to DID key
307
did_key = multikey_to_did_key(multikey)
308
print(f"DID key: {did_key}")
309
310
# DID key back to Multikey
311
recovered_multikey = did_key_to_multikey(did_key)
312
assert recovered_multikey.to_str() == multikey_str
313
314
# Create Multikey from raw key bytes
315
raw_public_key = b'\x04\x01\x02\x03...' # secp256k1 public key
316
multikey_from_raw = public_key_to_multikey(raw_public_key, 'secp256k1')
317
print(f"Multikey from raw: {multikey_from_raw.to_str()}")
318
```
319
320
### Cryptographic Algorithms
321
322
The SDK supports multiple cryptographic algorithms for different use cases:
323
324
```python { .api }
325
class SupportedAlgorithms:
326
"""Supported cryptographic algorithms."""
327
SECP256K1 = 'secp256k1' # Bitcoin/Ethereum style keys
328
ED25519 = 'ed25519' # High-performance EdDSA
329
P256 = 'p256' # NIST P-256 curve
330
331
class JWTAlgorithms:
332
"""JWT algorithm identifiers."""
333
ES256K = 'ES256K' # ECDSA using secp256k1
334
EDDSA = 'EdDSA' # EdDSA using Ed25519
335
ES256 = 'ES256' # ECDSA using P-256
336
```
337
338
Algorithm selection example:
339
340
```python
341
from atproto import Multikey, SupportedAlgorithms, JWTAlgorithms
342
343
# Create keys for different algorithms
344
algorithms = [
345
(SupportedAlgorithms.SECP256K1, JWTAlgorithms.ES256K),
346
(SupportedAlgorithms.ED25519, JWTAlgorithms.EDDSA),
347
(SupportedAlgorithms.P256, JWTAlgorithms.ES256)
348
]
349
350
for key_type, jwt_alg in algorithms:
351
# In practice, you would generate actual key material
352
mock_key_bytes = b'\x01' * 32 # Placeholder
353
354
multikey = Multikey(jwt_alg=jwt_alg, key_bytes=mock_key_bytes)
355
did_key = get_did_key(multikey)
356
357
print(f"Algorithm: {key_type}")
358
print(f"JWT Algorithm: {jwt_alg}")
359
print(f"DID Key: {did_key[:50]}...")
360
print()
361
```
362
363
### Error Handling
364
365
```python { .api }
366
class CryptographicError(Exception):
367
"""Base exception for cryptographic operations."""
368
369
class InvalidKeyError(CryptographicError):
370
"""Raised when key format or content is invalid."""
371
372
class UnsupportedAlgorithmError(CryptographicError):
373
"""Raised when algorithm is not supported."""
374
375
class SignatureVerificationError(CryptographicError):
376
"""Raised when signature verification fails."""
377
378
class MultibaseError(CryptographicError):
379
"""Raised for multibase encoding/decoding errors."""
380
```
381
382
Error handling patterns:
383
384
```python
385
from atproto import (
386
verify_signature, multibase_to_bytes,
387
InvalidKeyError, UnsupportedAlgorithmError, MultibaseError
388
)
389
390
# Handle key errors
391
try:
392
invalid_did_key = "did:key:invalid"
393
verify_signature(invalid_did_key, b"data", b"signature")
394
except InvalidKeyError as e:
395
print(f"Invalid key format: {e}")
396
397
# Handle algorithm errors
398
try:
399
unsupported_multikey = "unsupported_format_key"
400
multikey = Multikey.from_str(unsupported_multikey)
401
except UnsupportedAlgorithmError as e:
402
print(f"Unsupported algorithm: {e}")
403
404
# Handle multibase errors
405
try:
406
invalid_multibase = "invalid_multibase_string"
407
decoded = multibase_to_bytes(invalid_multibase)
408
except MultibaseError as e:
409
print(f"Multibase decoding failed: {e}")
410
```