or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aead.mdauth.mdbox.mded25519.mdhash.mdindex.mdkdf.mdkx.mdmemory.mdpwhash.mdrandom.mdsecretbox.mdsecretstream.mdshorthash.mdsign.mdstream.md

sign.mddocs/

0

# Digital Signatures

1

2

Ed25519 digital signatures for message authentication, integrity verification, and non-repudiation.

3

4

## Capabilities

5

6

### Key Pair Generation

7

8

Generates a random Ed25519 key pair for digital signatures.

9

10

```javascript { .api }

11

/**

12

* Generate random Ed25519 signing key pair

13

* @param pk - Output buffer for public key (must be PUBLICKEYBYTES long)

14

* @param sk - Output buffer for secret key (must be SECRETKEYBYTES long)

15

* @throws Error if buffer sizes are incorrect or generation fails

16

*/

17

function crypto_sign_keypair(pk: Buffer, sk: Buffer): void;

18

```

19

20

### Seed-based Key Pair Generation

21

22

Generates a deterministic Ed25519 key pair from a seed.

23

24

```javascript { .api }

25

/**

26

* Generate Ed25519 key pair from seed

27

* @param pk - Output buffer for public key (must be PUBLICKEYBYTES long)

28

* @param sk - Output buffer for secret key (must be SECRETKEYBYTES long)

29

* @param seed - Seed buffer (must be SEEDBYTES long)

30

* @throws Error if buffer sizes are incorrect or generation fails

31

*/

32

function crypto_sign_seed_keypair(pk: Buffer, sk: Buffer, seed: Buffer): void;

33

```

34

35

**Usage Example:**

36

37

```javascript

38

const sodium = require('sodium-native');

39

40

// Generate signing key pair

41

const publicKey = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES);

42

const secretKey = Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES);

43

sodium.crypto_sign_keypair(publicKey, secretKey);

44

45

// Or generate from seed for reproducible keys

46

const seed = Buffer.alloc(sodium.crypto_sign_SEEDBYTES);

47

sodium.randombytes_buf(seed);

48

sodium.crypto_sign_seed_keypair(publicKey, secretKey, seed);

49

```

50

51

### Combined Mode Signing

52

53

Signs a message and combines it with the signature.

54

55

```javascript { .api }

56

/**

57

* Sign message and combine with signature

58

* @param sm - Output buffer for signed message (must be m.length + BYTES)

59

* @param m - Message buffer to sign

60

* @param sk - Secret key buffer (must be SECRETKEYBYTES long)

61

* @throws Error if buffer sizes are incorrect or signing fails

62

*/

63

function crypto_sign(sm: Buffer, m: Buffer, sk: Buffer): void;

64

```

65

66

### Combined Mode Verification

67

68

Verifies a signed message and extracts the original message.

69

70

```javascript { .api }

71

/**

72

* Verify signed message and extract original message

73

* @param m - Output buffer for original message (must be sm.length - BYTES)

74

* @param sm - Signed message buffer to verify

75

* @param pk - Public key buffer (must be PUBLICKEYBYTES long)

76

* @returns true if verification successful, false if signature invalid

77

* @throws Error if buffer sizes are incorrect

78

*/

79

function crypto_sign_open(m: Buffer, sm: Buffer, pk: Buffer): boolean;

80

```

81

82

**Usage Example:**

83

84

```javascript

85

const sodium = require('sodium-native');

86

87

// Sign a message (combined mode)

88

const message = Buffer.from('Important message');

89

const signedMessage = Buffer.alloc(message.length + sodium.crypto_sign_BYTES);

90

sodium.crypto_sign(signedMessage, message, secretKey);

91

92

// Verify and extract message

93

const extractedMessage = Buffer.alloc(signedMessage.length - sodium.crypto_sign_BYTES);

94

if (sodium.crypto_sign_open(extractedMessage, signedMessage, publicKey)) {

95

console.log('Verified message:', extractedMessage.toString());

96

} else {

97

console.log('Invalid signature');

98

}

99

```

100

101

### Detached Mode Signing

102

103

Creates a signature that is stored separately from the message.

104

105

```javascript { .api }

106

/**

107

* Create detached signature for message

108

* @param sig - Output buffer for signature (must be BYTES long)

109

* @param m - Message buffer to sign

110

* @param sk - Secret key buffer (must be SECRETKEYBYTES long)

111

* @throws Error if buffer sizes are incorrect or signing fails

112

*/

113

function crypto_sign_detached(sig: Buffer, m: Buffer, sk: Buffer): void;

114

```

115

116

### Detached Mode Verification

117

118

Verifies a detached signature against a message.

119

120

```javascript { .api }

121

/**

122

* Verify detached signature against message

123

* @param sig - Signature buffer to verify (must be BYTES long)

124

* @param m - Message buffer that was signed

125

* @param pk - Public key buffer (must be PUBLICKEYBYTES long)

126

* @returns true if signature is valid, false otherwise

127

*/

128

function crypto_sign_verify_detached(sig: Buffer, m: Buffer, pk: Buffer): boolean;

129

```

130

131

**Usage Example:**

132

133

```javascript

134

const sodium = require('sodium-native');

135

136

// Create detached signature

137

const message = Buffer.from('Document to sign');

138

const signature = Buffer.alloc(sodium.crypto_sign_BYTES);

139

sodium.crypto_sign_detached(signature, message, secretKey);

140

141

// Verify detached signature

142

if (sodium.crypto_sign_verify_detached(signature, message, publicKey)) {

143

console.log('Signature is valid');

144

} else {

145

console.log('Invalid signature');

146

}

147

```

148

149

### Key Conversion Functions

150

151

Extract public key from secret key and convert between Ed25519 and Curve25519 keys.

152

153

```javascript { .api }

154

/**

155

* Extract public key from Ed25519 secret key

156

* @param pk - Output buffer for public key (must be PUBLICKEYBYTES long)

157

* @param sk - Secret key buffer (must be SECRETKEYBYTES long)

158

* @throws Error if buffer sizes are incorrect or extraction fails

159

*/

160

function crypto_sign_ed25519_sk_to_pk(pk: Buffer, sk: Buffer): void;

161

162

/**

163

* Convert Ed25519 public key to Curve25519 public key

164

* @param x25519pk - Output buffer for Curve25519 public key

165

* @param ed25519pk - Ed25519 public key to convert

166

* @throws Error if conversion fails or buffer sizes incorrect

167

*/

168

function crypto_sign_ed25519_pk_to_curve25519(x25519pk: Buffer, ed25519pk: Buffer): void;

169

170

/**

171

* Convert Ed25519 secret key to Curve25519 secret key

172

* @param x25519sk - Output buffer for Curve25519 secret key

173

* @param ed25519sk - Ed25519 secret key to convert

174

* @throws Error if conversion fails or buffer sizes incorrect

175

*/

176

function crypto_sign_ed25519_sk_to_curve25519(x25519sk: Buffer, ed25519sk: Buffer): void;

177

```

178

179

**Usage Example:**

180

181

```javascript

182

const sodium = require('sodium-native');

183

184

// Extract public key from secret key

185

const derivedPublicKey = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES);

186

sodium.crypto_sign_ed25519_sk_to_pk(derivedPublicKey, secretKey);

187

188

// Convert Ed25519 keys to Curve25519 for encryption

189

const curve25519PublicKey = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES);

190

const curve25519SecretKey = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES);

191

192

sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519PublicKey, publicKey);

193

sodium.crypto_sign_ed25519_sk_to_curve25519(curve25519SecretKey, secretKey);

194

```

195

196

## Constants

197

198

```javascript { .api }

199

// Seed size for deterministic key generation

200

const crypto_sign_SEEDBYTES: number;

201

202

// Public key size in bytes

203

const crypto_sign_PUBLICKEYBYTES: number;

204

205

// Secret key size in bytes

206

const crypto_sign_SECRETKEYBYTES: number;

207

208

// Signature size in bytes

209

const crypto_sign_BYTES: number;

210

```

211

212

## Security Considerations

213

214

- **Key Security**: Keep secret keys secure and use `sodium_malloc()` for storage.

215

- **Message Integrity**: Signatures provide both authentication and integrity verification.

216

- **Non-repudiation**: Valid signatures prove the signer possessed the secret key.

217

- **Deterministic**: Ed25519 signatures are deterministic - same message and key produce same signature.

218

219

## Common Patterns

220

221

### Document Signing Service

222

223

```javascript

224

const sodium = require('sodium-native');

225

226

class DocumentSigner {

227

constructor() {

228

this.publicKey = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES);

229

this.secretKey = Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES);

230

sodium.crypto_sign_keypair(this.publicKey, this.secretKey);

231

}

232

233

signDocument(document) {

234

const signature = Buffer.alloc(sodium.crypto_sign_BYTES);

235

sodium.crypto_sign_detached(signature, document, this.secretKey);

236

237

return {

238

document: document,

239

signature: signature,

240

publicKey: this.publicKey

241

};

242

}

243

244

static verifyDocument(signedDoc) {

245

return sodium.crypto_sign_verify_detached(

246

signedDoc.signature,

247

signedDoc.document,

248

signedDoc.publicKey

249

);

250

}

251

}

252

253

// Usage

254

const signer = new DocumentSigner();

255

const document = Buffer.from('Important contract text');

256

const signed = signer.signDocument(document);

257

258

if (DocumentSigner.verifyDocument(signed)) {

259

console.log('Document signature is valid');

260

}

261

```

262

263

### Multi-signature Verification

264

265

```javascript

266

const sodium = require('sodium-native');

267

268

class MultiSigVerifier {

269

constructor() {

270

this.signers = new Map();

271

}

272

273

addSigner(name, publicKey) {

274

this.signers.set(name, publicKey);

275

}

276

277

verifySignatures(document, signatures) {

278

const results = new Map();

279

280

for (const [signerName, signature] of signatures) {

281

const publicKey = this.signers.get(signerName);

282

if (publicKey) {

283

const isValid = sodium.crypto_sign_verify_detached(

284

signature,

285

document,

286

publicKey

287

);

288

results.set(signerName, isValid);

289

}

290

}

291

292

return results;

293

}

294

295

requireMinimumSignatures(document, signatures, minRequired) {

296

const results = this.verifySignatures(document, signatures);

297

const validCount = Array.from(results.values()).filter(valid => valid).length;

298

return validCount >= minRequired;

299

}

300

}

301

```