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
```