or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

curves.mdecdh.mdeddsa.mdencoding.mdindex.mdkeys-signatures.mdmathematical-functions.md

eddsa.mddocs/

0

# EdDSA Digital Signatures

1

2

Edwards-curve Digital Signature Algorithm (EdDSA) implementation providing pure EdDSA signatures using Ed25519 and Ed448 curves. EdDSA offers deterministic signatures, resistance to side-channel attacks, and high performance compared to traditional ECDSA.

3

4

## Capabilities

5

6

### EdDSA Public Key

7

8

Public key class for EdDSA signature verification on Edwards curves.

9

10

```python { .api }

11

class PublicKey:

12

"""Public key for Edwards Digital Signature Algorithm."""

13

14

def __init__(self, generator, public_key, public_point=None):

15

"""

16

Create EdDSA public key.

17

18

Parameters:

19

- generator: PointEdwards, curve generator point

20

- public_key: bytes, encoded public key

21

- public_point: PointEdwards, optional pre-computed point

22

23

Raises:

24

ValueError: if public key length is incorrect

25

"""

26

27

def public_point(self):

28

"""

29

Get public key as Edwards curve point.

30

31

Returns:

32

PointEdwards, public key point on Edwards curve

33

"""

34

35

def public_key(self):

36

"""

37

Get encoded public key bytes.

38

39

Returns:

40

bytes, encoded public key

41

"""

42

43

def verify(self, data, signature):

44

"""

45

Verify EdDSA signature over data.

46

47

Parameters:

48

- data: bytes or str, data that was signed

49

- signature: bytes, EdDSA signature (R || S)

50

51

Returns:

52

bool, True if signature is valid

53

54

Raises:

55

ValueError: if signature length is incorrect

56

"""

57

```

58

59

### EdDSA Private Key

60

61

Private key class for EdDSA signature creation on Edwards curves.

62

63

```python { .api }

64

class PrivateKey:

65

"""Private key for Edwards Digital Signature Algorithm."""

66

67

def __init__(self, generator, private_key):

68

"""

69

Create EdDSA private key.

70

71

Parameters:

72

- generator: PointEdwards, curve generator point

73

- private_key: bytes, raw private key bytes

74

75

Raises:

76

ValueError: if private key length is incorrect

77

"""

78

79

def private_key(self):

80

"""

81

Get raw private key bytes.

82

83

Returns:

84

bytes, raw private key material

85

"""

86

87

def public_key(self):

88

"""

89

Generate corresponding public key.

90

91

Returns:

92

PublicKey, public key derived from this private key

93

"""

94

95

def sign(self, data):

96

"""

97

Create EdDSA signature over data.

98

99

Parameters:

100

- data: bytes or str, data to sign

101

102

Returns:

103

bytes, EdDSA signature (R || S format)

104

"""

105

```

106

107

### Edwards Curve Parameters

108

109

Pre-defined Edwards curve parameters for Ed25519 and Ed448 algorithms.

110

111

```python { .api }

112

# Ed25519 curve and generator (RFC 8032)

113

curve_ed25519: CurveEdTw # Edwards curve y² = -x² + 1 - (121665/121666)x²y²

114

generator_ed25519: PointEdwards # Base point for Ed25519

115

116

# Ed448 curve and generator (RFC 8032)

117

curve_ed448: CurveEdTw # Edwards curve x² + y² = 1 - 39081x²y²

118

generator_ed448: PointEdwards # Base point for Ed448

119

```

120

121

## Usage Examples

122

123

### Ed25519 Signature Operations

124

125

```python

126

from ecdsa.eddsa import PrivateKey, PublicKey, generator_ed25519

127

import os

128

129

# Generate Ed25519 private key (32 bytes for Ed25519)

130

private_key_bytes = os.urandom(32)

131

private_key = PrivateKey(generator_ed25519, private_key_bytes)

132

133

# Get corresponding public key

134

public_key = private_key.public_key()

135

136

print(f"Private key length: {len(private_key.private_key())} bytes")

137

print(f"Public key length: {len(public_key.public_key())} bytes")

138

139

# Sign some data

140

message = b"Hello, EdDSA world!"

141

signature = private_key.sign(message)

142

143

print(f"Signature length: {len(signature)} bytes")

144

print(f"Signature (hex): {signature.hex()}")

145

146

# Verify signature

147

is_valid = public_key.verify(message, signature)

148

print(f"Signature valid: {is_valid}")

149

150

# Test with modified message (should fail)

151

try:

152

modified_message = b"Hello, EdDSA world!!"

153

is_valid_modified = public_key.verify(modified_message, signature)

154

print(f"Modified message signature valid: {is_valid_modified}")

155

except:

156

print("Signature verification failed for modified message")

157

```

158

159

### Ed448 Signature Operations

160

161

```python

162

from ecdsa.eddsa import PrivateKey, PublicKey, generator_ed448

163

import os

164

165

# Generate Ed448 private key (57 bytes for Ed448)

166

private_key_bytes = os.urandom(57)

167

private_key = PrivateKey(generator_ed448, private_key_bytes)

168

169

# Get corresponding public key

170

public_key = private_key.public_key()

171

172

print(f"Ed448 private key length: {len(private_key.private_key())} bytes")

173

print(f"Ed448 public key length: {len(public_key.public_key())} bytes")

174

175

# Sign data with Ed448

176

message = b"Ed448 provides higher security level"

177

signature = private_key.sign(message)

178

179

print(f"Ed448 signature length: {len(signature)} bytes")

180

print(f"Ed448 signature (hex): {signature.hex()}")

181

182

# Verify Ed448 signature

183

is_valid = public_key.verify(message, signature)

184

print(f"Ed448 signature valid: {is_valid}")

185

```

186

187

### Deterministic Signatures Demonstration

188

189

```python

190

from ecdsa.eddsa import PrivateKey, generator_ed25519

191

import os

192

193

# EdDSA signatures are deterministic - same message produces same signature

194

private_key_bytes = os.urandom(32)

195

private_key = PrivateKey(generator_ed25519, private_key_bytes)

196

197

message = b"Deterministic signature test"

198

199

# Sign the same message multiple times

200

sig1 = private_key.sign(message)

201

sig2 = private_key.sign(message)

202

sig3 = private_key.sign(message)

203

204

print(f"Signature 1: {sig1.hex()[:32]}...")

205

print(f"Signature 2: {sig2.hex()[:32]}...")

206

print(f"Signature 3: {sig3.hex()[:32]}...")

207

208

print(f"All signatures identical: {sig1 == sig2 == sig3}")

209

210

# Different messages produce different signatures

211

message2 = b"Different message"

212

sig_different = private_key.sign(message2)

213

print(f"Different message signature: {sig_different.hex()[:32]}...")

214

print(f"Signatures different: {sig1 != sig_different}")

215

```

216

217

### Working with Edwards Curve Points

218

219

```python

220

from ecdsa.eddsa import PrivateKey, generator_ed25519

221

from ecdsa.ellipticcurve import PointEdwards

222

import os

223

224

# Create private key and examine the underlying mathematics

225

private_key_bytes = os.urandom(32)

226

private_key = PrivateKey(generator_ed25519, private_key_bytes)

227

public_key = private_key.public_key()

228

229

# Get the public key point

230

public_point = public_key.public_point()

231

232

print(f"Public key point type: {type(public_point)}")

233

print(f"Point x coordinate: {public_point.x()}")

234

print(f"Point y coordinate: {public_point.y()}")

235

236

# Verify point is on the Edwards curve

237

curve = generator_ed25519.curve()

238

x, y = public_point.x(), public_point.y()

239

on_curve = curve.contains_point(x, y)

240

print(f"Public key point is on curve: {on_curve}")

241

242

# Demonstrate point arithmetic on Edwards curves

243

generator = generator_ed25519

244

scalar = 12345

245

result_point = scalar * generator

246

247

print(f"Scalar multiplication result: ({result_point.x()}, {result_point.y()})")

248

print(f"Result point on curve: {curve.contains_point(result_point.x(), result_point.y())}")

249

```

250

251

### Performance Comparison with ECDSA

252

253

```python

254

from ecdsa import SigningKey, NIST256p

255

from ecdsa.eddsa import PrivateKey, generator_ed25519

256

import time

257

import os

258

259

# Create ECDSA key (for comparison)

260

ecdsa_key = SigningKey.generate(curve=NIST256p)

261

262

# Create EdDSA key

263

eddsa_private_bytes = os.urandom(32)

264

eddsa_key = PrivateKey(generator_ed25519, eddsa_private_bytes)

265

266

message = b"Performance test message" * 10 # 250 bytes

267

268

# Time ECDSA signing

269

start_time = time.time()

270

for _ in range(100):

271

ecdsa_sig = ecdsa_key.sign(message)

272

ecdsa_sign_time = time.time() - start_time

273

274

# Time EdDSA signing

275

start_time = time.time()

276

for _ in range(100):

277

eddsa_sig = eddsa_key.sign(message)

278

eddsa_sign_time = time.time() - start_time

279

280

print(f"ECDSA signing (100 iterations): {ecdsa_sign_time:.4f} seconds")

281

print(f"EdDSA signing (100 iterations): {eddsa_sign_time:.4f} seconds")

282

print(f"EdDSA speedup: {ecdsa_sign_time / eddsa_sign_time:.2f}x")

283

284

# Time verification

285

ecdsa_vk = ecdsa_key.verifying_key

286

eddsa_pk = eddsa_key.public_key()

287

288

start_time = time.time()

289

for _ in range(100):

290

ecdsa_vk.verify(ecdsa_sig, message)

291

ecdsa_verify_time = time.time() - start_time

292

293

start_time = time.time()

294

for _ in range(100):

295

eddsa_pk.verify(message, eddsa_sig)

296

eddsa_verify_time = time.time() - start_time

297

298

print(f"ECDSA verification (100 iterations): {ecdsa_verify_time:.4f} seconds")

299

print(f"EdDSA verification (100 iterations): {eddsa_verify_time:.4f} seconds")

300

print(f"EdDSA verification speedup: {ecdsa_verify_time / eddsa_verify_time:.2f}x")

301

```

302

303

### EdDSA Key Storage and Serialization

304

305

```python

306

from ecdsa.eddsa import PrivateKey, PublicKey, generator_ed25519

307

import os

308

import json

309

import base64

310

311

# Generate key pair

312

private_key_bytes = os.urandom(32)

313

private_key = PrivateKey(generator_ed25519, private_key_bytes)

314

public_key = private_key.public_key()

315

316

# Serialize keys for storage

317

private_key_b64 = base64.b64encode(private_key.private_key()).decode('ascii')

318

public_key_b64 = base64.b64encode(public_key.public_key()).decode('ascii')

319

320

# Create key storage format

321

key_data = {

322

"algorithm": "Ed25519",

323

"private_key": private_key_b64,

324

"public_key": public_key_b64

325

}

326

327

print("Serialized key data:")

328

print(json.dumps(key_data, indent=2))

329

330

# Deserialize keys

331

loaded_private_bytes = base64.b64decode(key_data["private_key"])

332

loaded_public_bytes = base64.b64decode(key_data["public_key"])

333

334

# Reconstruct keys

335

loaded_private_key = PrivateKey(generator_ed25519, loaded_private_bytes)

336

loaded_public_key = PublicKey(generator_ed25519, loaded_public_bytes)

337

338

# Verify keys work correctly

339

test_message = b"Key serialization test"

340

signature = loaded_private_key.sign(test_message)

341

is_valid = loaded_public_key.verify(test_message, signature)

342

343

print(f"Loaded keys work correctly: {is_valid}")

344

print(f"Original and loaded private keys match: {private_key == loaded_private_key}")

345

print(f"Original and loaded public keys match: {public_key == loaded_public_key}")

346

```

347

348

### EdDSA Security Properties

349

350

```python

351

from ecdsa.eddsa import PrivateKey, generator_ed25519, generator_ed448

352

import os

353

354

# Demonstrate EdDSA security properties

355

print("EdDSA Security Properties:")

356

print("=" * 40)

357

358

# 1. Deterministic signatures (no randomness during signing)

359

private_key = PrivateKey(generator_ed25519, os.urandom(32))

360

message = b"Security test message"

361

362

sig1 = private_key.sign(message)

363

sig2 = private_key.sign(message)

364

print(f"1. Deterministic signatures: {sig1 == sig2}")

365

366

# 2. Context separation (different private keys, same message)

367

private_key2 = PrivateKey(generator_ed25519, os.urandom(32))

368

sig_different_key = private_key2.sign(message)

369

print(f"2. Different keys produce different signatures: {sig1 != sig_different_key}")

370

371

# 3. Ed25519 vs Ed448 security levels

372

ed25519_key = PrivateKey(generator_ed25519, os.urandom(32))

373

ed448_key = PrivateKey(generator_ed448, os.urandom(57))

374

375

ed25519_sig = ed25519_key.sign(message)

376

ed448_sig = ed448_key.sign(message)

377

378

print(f"3. Ed25519 signature length: {len(ed25519_sig)} bytes")

379

print(f" Ed448 signature length: {len(ed448_sig)} bytes")

380

print(f" Ed25519 security level: ~128 bits")

381

print(f" Ed448 security level: ~224 bits")

382

383

# 4. Signature malleability resistance

384

print("4. EdDSA signatures are not malleable (unlike some ECDSA implementations)")

385

386

# 5. Side-channel resistance

387

print("5. EdDSA is designed to be resistant to timing attacks")

388

print(" - No secret branches in the signing algorithm")

389

print(" - No secret array indices")

390

print(" - No secret memory access patterns")

391

```

392

393

## Algorithm Details

394

395

EdDSA provides several security and performance advantages over ECDSA:

396

397

### Security Benefits

398

399

1. **Deterministic Signatures**: No random number generation during signing eliminates the risk of nonce reuse attacks

400

2. **Malleability Resistance**: EdDSA signatures cannot be modified while remaining valid

401

3. **Side-Channel Resistance**: Designed to resist timing attacks and other side-channel attacks

402

4. **Complete Addition Formulas**: Edwards curves use complete addition formulas that work for all points

403

404

### Performance Benefits

405

406

1. **Faster Verification**: Edwards curve arithmetic is generally faster than Weierstrass curves

407

2. **Batch Verification**: Multiple signatures can be verified together more efficiently

408

3. **Smaller Signatures**: Ed25519 signatures are 64 bytes vs. 64-72 bytes for ECDSA on P-256

409

410

### Curve Properties

411

412

- **Ed25519**: Based on Curve25519, ~128-bit security level, 32-byte keys, 64-byte signatures

413

- **Ed448**: Based on Curve448, ~224-bit security level, 57-byte keys, 114-byte signatures