or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-operations.mdcore-functionality.mdcryptographic-operations.mdidentity-resolution.mdindex.mdjwt-operations.mdreal-time-streaming.md

cryptographic-operations.mddocs/

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

```