or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bip39.mded25519.mdhashing.mdindex.mdkey-derivation.mdsecp256k1.mdsr25519.mdvrf.md

secp256k1.mddocs/

0

# Secp256k1 ECDSA Operations

1

2

Secp256k1 elliptic curve cryptography functions including key generation, signing, signature recovery, and public key compression/expansion operations. This is the same curve used by Bitcoin and Ethereum.

3

4

## Capabilities

5

6

### Generate Keypair from Seed

7

8

Generates a secp256k1 keypair from a secret key seed.

9

10

```typescript { .api }

11

/**

12

* Generates secp256k1 keypair from secret key

13

* @param seckey - 32-byte secret key as Uint8Array

14

* @returns 64-byte uncompressed public key as Uint8Array

15

*/

16

function secp256k1FromSeed(seckey: Uint8Array): Uint8Array;

17

```

18

19

**Usage Example:**

20

21

```typescript

22

import { waitReady, secp256k1FromSeed } from "@polkadot/wasm-crypto";

23

24

await waitReady();

25

26

const secretKey = new Uint8Array(32).fill(1); // Example secret key

27

const publicKey = secp256k1FromSeed(secretKey);

28

29

console.log("Secret key length:", secretKey.length); // 32

30

console.log("Public key length:", publicKey.length); // 64 (uncompressed)

31

```

32

33

### Sign Message Hash

34

35

Signs a message hash using secp256k1 ECDSA.

36

37

```typescript { .api }

38

/**

39

* Signs a message hash using secp256k1 ECDSA

40

* @param msgHash - 32-byte message hash as Uint8Array

41

* @param seckey - 32-byte secret key as Uint8Array

42

* @returns 65-byte signature as Uint8Array (64-byte signature + 1-byte recovery ID)

43

*/

44

function secp256k1Sign(msgHash: Uint8Array, seckey: Uint8Array): Uint8Array;

45

```

46

47

**Usage Example:**

48

49

```typescript

50

import { waitReady, secp256k1FromSeed, secp256k1Sign, sha256 } from "@polkadot/wasm-crypto";

51

52

await waitReady();

53

54

const secretKey = new Uint8Array(32).fill(1);

55

const publicKey = secp256k1FromSeed(secretKey);

56

57

// Hash the message first

58

const message = new TextEncoder().encode("Hello, secp256k1!");

59

const messageHash = sha256(message);

60

61

const signature = secp256k1Sign(messageHash, secretKey);

62

console.log("Signature length:", signature.length); // 65

63

```

64

65

### Recover Public Key from Signature

66

67

Recovers the public key from a secp256k1 signature and message hash.

68

69

```typescript { .api }

70

/**

71

* Recovers public key from secp256k1 signature

72

* @param msgHash - 32-byte message hash as Uint8Array

73

* @param sig - 64-byte signature as Uint8Array (without recovery ID)

74

* @param recovery - Recovery ID (0, 1, 2, or 3)

75

* @returns 64-byte uncompressed public key as Uint8Array

76

*/

77

function secp256k1Recover(msgHash: Uint8Array, sig: Uint8Array, recovery: number): Uint8Array;

78

```

79

80

**Usage Example:**

81

82

```typescript

83

import {

84

waitReady,

85

secp256k1FromSeed,

86

secp256k1Sign,

87

secp256k1Recover,

88

sha256

89

} from "@polkadot/wasm-crypto";

90

91

await waitReady();

92

93

const secretKey = new Uint8Array(32).fill(1);

94

const originalPublicKey = secp256k1FromSeed(secretKey);

95

96

const message = new TextEncoder().encode("Hello, secp256k1!");

97

const messageHash = sha256(message);

98

99

const fullSignature = secp256k1Sign(messageHash, secretKey);

100

const signature = fullSignature.slice(0, 64); // Remove recovery ID

101

const recoveryId = fullSignature[64]; // Extract recovery ID

102

103

const recoveredPublicKey = secp256k1Recover(messageHash, signature, recoveryId);

104

105

// Compare original and recovered public keys

106

const keysMatch = Array.from(originalPublicKey).join(',') ===

107

Array.from(recoveredPublicKey).join(',');

108

console.log("Keys match:", keysMatch); // true

109

```

110

111

### Compress Public Key

112

113

Compresses a secp256k1 public key from 64 bytes to 33 bytes.

114

115

```typescript { .api }

116

/**

117

* Compresses secp256k1 public key

118

* @param pubkey - 64-byte uncompressed public key as Uint8Array

119

* @returns 33-byte compressed public key as Uint8Array

120

*/

121

function secp256k1Compress(pubkey: Uint8Array): Uint8Array;

122

```

123

124

**Usage Example:**

125

126

```typescript

127

import { waitReady, secp256k1FromSeed, secp256k1Compress } from "@polkadot/wasm-crypto";

128

129

await waitReady();

130

131

const secretKey = new Uint8Array(32).fill(1);

132

const uncompressedPublicKey = secp256k1FromSeed(secretKey);

133

const compressedPublicKey = secp256k1Compress(uncompressedPublicKey);

134

135

console.log("Uncompressed length:", uncompressedPublicKey.length); // 64

136

console.log("Compressed length:", compressedPublicKey.length); // 33

137

```

138

139

### Expand Public Key

140

141

Expands a compressed secp256k1 public key from 33 bytes to 64 bytes.

142

143

```typescript { .api }

144

/**

145

* Expands compressed secp256k1 public key

146

* @param pubkey - 33-byte compressed public key as Uint8Array

147

* @returns 64-byte uncompressed public key as Uint8Array

148

*/

149

function secp256k1Expand(pubkey: Uint8Array): Uint8Array;

150

```

151

152

**Usage Example:**

153

154

```typescript

155

import {

156

waitReady,

157

secp256k1FromSeed,

158

secp256k1Compress,

159

secp256k1Expand

160

} from "@polkadot/wasm-crypto";

161

162

await waitReady();

163

164

const secretKey = new Uint8Array(32).fill(1);

165

const originalPublicKey = secp256k1FromSeed(secretKey);

166

167

// Compress then expand

168

const compressedPublicKey = secp256k1Compress(originalPublicKey);

169

const expandedPublicKey = secp256k1Expand(compressedPublicKey);

170

171

// Keys should match after compression/expansion cycle

172

const keysMatch = Array.from(originalPublicKey).join(',') ===

173

Array.from(expandedPublicKey).join(',');

174

console.log("Compression/expansion cycle preserves key:", keysMatch); // true

175

```

176

177

## Complete Secp256k1 Workflow

178

179

```typescript

180

import {

181

waitReady,

182

secp256k1FromSeed,

183

secp256k1Sign,

184

secp256k1Recover,

185

secp256k1Compress,

186

secp256k1Expand,

187

sha256

188

} from "@polkadot/wasm-crypto";

189

190

async function demonstrateSecp256k1() {

191

await waitReady();

192

193

// Generate keypair

194

const secretKey = new Uint8Array(32);

195

crypto.getRandomValues(secretKey); // Use random secret in production

196

197

const publicKey = secp256k1FromSeed(secretKey);

198

199

// Test compression/expansion

200

const compressedPubKey = secp256k1Compress(publicKey);

201

const expandedPubKey = secp256k1Expand(compressedPubKey);

202

203

console.log("Compression/expansion works:",

204

Array.from(publicKey).join(',') === Array.from(expandedPubKey).join(',')

205

);

206

207

// Sign and recover

208

const message = new TextEncoder().encode("Test message for secp256k1");

209

const messageHash = sha256(message);

210

211

const fullSignature = secp256k1Sign(messageHash, secretKey);

212

const signature = fullSignature.slice(0, 64);

213

const recoveryId = fullSignature[64];

214

215

const recoveredPubKey = secp256k1Recover(messageHash, signature, recoveryId);

216

217

console.log("Key recovery works:",

218

Array.from(publicKey).join(',') === Array.from(recoveredPubKey).join(',')

219

);

220

221

return {

222

secretKey,

223

publicKey,

224

compressedPubKey,

225

signature,

226

recoveredPubKey

227

};

228

}

229

230

demonstrateSecp256k1();

231

```