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

keys-signatures.mddocs/

0

# Core Keys & Signatures

1

2

Primary ECDSA/EdDSA functionality for creating and verifying digital signatures. This module provides the main interface for elliptic curve cryptographic operations including key generation, deterministic signing, and signature verification with support for multiple curves and hash functions.

3

4

## Capabilities

5

6

### SigningKey Class

7

8

The SigningKey class represents a private key for creating digital signatures using ECDSA or EdDSA algorithms.

9

10

#### Key Generation and Loading

11

12

```python { .api }

13

class SigningKey:

14

@classmethod

15

def generate(cls, curve=NIST192p, entropy=None, hashfunc=sha1):

16

"""

17

Generate a new random signing key.

18

19

Parameters:

20

- curve: Curve object (default NIST192p)

21

- entropy: callable returning random bytes, or None for os.urandom

22

- hashfunc: hash function for signatures (default sha1)

23

24

Returns:

25

SigningKey object

26

"""

27

28

@classmethod

29

def from_secret_exponent(cls, secexp, curve=NIST192p, hashfunc=sha1):

30

"""

31

Create SigningKey from integer secret exponent.

32

33

Parameters:

34

- secexp: int, secret exponent (private key value)

35

- curve: Curve object (default NIST192p)

36

- hashfunc: hash function for signatures (default sha1)

37

38

Returns:

39

SigningKey object

40

"""

41

42

@classmethod

43

def from_string(cls, string, curve=NIST192p, hashfunc=sha1):

44

"""

45

Create SigningKey from raw byte string.

46

47

Parameters:

48

- string: bytes, raw private key bytes

49

- curve: Curve object (default NIST192p)

50

- hashfunc: hash function for signatures (default sha1)

51

52

Returns:

53

SigningKey object

54

"""

55

56

@classmethod

57

def from_pem(cls, string, hashfunc=sha1, valid_curve_encodings=None):

58

"""

59

Create SigningKey from PEM-encoded private key.

60

61

Parameters:

62

- string: str or bytes, PEM-encoded private key

63

- hashfunc: hash function for signatures (default sha1)

64

- valid_curve_encodings: list of acceptable curve encodings or None

65

66

Returns:

67

SigningKey object

68

"""

69

70

@classmethod

71

def from_der(cls, string, hashfunc=sha1, valid_curve_encodings=None):

72

"""

73

Create SigningKey from DER-encoded private key.

74

75

Parameters:

76

- string: bytes, DER-encoded private key

77

- hashfunc: hash function for signatures (default sha1)

78

- valid_curve_encodings: list of acceptable curve encodings or None

79

80

Returns:

81

SigningKey object

82

"""

83

```

84

85

#### Signing Operations

86

87

```python { .api }

88

def sign(self, data, entropy=None, hashfunc=None, sigencode=sigencode_string, k=None, allow_truncate=True):

89

"""

90

Sign data using ECDSA/EdDSA.

91

92

Parameters:

93

- data: bytes, data to sign

94

- entropy: callable returning random bytes, or None for default

95

- hashfunc: hash function, or None for default

96

- sigencode: signature encoding function (default sigencode_string)

97

- k: int, specific k value for signature (for testing only)

98

- allow_truncate: bool, allow hash truncation for curve compatibility

99

100

Returns:

101

bytes, encoded signature

102

"""

103

104

def sign_deterministic(self, data, hashfunc=None, sigencode=sigencode_string, extra_entropy=b""):

105

"""

106

Sign data using RFC 6979 deterministic ECDSA.

107

108

Parameters:

109

- data: bytes, data to sign

110

- hashfunc: hash function, or None for default

111

- sigencode: signature encoding function (default sigencode_string)

112

- extra_entropy: bytes, additional entropy for deterministic generation

113

114

Returns:

115

bytes, encoded signature

116

"""

117

118

def sign_digest(self, digest, entropy=None, sigencode=sigencode_string, k=None, allow_truncate=False):

119

"""

120

Sign a pre-computed hash digest.

121

122

Parameters:

123

- digest: bytes, hash digest to sign

124

- entropy: callable returning random bytes, or None for default

125

- sigencode: signature encoding function (default sigencode_string)

126

- k: int, specific k value for signature (for testing only)

127

- allow_truncate: bool, allow hash truncation for curve compatibility

128

129

Returns:

130

bytes, encoded signature

131

"""

132

133

def sign_digest_deterministic(self, digest, hashfunc=None, sigencode=sigencode_string, extra_entropy=b"", allow_truncate=False):

134

"""

135

Sign a pre-computed hash digest using RFC 6979 deterministic ECDSA.

136

137

Parameters:

138

- digest: bytes, hash digest to sign

139

- hashfunc: hash function used to create digest (required for RFC 6979)

140

- sigencode: signature encoding function (default sigencode_string)

141

- extra_entropy: bytes, additional entropy for deterministic generation

142

- allow_truncate: bool, allow hash truncation for curve compatibility

143

144

Returns:

145

bytes, encoded signature

146

"""

147

148

def sign_number(self, number, entropy=None, k=None):

149

"""

150

Sign a number directly (low-level interface).

151

152

Parameters:

153

- number: int, number to sign

154

- entropy: callable returning random bytes, or None for default

155

- k: int, specific k value for signature (for testing only)

156

157

Returns:

158

tuple[int, int], (r, s) signature pair

159

"""

160

```

161

162

#### Key Access and Export

163

164

```python { .api }

165

def get_verifying_key(self):

166

"""

167

Get the corresponding public key.

168

169

Returns:

170

VerifyingKey object

171

"""

172

173

def to_string(self):

174

"""

175

Export private key as raw bytes.

176

177

Returns:

178

bytes, raw private key

179

"""

180

181

def to_pem(self, point_encoding="uncompressed", format="ssleay", curve_parameters_encoding=None):

182

"""

183

Export private key in PEM format.

184

185

Parameters:

186

- point_encoding: str, point encoding format ("uncompressed", "compressed", "hybrid")

187

- format: str, PEM format variant ("ssleay", "pkcs8")

188

- curve_parameters_encoding: str or None, curve parameter encoding

189

190

Returns:

191

bytes, PEM-encoded private key

192

"""

193

194

def to_der(self, point_encoding="uncompressed", format="ssleay", curve_parameters_encoding=None):

195

"""

196

Export private key in DER format.

197

198

Parameters:

199

- point_encoding: str, point encoding format ("uncompressed", "compressed", "hybrid")

200

- format: str, DER format variant ("ssleay", "pkcs8")

201

- curve_parameters_encoding: str or None, curve parameter encoding

202

203

Returns:

204

bytes, DER-encoded private key

205

"""

206

207

def to_ssh(self):

208

"""

209

Export private key in SSH format.

210

211

Returns:

212

bytes, SSH-encoded private key

213

"""

214

```

215

216

#### Key Attributes

217

218

```python { .api }

219

curve: Curve # The elliptic curve object

220

default_hashfunc: callable # Default hash function

221

baselen: int # Length of raw key encoding in bytes

222

verifying_key: VerifyingKey # Associated public key

223

```

224

225

### VerifyingKey Class

226

227

The VerifyingKey class represents a public key for verifying digital signatures created with ECDSA or EdDSA algorithms.

228

229

#### Key Loading and Creation

230

231

```python { .api }

232

class VerifyingKey:

233

@classmethod

234

def from_public_point(cls, point, curve=NIST192p, hashfunc=sha1, validate_point=True):

235

"""

236

Create VerifyingKey from elliptic curve point.

237

238

Parameters:

239

- point: Point object, public key point on curve

240

- curve: Curve object (default NIST192p)

241

- hashfunc: hash function for signatures (default sha1)

242

- validate_point: bool, validate point is on curve

243

244

Returns:

245

VerifyingKey object

246

"""

247

248

@classmethod

249

def from_string(cls, string, curve=NIST192p, hashfunc=sha1, validate_point=True, valid_encodings=None):

250

"""

251

Create VerifyingKey from raw byte string.

252

253

Parameters:

254

- string: bytes, raw public key bytes

255

- curve: Curve object (default NIST192p)

256

- hashfunc: hash function for signatures (default sha1)

257

- validate_point: bool, validate point is on curve

258

- valid_encodings: list of acceptable point encodings or None

259

260

Returns:

261

VerifyingKey object

262

"""

263

264

@classmethod

265

def from_pem(cls, string, hashfunc=sha1, valid_encodings=None, valid_curve_encodings=None):

266

"""

267

Create VerifyingKey from PEM-encoded public key.

268

269

Parameters:

270

- string: str or bytes, PEM-encoded public key

271

- hashfunc: hash function for signatures (default sha1)

272

- valid_encodings: list of acceptable point encodings or None

273

- valid_curve_encodings: list of acceptable curve encodings or None

274

275

Returns:

276

VerifyingKey object

277

"""

278

279

@classmethod

280

def from_der(cls, string, hashfunc=sha1, valid_encodings=None, valid_curve_encodings=None):

281

"""

282

Create VerifyingKey from DER-encoded public key.

283

284

Parameters:

285

- string: bytes, DER-encoded public key

286

- hashfunc: hash function for signatures (default sha1)

287

- valid_encodings: list of acceptable point encodings or None

288

- valid_curve_encodings: list of acceptable curve encodings or None

289

290

Returns:

291

VerifyingKey object

292

"""

293

294

@classmethod

295

def from_public_key_recovery(cls, signature, data, curve, hashfunc=sha1, sigdecode=sigdecode_string, allow_truncate=True):

296

"""

297

Recover public key(s) from signature and original data.

298

299

Parameters:

300

- signature: bytes, encoded signature

301

- data: bytes, original signed data

302

- curve: Curve object

303

- hashfunc: hash function used for signing (default sha1)

304

- sigdecode: signature decoding function (default sigdecode_string)

305

- allow_truncate: bool, allow hash truncation for curve compatibility

306

307

Returns:

308

list[VerifyingKey], possible public keys (usually 2 or 4 options)

309

"""

310

311

@classmethod

312

def from_public_key_recovery_with_digest(cls, signature, digest, curve, hashfunc=sha1, sigdecode=sigdecode_string, allow_truncate=False):

313

"""

314

Recover public key(s) from signature and pre-computed digest.

315

316

Parameters:

317

- signature: bytes, encoded signature

318

- digest: bytes, hash digest of original data

319

- curve: Curve object

320

- hashfunc: hash function used to create digest (default sha1)

321

- sigdecode: signature decoding function (default sigdecode_string)

322

- allow_truncate: bool, allow hash truncation for curve compatibility

323

324

Returns:

325

list[VerifyingKey], possible public keys (usually 2 or 4 options)

326

"""

327

```

328

329

#### Signature Verification

330

331

```python { .api }

332

def verify(self, signature, data, hashfunc=None, sigdecode=sigdecode_string, allow_truncate=True):

333

"""

334

Verify signature against data.

335

336

Parameters:

337

- signature: bytes, encoded signature to verify

338

- data: bytes, original data that was signed

339

- hashfunc: hash function, or None for default

340

- sigdecode: signature decoding function (default sigdecode_string)

341

- allow_truncate: bool, allow hash truncation for curve compatibility

342

343

Returns:

344

bool, True if signature is valid

345

346

Raises:

347

BadSignatureError: if signature is invalid

348

"""

349

350

def verify_digest(self, signature, digest, sigdecode=sigdecode_string, allow_truncate=False):

351

"""

352

Verify signature against pre-computed hash digest.

353

354

Parameters:

355

- signature: bytes, encoded signature to verify

356

- digest: bytes, hash digest of original data

357

- sigdecode: signature decoding function (default sigdecode_string)

358

- allow_truncate: bool, allow hash truncation for curve compatibility

359

360

Returns:

361

bool, True if signature is valid

362

363

Raises:

364

BadSignatureError: if signature is invalid

365

"""

366

```

367

368

#### Key Export and Optimization

369

370

```python { .api }

371

def precompute(self, lazy=False):

372

"""

373

Precompute values for faster signature verification.

374

375

Parameters:

376

- lazy: bool, compute values lazily on first use

377

"""

378

379

def to_string(self, encoding="raw"):

380

"""

381

Export public key as raw bytes.

382

383

Parameters:

384

- encoding: str, point encoding format ("raw", "uncompressed", "compressed", "hybrid")

385

386

Returns:

387

bytes, encoded public key

388

"""

389

390

def to_pem(self, point_encoding="uncompressed", curve_parameters_encoding=None):

391

"""

392

Export public key in PEM format.

393

394

Parameters:

395

- point_encoding: str, point encoding format ("uncompressed", "compressed", "hybrid")

396

- curve_parameters_encoding: str or None, curve parameter encoding

397

398

Returns:

399

bytes, PEM-encoded public key

400

"""

401

402

def to_der(self, point_encoding="uncompressed", curve_parameters_encoding=None):

403

"""

404

Export public key in DER format.

405

406

Parameters:

407

- point_encoding: str, point encoding format ("uncompressed", "compressed", "hybrid")

408

- curve_parameters_encoding: str or None, curve parameter encoding

409

410

Returns:

411

bytes, DER-encoded public key

412

"""

413

414

def to_ssh(self):

415

"""

416

Export public key in SSH format.

417

418

Returns:

419

bytes, SSH-encoded public key

420

"""

421

```

422

423

#### Key Attributes

424

425

```python { .api }

426

curve: Curve # The elliptic curve object

427

default_hashfunc: callable # Default hash function

428

pubkey: object # Internal public key object

429

```

430

431

## Exception Classes

432

433

```python { .api }

434

class BadSignatureError(Exception):

435

"""Raised when signature verification fails."""

436

437

class BadDigestError(Exception):

438

"""Raised when hash digest is too large for the curve."""

439

440

class MalformedPointError(Exception):

441

"""Raised when point encoding is invalid or point is not on curve."""

442

```

443

444

## Usage Examples

445

446

### Basic Key Generation and Signing

447

448

```python

449

from ecdsa import SigningKey, NIST256p

450

import hashlib

451

452

# Generate a new signing key

453

sk = SigningKey.generate(curve=NIST256p)

454

vk = sk.verifying_key

455

456

# Sign some data

457

message = b"Hello, cryptographic world!"

458

signature = sk.sign(message, hashfunc=hashlib.sha256)

459

460

# Verify the signature

461

try:

462

vk.verify(signature, message, hashfunc=hashlib.sha256)

463

print("Signature verified successfully!")

464

except BadSignatureError:

465

print("Signature verification failed!")

466

```

467

468

### Deterministic Signatures (RFC 6979)

469

470

```python

471

from ecdsa import SigningKey, NIST256p

472

import hashlib

473

474

sk = SigningKey.generate(curve=NIST256p)

475

message = b"Deterministic signing example"

476

477

# Create deterministic signature (same signature every time)

478

sig1 = sk.sign_deterministic(message, hashfunc=hashlib.sha256)

479

sig2 = sk.sign_deterministic(message, hashfunc=hashlib.sha256)

480

assert sig1 == sig2 # Signatures are identical

481

482

# Verify deterministic signature

483

vk = sk.verifying_key

484

vk.verify(sig1, message, hashfunc=hashlib.sha256)

485

```

486

487

### Key Serialization and Loading

488

489

```python

490

from ecdsa import SigningKey, VerifyingKey, NIST256p

491

492

# Generate key pair

493

sk = SigningKey.generate(curve=NIST256p)

494

vk = sk.verifying_key

495

496

# Export keys in various formats

497

private_pem = sk.to_pem()

498

public_pem = vk.to_pem()

499

private_der = sk.to_der()

500

public_der = vk.to_der()

501

502

# Load keys from serialized formats

503

loaded_sk = SigningKey.from_pem(private_pem)

504

loaded_vk = VerifyingKey.from_pem(public_pem)

505

loaded_sk_der = SigningKey.from_der(private_der)

506

loaded_vk_der = VerifyingKey.from_der(public_der)

507

508

# Verify they work the same

509

message = b"Test message"

510

original_sig = sk.sign(message)

511

loaded_sig = loaded_sk.sign(message)

512

513

# Both signatures should verify with both public keys

514

vk.verify(original_sig, message)

515

loaded_vk.verify(loaded_sig, message)

516

```

517

518

### Multiple Signature Encodings

519

520

```python

521

from ecdsa import SigningKey, NIST256p

522

from ecdsa.util import sigencode_der, sigdecode_der, sigencode_string, sigdecode_string

523

524

sk = SigningKey.generate(curve=NIST256p)

525

vk = sk.verifying_key

526

message = b"Encoding example"

527

528

# Sign with different encodings

529

sig_raw = sk.sign(message, sigencode=sigencode_string)

530

sig_der = sk.sign(message, sigencode=sigencode_der)

531

532

# Verify with corresponding decodings

533

vk.verify(sig_raw, message, sigdecode=sigdecode_string)

534

vk.verify(sig_der, message, sigdecode=sigdecode_der)

535

```