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

key-derivation.mddocs/

0

# Key Derivation Functions

1

2

Password-based key derivation functions for generating cryptographic keys from passwords and salts, including PBKDF2 and Scrypt algorithms.

3

4

## Capabilities

5

6

### PBKDF2 Key Derivation

7

8

Password-Based Key Derivation Function 2 (PBKDF2) for deriving cryptographic keys from passwords.

9

10

```typescript { .api }

11

/**

12

* Derives key using PBKDF2

13

* @param data - Password data as Uint8Array

14

* @param salt - Salt as Uint8Array (recommended: at least 16 bytes)

15

* @param rounds - Number of iterations (recommended: at least 10,000)

16

* @returns 64-byte derived key as Uint8Array

17

*/

18

function pbkdf2(data: Uint8Array, salt: Uint8Array, rounds: number): Uint8Array;

19

```

20

21

**Usage Example:**

22

23

```typescript

24

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

25

26

await waitReady();

27

28

const password = new TextEncoder().encode("my-secure-password");

29

const salt = new Uint8Array(16);

30

crypto.getRandomValues(salt); // Generate random salt

31

32

// Derive key with different iteration counts

33

const key10k = pbkdf2(password, salt, 10000);

34

const key100k = pbkdf2(password, salt, 100000);

35

36

console.log("PBKDF2 key length:", key10k.length); // 64

37

console.log("Keys are different:",

38

Array.from(key10k).join(',') !== Array.from(key100k).join(',')

39

); // true

40

```

41

42

### Scrypt Key Derivation

43

44

Scrypt key derivation function designed to be memory-hard and resist hardware attacks.

45

46

```typescript { .api }

47

/**

48

* Derives key using Scrypt

49

* @param password - Password as Uint8Array

50

* @param salt - Salt as Uint8Array (recommended: at least 16 bytes)

51

* @param log2n - CPU/memory cost parameter (power of 2, e.g., 14 = 2^14 = 16384)

52

* @param r - Block size parameter (typically 8)

53

* @param p - Parallelization parameter (typically 1)

54

* @returns 64-byte derived key as Uint8Array

55

*/

56

function scrypt(password: Uint8Array, salt: Uint8Array, log2n: number, r: number, p: number): Uint8Array;

57

```

58

59

**Usage Example:**

60

61

```typescript

62

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

63

64

await waitReady();

65

66

const password = new TextEncoder().encode("my-secure-password");

67

const salt = new Uint8Array(16);

68

crypto.getRandomValues(salt); // Generate random salt

69

70

// Common Scrypt parameters

71

const log2n = 14; // N = 2^14 = 16384 (memory cost)

72

const r = 8; // Block size

73

const p = 1; // Parallelization

74

75

const derivedKey = scrypt(password, salt, log2n, r, p);

76

77

console.log("Scrypt key length:", derivedKey.length); // 64

78

```

79

80

## Parameter Guidelines

81

82

### PBKDF2 Parameters

83

84

- **Rounds**: Minimum 10,000, recommended 100,000+ for high security

85

- **Salt**: At least 16 bytes, preferably 32 bytes of random data

86

- **Output**: Always 64 bytes

87

88

### Scrypt Parameters

89

90

- **log2n**: Common values are 12-16 (N = 4096-65536)

91

- 12: Low security, fast (N = 4096)

92

- 14: Medium security (N = 16384) - good default

93

- 16: High security, slower (N = 65536)

94

- **r**: Usually 8 (block size parameter)

95

- **p**: Usually 1 (parallelization parameter)

96

- **Salt**: At least 16 bytes, preferably 32 bytes of random data

97

- **Output**: Always 64 bytes

98

99

## Security Considerations

100

101

```typescript

102

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

103

104

async function demonstrateSecureKeyDerivation() {

105

await waitReady();

106

107

const password = new TextEncoder().encode("user-password");

108

109

// Generate cryptographically secure salt

110

const salt = new Uint8Array(32);

111

crypto.getRandomValues(salt);

112

113

// PBKDF2 with high iteration count

114

const pbkdf2Key = pbkdf2(password, salt, 100000);

115

116

// Scrypt with recommended parameters

117

const scryptKey = scrypt(password, salt, 14, 8, 1);

118

119

// Store salt alongside derived key for later verification

120

const storedData = {

121

salt: Array.from(salt),

122

pbkdf2Key: Array.from(pbkdf2Key),

123

scryptKey: Array.from(scryptKey)

124

};

125

126

console.log("Salt length:", salt.length); // 32

127

console.log("Both keys derived successfully");

128

129

return storedData;

130

}

131

132

demonstrateSecureKeyDerivation();

133

```

134

135

## Performance Comparison

136

137

```typescript

138

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

139

140

async function compareKeyDerivationPerformance() {

141

await waitReady();

142

143

const password = new TextEncoder().encode("test-password");

144

const salt = new Uint8Array(32).fill(1); // Fixed salt for consistent timing

145

146

// Time PBKDF2

147

console.time("PBKDF2 (100k iterations)");

148

const pbkdf2Key = pbkdf2(password, salt, 100000);

149

console.timeEnd("PBKDF2 (100k iterations)");

150

151

// Time Scrypt

152

console.time("Scrypt (N=16384, r=8, p=1)");

153

const scryptKey = scrypt(password, salt, 14, 8, 1);

154

console.timeEnd("Scrypt (N=16384, r=8, p=1)");

155

156

console.log("PBKDF2 result length:", pbkdf2Key.length); // 64

157

console.log("Scrypt result length:", scryptKey.length); // 64

158

159

return { pbkdf2Key, scryptKey };

160

}

161

162

compareKeyDerivationPerformance();

163

```

164

165

## Complete Key Derivation Workflow

166

167

```typescript

168

import { waitReady, pbkdf2, scrypt, hmacSha256 } from "@polkadot/wasm-crypto";

169

170

async function demonstrateKeyDerivationWorkflow() {

171

await waitReady();

172

173

// Simulate user registration

174

const userPassword = "user-secure-password-123";

175

const passwordBytes = new TextEncoder().encode(userPassword);

176

177

// Generate unique salt for this user

178

const userSalt = new Uint8Array(32);

179

crypto.getRandomValues(userSalt);

180

181

// Derive master key using Scrypt (more secure for password storage)

182

const masterKey = scrypt(passwordBytes, userSalt, 14, 8, 1);

183

184

// Derive application-specific keys using HMAC

185

const encryptionKey = hmacSha256(masterKey, new TextEncoder().encode("encryption"));

186

const authKey = hmacSha256(masterKey, new TextEncoder().encode("authentication"));

187

188

// For comparison, also show PBKDF2 derivation

189

const pbkdf2MasterKey = pbkdf2(passwordBytes, userSalt, 100000);

190

191

console.log("User salt:", Array.from(userSalt.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));

192

console.log("Scrypt master key:", Array.from(masterKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));

193

console.log("PBKDF2 master key:", Array.from(pbkdf2MasterKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));

194

console.log("Encryption key:", Array.from(encryptionKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));

195

console.log("Auth key:", Array.from(authKey.slice(0, 8)).map(b => b.toString(16).padStart(2, '0')).join(''));

196

197

return {

198

userSalt,

199

masterKey,

200

pbkdf2MasterKey,

201

encryptionKey,

202

authKey

203

};

204

}

205

206

demonstrateKeyDerivationWorkflow();

207

```