0
# Digital Signatures
1
2
Signing and verification functions for multiple cryptographic schemes with automatic signature format detection. Supports sr25519, ed25519, secp256k1, and Ethereum-style signatures.
3
4
## Capabilities
5
6
### Sr25519 Signatures
7
8
Sr25519 signing and verification with support for Schnorr signatures and VRF.
9
10
```typescript { .api }
11
/**
12
* Sign a message using sr25519
13
* @param message - Message string or bytes to sign
14
* @param keypair - Keypair object with publicKey and secretKey
15
* @returns 64-byte signature
16
*/
17
function sr25519Sign(message: string | Uint8Array, keypair: Partial<Keypair>): Uint8Array;
18
19
/**
20
* Verify sr25519 signature
21
* @param message - Original message bytes
22
* @param signature - 64-byte signature to verify
23
* @param publicKey - 32-byte public key
24
* @returns true if signature is valid
25
*/
26
function sr25519Verify(message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean;
27
```
28
29
**Usage Example:**
30
31
```typescript
32
import { sr25519PairFromSeed, sr25519Sign, sr25519Verify } from "@polkadot/util-crypto";
33
34
const seed = new Uint8Array(32);
35
const pair = sr25519PairFromSeed(seed);
36
const message = new TextEncoder().encode("Hello Polkadot");
37
38
// Sign message
39
const signature = sr25519Sign(message, pair);
40
41
// Verify signature
42
const isValid = sr25519Verify(message, signature, pair.publicKey);
43
console.log("Signature valid:", isValid);
44
```
45
46
### Sr25519 VRF (Verifiable Random Functions)
47
48
VRF signing and verification for randomness generation with proof.
49
50
```typescript { .api }
51
/**
52
* Generate VRF signature and proof
53
* @param secretKey - 64-byte secret key
54
* @param context - Context bytes for VRF
55
* @param message - Message to sign
56
* @param extra - Optional extra randomness
57
* @returns VRF signature and proof
58
*/
59
function sr25519VrfSign(secretKey: Uint8Array, context: Uint8Array, message: Uint8Array, extra?: Uint8Array): Uint8Array;
60
61
/**
62
* Verify VRF signature and proof
63
* @param publicKey - 32-byte public key
64
* @param context - Context bytes for VRF
65
* @param message - Original message
66
* @param proof - VRF proof to verify
67
* @param extra - Optional extra randomness
68
* @returns true if VRF proof is valid
69
*/
70
function sr25519VrfVerify(publicKey: Uint8Array, context: Uint8Array, message: Uint8Array, proof: Uint8Array, extra?: Uint8Array): boolean;
71
```
72
73
### Ed25519 Signatures
74
75
Ed25519 signing and verification with deterministic signatures.
76
77
```typescript { .api }
78
/**
79
* Sign a message using ed25519
80
* @param publicKey - 32-byte public key
81
* @param secretKey - 32 or 64-byte secret key
82
* @param message - Message bytes to sign
83
* @returns 64-byte signature
84
*/
85
function ed25519Sign(publicKey: Uint8Array, secretKey: Uint8Array, message: Uint8Array): Uint8Array;
86
87
/**
88
* Verify ed25519 signature
89
* @param message - Original message bytes
90
* @param signature - 64-byte signature to verify
91
* @param publicKey - 32-byte public key
92
* @returns true if signature is valid
93
*/
94
function ed25519Verify(message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean;
95
```
96
97
**Usage Example:**
98
99
```typescript
100
import { ed25519PairFromSeed, ed25519Sign, ed25519Verify } from "@polkadot/util-crypto";
101
102
const seed = new Uint8Array(32);
103
const pair = ed25519PairFromSeed(seed);
104
const message = new TextEncoder().encode("Hello World");
105
106
// Sign message
107
const signature = ed25519Sign(pair.publicKey, pair.secretKey, message);
108
109
// Verify signature
110
const isValid = ed25519Verify(message, signature, pair.publicKey);
111
```
112
113
### Secp256k1 Signatures
114
115
Secp256k1 signing, verification, and public key recovery for Ethereum compatibility.
116
117
```typescript { .api }
118
/**
119
* Sign message hash using secp256k1
120
* @param msgHash - 32-byte message hash
121
* @param secretKey - 32-byte private key
122
* @returns Signature with recovery info
123
*/
124
function secp256k1Sign(msgHash: Uint8Array, secretKey: Uint8Array): Uint8Array;
125
126
/**
127
* Verify secp256k1 signature
128
* @param msgHash - 32-byte message hash
129
* @param signature - Signature bytes
130
* @param publicKey - Public key for verification
131
* @returns true if signature is valid
132
*/
133
function secp256k1Verify(msgHash: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean;
134
135
/**
136
* Recover public key from signature
137
* @param msgHash - 32-byte message hash
138
* @param signature - Signature bytes
139
* @param recovery - Recovery parameter (0-3)
140
* @returns Recovered public key
141
*/
142
function secp256k1Recover(msgHash: Uint8Array, signature: Uint8Array, recovery: number): Uint8Array;
143
144
/**
145
* Compress secp256k1 public key from uncompressed (65 bytes) to compressed (33 bytes)
146
* @param publicKey - Public key to compress (33 or 65 bytes)
147
* @param onlyJs - Force JavaScript implementation
148
* @returns Compressed public key (33 bytes)
149
*/
150
function secp256k1Compress(publicKey: Uint8Array, onlyJs?: boolean): Uint8Array;
151
152
/**
153
* Expand secp256k1 public key from compressed (33 bytes) to uncompressed coordinates (64 bytes)
154
* @param publicKey - Public key to expand (33 or 65 bytes)
155
* @param onlyJs - Force JavaScript implementation
156
* @returns Uncompressed public key coordinates (64 bytes, without 0x04 prefix)
157
*/
158
function secp256k1Expand(publicKey: Uint8Array, onlyJs?: boolean): Uint8Array;
159
160
/**
161
* Add a tweak to a secp256k1 private key
162
* @param seckey - Private key (32 bytes)
163
* @param tweak - Tweak value (32 bytes)
164
* @param onlyBn - Force BN.js implementation
165
* @returns Modified private key (32 bytes)
166
*/
167
function secp256k1PrivateKeyTweakAdd(seckey: Uint8Array, tweak: Uint8Array, onlyBn?: boolean): Uint8Array;
168
```
169
170
**Usage Example:**
171
172
```typescript
173
import {
174
secp256k1PairFromSeed,
175
secp256k1Sign,
176
secp256k1Verify,
177
secp256k1Recover,
178
secp256k1Compress,
179
secp256k1Expand,
180
secp256k1PrivateKeyTweakAdd,
181
keccak256AsU8a
182
} from "@polkadot/util-crypto";
183
184
const seed = new Uint8Array(32);
185
const pair = secp256k1PairFromSeed(seed);
186
const message = new TextEncoder().encode("Hello Ethereum");
187
const messageHash = keccak256AsU8a(message);
188
189
// Sign message hash
190
const signature = secp256k1Sign(messageHash, pair.secretKey);
191
192
// Verify signature
193
const isValid = secp256k1Verify(messageHash, signature, pair.publicKey);
194
195
// Recover public key
196
const recoveredKey = secp256k1Recover(messageHash, signature, 0);
197
198
// Compress public key
199
const compressedKey = secp256k1Compress(pair.publicKey);
200
201
// Expand compressed key to coordinates
202
const expandedKey = secp256k1Expand(compressedKey);
203
204
// Add tweak to private key
205
const tweak = new Uint8Array(32);
206
const tweakedPrivateKey = secp256k1PrivateKeyTweakAdd(pair.secretKey, tweak);
207
```
208
209
### Universal Signature Verification
210
211
Automatic detection and verification of different signature formats.
212
213
```typescript { .api }
214
/**
215
* Verify signature with automatic format detection
216
* @param message - Original message bytes
217
* @param signature - Signature in any supported format
218
* @param addressOrPublicKey - Address string or public key bytes
219
* @returns Verification result with details
220
*/
221
function signatureVerify(
222
message: Uint8Array,
223
signature: Uint8Array | string,
224
addressOrPublicKey: string | Uint8Array
225
): VerifyResult;
226
227
interface VerifyResult {
228
/** The detected crypto interface, or 'none' if not detected */
229
crypto: 'none' | KeypairType;
230
/** The validity for this result, false if invalid */
231
isValid: boolean;
232
/** Flag to indicate if the passed data was wrapped in <Bytes>...</Bytes> */
233
isWrapped: boolean;
234
/** The extracted publicKey */
235
publicKey: Uint8Array;
236
}
237
```
238
239
**Usage Example:**
240
241
```typescript
242
import { signatureVerify } from "@polkadot/util-crypto";
243
244
const message = new TextEncoder().encode("Test message");
245
const signature = "0x..."; // Any signature format
246
const address = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";
247
248
const result = signatureVerify(message, signature, address);
249
250
console.log("Crypto scheme:", result.crypto);
251
console.log("Is valid:", result.isValid);
252
console.log("Public key:", result.publicKey);
253
```
254
255
## Key Derivation and Signing
256
257
### Sr25519 Key Derivation
258
259
Hard and soft key derivation for hierarchical signing.
260
261
```typescript { .api }
262
/**
263
* Derive sr25519 public key (soft derivation)
264
* @param publicKey - Parent public key
265
* @param chainCode - Chain code for derivation
266
* @returns Derived public key
267
*/
268
function sr25519DerivePublic(publicKey: Uint8Array, chainCode: Uint8Array): Uint8Array;
269
270
/**
271
* Derive sr25519 key pair (soft derivation)
272
* @param pair - Parent key pair
273
* @param chainCode - Chain code for derivation
274
* @returns Derived key pair
275
*/
276
function sr25519DeriveSoft(pair: Keypair, chainCode: Uint8Array): Keypair;
277
278
/**
279
* Hard derivation for sr25519
280
* @param seed - Parent seed
281
* @param chainCode - Chain code for derivation
282
* @returns Derived seed
283
*/
284
function sr25519DeriveHard(seed: Uint8Array, chainCode: Uint8Array): Uint8Array;
285
286
/**
287
* Sr25519 Diffie-Hellman agreement
288
* @param publicKey - Other party's public key
289
* @param secretKey - Own secret key
290
* @returns Shared secret
291
*/
292
function sr25519Agreement(publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array;
293
```
294
295
### Ed25519 Key Derivation
296
297
```typescript { .api }
298
/**
299
* Hard derivation for ed25519
300
* @param seed - Parent seed
301
* @param chainCode - Chain code for derivation
302
* @returns Derived seed
303
*/
304
function ed25519DeriveHard(seed: Uint8Array, chainCode: Uint8Array): Uint8Array;
305
```
306
307
## Signature Format Notes
308
309
- **Sr25519**: 64-byte signatures, supports batch verification
310
- **Ed25519**: 64-byte deterministic signatures, very fast verification
311
- **Secp256k1**: Variable length with recovery, Ethereum-compatible
312
- **Multi-format**: `signatureVerify` handles automatic detection
313
314
## Security Considerations
315
316
- Always verify signatures before trusting signed data
317
- Use appropriate hash functions for each signature scheme
318
- Be careful with signature malleability in secp256k1
319
- VRF provides both signature and verifiable randomness
320
- Store private keys securely and never reuse nonces