or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aead-ciphers.mdasymmetric-cryptography.mdhash-functions.mdindex.mdkey-derivation.mdkey-serialization.mdmessage-authentication.mdsymmetric-ciphers.mdsymmetric-encryption.mdtwo-factor-auth.mdutilities.mdx509-certificates.md

aead-ciphers.mddocs/

0

# AEAD Ciphers

1

2

Authenticated Encryption with Associated Data (AEAD) providing encryption and authentication in a single operation. AEAD ciphers ensure both confidentiality and authenticity of data while allowing additional authenticated data that remains unencrypted.

3

4

## Core Imports

5

6

```python

7

from cryptography.hazmat.primitives.ciphers.aead import AESGCM, ChaCha20Poly1305, AESCCM, AESSIV, AESOCB3, AESGCMSIV

8

```

9

10

## Capabilities

11

12

### AES-GCM (Galois/Counter Mode)

13

14

AES in Galois/Counter Mode providing authenticated encryption with excellent performance.

15

16

```python { .api }

17

class AESGCM:

18

def __init__(self, key: bytes):

19

"""

20

Initialize AES-GCM with key.

21

22

Args:

23

key (bytes): 128, 192, or 256-bit key (16, 24, or 32 bytes)

24

"""

25

26

@classmethod

27

def generate_key(cls, bit_length: int) -> bytes:

28

"""

29

Generate random key for AES-GCM.

30

31

Args:

32

bit_length (int): Key length in bits (128, 192, or 256)

33

34

Returns:

35

bytes: Random key of specified length

36

"""

37

38

def encrypt(self, nonce: bytes, data: bytes, associated_data: bytes = None) -> bytes:

39

"""

40

Encrypt data with authentication.

41

42

Args:

43

nonce (bytes): 96-bit (12 bytes) nonce. Must be unique per key.

44

data (bytes): Data to encrypt

45

associated_data (bytes, optional): Additional data to authenticate but not encrypt

46

47

Returns:

48

bytes: Encrypted data with authentication tag appended

49

50

Note:

51

Never reuse nonce with same key - this breaks security completely

52

"""

53

54

def decrypt(self, nonce: bytes, data: bytes, associated_data: bytes = None) -> bytes:

55

"""

56

Decrypt and verify authenticated data.

57

58

Args:

59

nonce (bytes): Same nonce used for encryption

60

data (bytes): Encrypted data with authentication tag

61

associated_data (bytes, optional): Same associated data from encryption

62

63

Returns:

64

bytes: Decrypted plaintext data

65

66

Raises:

67

InvalidTag: If authentication verification fails

68

"""

69

```

70

71

### ChaCha20-Poly1305

72

73

Modern stream cipher with Poly1305 MAC for authenticated encryption.

74

75

```python { .api }

76

class ChaCha20Poly1305:

77

def __init__(self, key: bytes):

78

"""

79

Initialize ChaCha20-Poly1305 with key.

80

81

Args:

82

key (bytes): 256-bit key (32 bytes)

83

"""

84

85

@classmethod

86

def generate_key(cls) -> bytes:

87

"""

88

Generate random 256-bit key.

89

90

Returns:

91

bytes: 32-byte random key

92

"""

93

94

def encrypt(self, nonce: bytes, data: bytes, associated_data: bytes = None) -> bytes:

95

"""

96

Encrypt data with ChaCha20-Poly1305.

97

98

Args:

99

nonce (bytes): 96-bit (12 bytes) nonce. Must be unique per key.

100

data (bytes): Data to encrypt

101

associated_data (bytes, optional): Additional authenticated data

102

103

Returns:

104

bytes: Encrypted data with Poly1305 tag appended

105

"""

106

107

def decrypt(self, nonce: bytes, data: bytes, associated_data: bytes = None) -> bytes:

108

"""

109

Decrypt and verify ChaCha20-Poly1305 data.

110

111

Args:

112

nonce (bytes): Same nonce used for encryption

113

data (bytes): Encrypted data with authentication tag

114

associated_data (bytes, optional): Same associated data from encryption

115

116

Returns:

117

bytes: Decrypted plaintext

118

119

Raises:

120

InvalidTag: If Poly1305 authentication fails

121

"""

122

```

123

124

### AES-CCM (Counter with CBC-MAC)

125

126

AES Counter mode with CBC-MAC for authenticated encryption.

127

128

```python { .api }

129

class AESCCM:

130

def __init__(self, key: bytes, tag_length: int = 16):

131

"""

132

Initialize AES-CCM with key and tag length.

133

134

Args:

135

key (bytes): 128, 192, or 256-bit AES key

136

tag_length (int): Authentication tag length (4, 6, 8, 10, 12, 14, 16 bytes)

137

"""

138

139

@classmethod

140

def generate_key(cls, bit_length: int) -> bytes:

141

"""Generate random AES key"""

142

143

def encrypt(self, nonce: bytes, data: bytes, associated_data: bytes = None) -> bytes:

144

"""

145

Encrypt with AES-CCM.

146

147

Args:

148

nonce (bytes): 7-15 byte nonce (longer nonce = shorter counter)

149

data (bytes): Data to encrypt

150

associated_data (bytes, optional): Additional authenticated data

151

152

Returns:

153

bytes: Encrypted data with CBC-MAC tag

154

"""

155

156

def decrypt(self, nonce: bytes, data: bytes, associated_data: bytes = None) -> bytes:

157

"""

158

Decrypt and verify AES-CCM data.

159

160

Raises:

161

InvalidTag: If CBC-MAC verification fails

162

"""

163

```

164

165

### AES-SIV (Synthetic Initialization Vector)

166

167

Misuse-resistant authenticated encryption that's secure even with nonce reuse.

168

169

```python { .api }

170

class AESSIV:

171

def __init__(self, key: bytes):

172

"""

173

Initialize AES-SIV.

174

175

Args:

176

key (bytes): 256, 384, or 512-bit key (32, 48, or 64 bytes)

177

Key length determines AES variant (AES-128, AES-192, AES-256)

178

"""

179

180

@classmethod

181

def generate_key(cls, bit_length: int) -> bytes:

182

"""Generate random key for AES-SIV"""

183

184

def encrypt(self, data: bytes, associated_data: List[bytes] = None) -> bytes:

185

"""

186

Encrypt with AES-SIV (no nonce required).

187

188

Args:

189

data (bytes): Data to encrypt

190

associated_data (List[bytes], optional): List of associated data items

191

192

Returns:

193

bytes: SIV (16 bytes) + encrypted data

194

195

Note:

196

AES-SIV is nonce-misuse resistant - safe even with repeated inputs

197

"""

198

199

def decrypt(self, data: bytes, associated_data: List[bytes] = None) -> bytes:

200

"""

201

Decrypt AES-SIV data.

202

203

Args:

204

data (bytes): SIV + encrypted data from encrypt()

205

associated_data (List[bytes], optional): Same associated data from encryption

206

207

Returns:

208

bytes: Decrypted plaintext

209

210

Raises:

211

InvalidTag: If SIV verification fails

212

"""

213

```

214

215

### AES-OCB3 (Offset Codebook Mode)

216

217

High-performance authenticated encryption mode.

218

219

```python { .api }

220

class AESOCB3:

221

def __init__(self, key: bytes):

222

"""

223

Initialize AES-OCB3.

224

225

Args:

226

key (bytes): 128, 192, or 256-bit AES key

227

"""

228

229

@classmethod

230

def generate_key(cls, bit_length: int) -> bytes:

231

"""Generate random AES key"""

232

233

def encrypt(self, nonce: bytes, data: bytes, associated_data: bytes = None) -> bytes:

234

"""

235

Encrypt with AES-OCB3.

236

237

Args:

238

nonce (bytes): 1-15 byte nonce, must be unique per key

239

data (bytes): Data to encrypt

240

associated_data (bytes, optional): Additional authenticated data

241

242

Returns:

243

bytes: Encrypted data with authentication tag

244

"""

245

246

def decrypt(self, nonce: bytes, data: bytes, associated_data: bytes = None) -> bytes:

247

"""

248

Decrypt AES-OCB3 data.

249

250

Raises:

251

InvalidTag: If authentication verification fails

252

"""

253

```

254

255

### AES-GCM-SIV (Galois/Counter Mode with SIV)

256

257

Misuse-resistant variant of AES-GCM that's secure with nonce reuse.

258

259

```python { .api }

260

class AESGCMSIV:

261

def __init__(self, key: bytes):

262

"""

263

Initialize AES-GCM-SIV.

264

265

Args:

266

key (bytes): 128 or 256-bit key (16 or 32 bytes)

267

"""

268

269

@classmethod

270

def generate_key(cls, bit_length: int) -> bytes:

271

"""Generate random key for AES-GCM-SIV"""

272

273

def encrypt(self, nonce: bytes, data: bytes, associated_data: bytes = None) -> bytes:

274

"""

275

Encrypt with AES-GCM-SIV.

276

277

Args:

278

nonce (bytes): 96-bit (12 bytes) nonce

279

data (bytes): Data to encrypt

280

associated_data (bytes, optional): Additional authenticated data

281

282

Returns:

283

bytes: Encrypted data with authentication tag

284

285

Note:

286

Secure even with nonce reuse, but unique nonces still recommended

287

"""

288

289

def decrypt(self, nonce: bytes, data: bytes, associated_data: bytes = None) -> bytes:

290

"""

291

Decrypt AES-GCM-SIV data.

292

293

Raises:

294

InvalidTag: If authentication verification fails

295

"""

296

```

297

298

## Usage Examples

299

300

### Basic AES-GCM Encryption

301

302

```python

303

from cryptography.hazmat.primitives.ciphers.aead import AESGCM

304

from cryptography.exceptions import InvalidTag

305

import os

306

307

# Generate key and nonce

308

key = AESGCM.generate_key(256) # 256-bit key

309

aesgcm = AESGCM(key)

310

311

# Encrypt data

312

nonce = os.urandom(12) # 96-bit nonce

313

plaintext = b"Secret message for authenticated encryption"

314

associated_data = b"public metadata"

315

316

ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data)

317

print(f"Encrypted: {ciphertext.hex()}")

318

319

# Decrypt data

320

try:

321

decrypted = aesgcm.decrypt(nonce, ciphertext, associated_data)

322

print(f"Decrypted: {decrypted}")

323

except InvalidTag:

324

print("Authentication failed - data may be tampered")

325

```

326

327

### ChaCha20-Poly1305 for High-Performance Applications

328

329

```python

330

from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305

331

import os

332

333

# Initialize ChaCha20-Poly1305

334

key = ChaCha20Poly1305.generate_key()

335

chacha = ChaCha20Poly1305(key)

336

337

# Encrypt with associated data

338

nonce = os.urandom(12)

339

message = b"High-speed encrypted message"

340

metadata = b"timestamp:2024-01-01,user:alice"

341

342

encrypted = chacha.encrypt(nonce, message, metadata)

343

344

# Decrypt and verify

345

try:

346

decrypted = chacha.decrypt(nonce, encrypted, metadata)

347

print(f"Message: {decrypted}")

348

print("Authentication successful")

349

except InvalidTag:

350

print("Message authentication failed")

351

```

352

353

### Secure File Encryption with AES-GCM

354

355

```python

356

from cryptography.hazmat.primitives.ciphers.aead import AESGCM

357

import os

358

import json

359

360

class SecureFileManager:

361

def __init__(self, key=None):

362

self.key = key or AESGCM.generate_key(256)

363

self.aesgcm = AESGCM(self.key)

364

365

def encrypt_file(self, input_path, output_path, metadata=None):

366

"""Encrypt file with optional metadata"""

367

with open(input_path, 'rb') as f:

368

plaintext = f.read()

369

370

nonce = os.urandom(12)

371

associated_data = json.dumps(metadata or {}).encode() if metadata else None

372

373

ciphertext = self.aesgcm.encrypt(nonce, plaintext, associated_data)

374

375

# Store nonce + ciphertext + metadata length + metadata

376

with open(output_path, 'wb') as f:

377

f.write(nonce) # First 12 bytes

378

f.write(len(associated_data or b"").to_bytes(4, 'big')) # Metadata length

379

if associated_data:

380

f.write(associated_data) # Metadata

381

f.write(ciphertext) # Encrypted content

382

383

def decrypt_file(self, input_path, output_path):

384

"""Decrypt file and return metadata"""

385

with open(input_path, 'rb') as f:

386

nonce = f.read(12)

387

metadata_len = int.from_bytes(f.read(4), 'big')

388

associated_data = f.read(metadata_len) if metadata_len > 0 else None

389

ciphertext = f.read()

390

391

try:

392

plaintext = self.aesgcm.decrypt(nonce, ciphertext, associated_data)

393

394

with open(output_path, 'wb') as f:

395

f.write(plaintext)

396

397

metadata = json.loads(associated_data.decode()) if associated_data else {}

398

return metadata

399

400

except InvalidTag:

401

raise ValueError("File decryption failed - file may be corrupted or tampered")

402

403

# Usage

404

file_manager = SecureFileManager()

405

406

# Encrypt file with metadata

407

file_manager.encrypt_file(

408

'document.pdf',

409

'document.pdf.enc',

410

metadata={'author': 'Alice', 'classification': 'confidential'}

411

)

412

413

# Decrypt file

414

metadata = file_manager.decrypt_file('document.pdf.enc', 'document_decrypted.pdf')

415

print(f"File metadata: {metadata}")

416

```

417

418

### Misuse-Resistant Encryption with AES-SIV

419

420

```python

421

from cryptography.hazmat.primitives.ciphers.aead import AESSIV

422

423

# AES-SIV is safe even with nonce reuse

424

key = AESSIV.generate_key(256) # 256-bit key for AES-128-SIV

425

aessiv = AESSIV(key)

426

427

# Encrypt same data multiple times (normally dangerous)

428

data = b"Repeated message"

429

associated_data = [b"context1", b"context2"]

430

431

# These encryptions are safe even though input is identical

432

ciphertext1 = aessiv.encrypt(data, associated_data)

433

ciphertext2 = aessiv.encrypt(data, associated_data)

434

435

print(f"Encryption 1: {ciphertext1.hex()}")

436

print(f"Encryption 2: {ciphertext2.hex()}")

437

print(f"Same result: {ciphertext1 == ciphertext2}") # True - deterministic

438

439

# Decrypt both

440

decrypted1 = aessiv.decrypt(ciphertext1, associated_data)

441

decrypted2 = aessiv.decrypt(ciphertext2, associated_data)

442

443

print(f"Decrypted: {decrypted1}")

444

```

445

446

### Multi-Algorithm AEAD Wrapper

447

448

```python

449

from cryptography.hazmat.primitives.ciphers.aead import AESGCM, ChaCha20Poly1305, AESSIV

450

from cryptography.exceptions import InvalidTag

451

import os

452

import struct

453

454

class UniversalAEAD:

455

ALGORITHMS = {

456

'AES-GCM': AESGCM,

457

'ChaCha20-Poly1305': ChaCha20Poly1305,

458

'AES-SIV': AESSIV

459

}

460

461

def __init__(self, algorithm='AES-GCM', key_size=256):

462

self.algorithm = algorithm

463

self.key_size = key_size

464

465

if algorithm == 'AES-GCM':

466

self.key = AESGCM.generate_key(key_size)

467

self.cipher = AESGCM(self.key)

468

elif algorithm == 'ChaCha20-Poly1305':

469

self.key = ChaCha20Poly1305.generate_key()

470

self.cipher = ChaCha20Poly1305(self.key)

471

elif algorithm == 'AES-SIV':

472

self.key = AESSIV.generate_key(key_size)

473

self.cipher = AESSIV(self.key)

474

475

def encrypt(self, data, associated_data=None):

476

"""Encrypt with algorithm identification"""

477

if self.algorithm == 'AES-SIV':

478

# AES-SIV doesn't use nonce

479

ciphertext = self.cipher.encrypt(data, [associated_data] if associated_data else None)

480

nonce = b''

481

else:

482

# Nonce-based algorithms

483

nonce = os.urandom(12)

484

ciphertext = self.cipher.encrypt(nonce, data, associated_data)

485

486

# Format: algorithm_id (1 byte) + nonce_len (1 byte) + nonce + ciphertext

487

algorithm_id = list(self.ALGORITHMS.keys()).index(self.algorithm)

488

header = struct.pack('BB', algorithm_id, len(nonce))

489

490

return header + nonce + ciphertext

491

492

def decrypt(self, encrypted_data, associated_data=None):

493

"""Decrypt with automatic algorithm detection"""

494

algorithm_id, nonce_len = struct.unpack('BB', encrypted_data[:2])

495

algorithm = list(self.ALGORITHMS.keys())[algorithm_id]

496

497

nonce = encrypted_data[2:2+nonce_len]

498

ciphertext = encrypted_data[2+nonce_len:]

499

500

if algorithm == 'AES-SIV':

501

return self.cipher.decrypt(ciphertext, [associated_data] if associated_data else None)

502

else:

503

return self.cipher.decrypt(nonce, ciphertext, associated_data)

504

505

# Usage

506

# Try different algorithms

507

for alg in ['AES-GCM', 'ChaCha20-Poly1305', 'AES-SIV']:

508

aead = UniversalAEAD(alg)

509

510

data = b"Test message for " + alg.encode()

511

metadata = b"algorithm:" + alg.encode()

512

513

encrypted = aead.encrypt(data, metadata)

514

decrypted = aead.decrypt(encrypted, metadata)

515

516

print(f"{alg}: {decrypted}")

517

```

518

519

## Security Considerations

520

521

- **Nonce Management**: Never reuse nonces with the same key (except AES-SIV/GCM-SIV)

522

- **Key Rotation**: Regularly rotate encryption keys

523

- **Associated Data**: Use associated data for context binding

524

- **Algorithm Selection**:

525

- AES-GCM: Fastest, requires careful nonce management

526

- ChaCha20-Poly1305: Fast, good for software implementations

527

- AES-SIV: Misuse-resistant but slower

528

- **Authentication**: Always verify authentication tags before processing decrypted data

529

- **Side-Channel Protection**: AEAD algorithms resist timing attacks

530

- **Nonce Sizes**: Respect algorithm-specific nonce requirements