or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

big-number-arithmetic.mdbit-array-utilities.mdcipher-modes.mddata-encoding.mdelliptic-curve-cryptography.mdhash-functions.mdhigh-level-encryption.mdindex.mdkey-derivation.mdkey-exchange.mdmessage-authentication.mdrandom-number-generation.mdsymmetric-encryption.md

key-derivation.mddocs/

0

# Key Derivation

1

2

SJCL provides multiple key derivation functions (KDFs) for converting passwords and other input material into cryptographic keys. These functions include PBKDF2, scrypt, and HKDF, each suited for different security requirements.

3

4

## Capabilities

5

6

### PBKDF2 (Password-Based Key Derivation Function 2)

7

8

The most commonly used password-based key derivation function, applying HMAC iteratively to derive keys from passwords.

9

10

```javascript { .api }

11

/**

12

* PBKDF2 key derivation function

13

* @param {string|BitArray} password - Password or key material

14

* @param {BitArray} salt - Random salt (recommended: at least 8 bytes)

15

* @param {number} count - Number of iterations (recommended: ≥10,000)

16

* @param {number} length - Desired key length in bits

17

* @param {Function} [Prff] - Pseudorandom function (default: HMAC-SHA256)

18

* @returns {BitArray} Derived key as bit array

19

* @throws {sjcl.exception.invalid} If parameters are invalid

20

*/

21

sjcl.misc.pbkdf2(password, salt, count, length, Prff);

22

```

23

24

**Usage Examples:**

25

26

```javascript

27

const sjcl = require('sjcl');

28

29

// Basic PBKDF2 key derivation

30

const password = "userPassword123";

31

const salt = sjcl.random.randomWords(4); // 16 bytes

32

const iterations = 100000; // High iteration count for security

33

const keyLength = 256; // 256-bit key

34

35

const derivedKey = sjcl.misc.pbkdf2(password, salt, iterations, keyLength);

36

const aes = new sjcl.cipher.aes(derivedKey);

37

38

// Using different hash functions

39

const derivedKeySHA1 = sjcl.misc.pbkdf2(

40

password,

41

salt,

42

iterations,

43

keyLength,

44

sjcl.misc.hmac.prototype.encrypt // Uses HMAC-SHA1

45

);

46

47

// Derive multiple keys from same password

48

function deriveKeys(password, salt, iterations) {

49

return {

50

encryptionKey: sjcl.misc.pbkdf2(password, salt, iterations, 256),

51

authKey: sjcl.misc.pbkdf2(password + "auth", salt, iterations, 256),

52

iv: sjcl.misc.pbkdf2(password + "iv", salt, iterations, 128)

53

};

54

}

55

56

const keys = deriveKeys("masterPassword", salt, 100000);

57

```

58

59

### scrypt

60

61

Memory-hard key derivation function designed to be resistant to hardware-based attacks by requiring significant memory usage.

62

63

```javascript { .api }

64

/**

65

* scrypt key derivation function

66

* @param {string|BitArray} password - Password or key material

67

* @param {BitArray} salt - Random salt

68

* @param {number} N - CPU/memory cost parameter (power of 2)

69

* @param {number} r - Block size parameter

70

* @param {number} p - Parallelization parameter

71

* @param {number} length - Desired key length in bits

72

* @param {Function} [Prff] - Pseudorandom function (default: HMAC-SHA256)

73

* @returns {BitArray} Derived key as bit array

74

* @throws {sjcl.exception.invalid} If parameters are invalid

75

*/

76

sjcl.misc.scrypt(password, salt, N, r, p, length, Prff);

77

```

78

79

**Usage Examples:**

80

81

```javascript

82

const sjcl = require('sjcl');

83

84

// Basic scrypt usage

85

const password = "strongPassword";

86

const salt = sjcl.random.randomWords(4);

87

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

88

const r = 8; // Block size

89

const p = 1; // Parallelization

90

const keyLength = 256;

91

92

const scryptKey = sjcl.misc.scrypt(password, salt, N, r, p, keyLength);

93

94

// Higher security settings (more memory/time intensive)

95

const secureKey = sjcl.misc.scrypt(

96

password,

97

salt,

98

32768, // N = 2^15 (more memory)

99

8, // r = 8

100

1, // p = 1

101

256 // 256-bit key

102

);

103

104

// Lighter settings for mobile/resource-constrained environments

105

const mobileKey = sjcl.misc.scrypt(

106

password,

107

salt,

108

4096, // N = 2^12 (less memory)

109

8, // r = 8

110

1, // p = 1

111

256 // 256-bit key

112

);

113

```

114

115

### HKDF (HMAC-based Key Derivation Function)

116

117

Key derivation function for expanding existing key material into multiple cryptographic keys.

118

119

```javascript { .api }

120

/**

121

* HKDF key derivation function

122

* @param {BitArray} ikm - Input key material (should have good entropy)

123

* @param {number} keyBitLength - Desired output key length in bits

124

* @param {BitArray} [salt] - Optional salt (if not provided, zero salt is used)

125

* @param {BitArray} [info] - Optional context/application info

126

* @param {Function} [Hash] - Hash function to use (default: SHA-256)

127

* @returns {BitArray} Derived key as bit array

128

* @throws {sjcl.exception.invalid} If parameters are invalid

129

*/

130

sjcl.misc.hkdf(ikm, keyBitLength, salt, info, Hash);

131

```

132

133

**Usage Examples:**

134

135

```javascript

136

const sjcl = require('sjcl');

137

138

// Basic HKDF usage

139

const inputKeyMaterial = sjcl.random.randomWords(8); // 256 bits of random data

140

const salt = sjcl.random.randomWords(4); // Optional salt

141

const info = sjcl.codec.utf8String.toBits("MyApp-EncryptionKey-v1");

142

143

const derivedKey = sjcl.misc.hkdf(inputKeyMaterial, 256, salt, info);

144

145

// Derive multiple keys from shared secret

146

function deriveMultipleKeys(sharedSecret) {

147

const salt = sjcl.random.randomWords(4);

148

149

return {

150

encKey: sjcl.misc.hkdf(

151

sharedSecret,

152

256,

153

salt,

154

sjcl.codec.utf8String.toBits("encryption")

155

),

156

macKey: sjcl.misc.hkdf(

157

sharedSecret,

158

256,

159

salt,

160

sjcl.codec.utf8String.toBits("authentication")

161

),

162

kdfKey: sjcl.misc.hkdf(

163

sharedSecret,

164

256,

165

salt,

166

sjcl.codec.utf8String.toBits("key-derivation")

167

)

168

};

169

}

170

171

// HKDF with different hash functions

172

const hkdfSHA512 = sjcl.misc.hkdf(

173

inputKeyMaterial,

174

512,

175

salt,

176

info,

177

sjcl.hash.sha512

178

);

179

```

180

181

## Cached PBKDF2

182

183

Optimized PBKDF2 implementation with automatic salt generation and caching capabilities.

184

185

```javascript { .api }

186

/**

187

* Cached PBKDF2 with automatic salt generation

188

* @param {string} password - Password for key derivation

189

* @param {Object} obj - Object containing salt and other parameters

190

* @returns {BitArray} Derived key as bit array

191

*/

192

sjcl.misc.cachedPbkdf2(password, obj);

193

```

194

195

**Usage Examples:**

196

197

```javascript

198

const sjcl = require('sjcl');

199

200

// Using cached PBKDF2

201

const password = "userPassword";

202

const params = {

203

salt: sjcl.random.randomWords(4),

204

iter: 100000

205

};

206

207

const cachedKey = sjcl.misc.cachedPbkdf2(password, params);

208

209

// The params object will be modified with additional metadata

210

console.log(params); // Contains salt, iter, and derived key info

211

```

212

213

## Security Recommendations

214

215

### PBKDF2

216

- **Minimum iterations**: 10,000 (preferably 100,000+)

217

- **Salt length**: At least 128 bits (4 words)

218

- **Unique salts**: Generate new salt for each password

219

- **Memory considerations**: PBKDF2 is not memory-hard

220

221

### scrypt

222

- **Parameter selection**: Balance security vs. performance

223

- **N parameter**: Should be power of 2, start with 16384

224

- **Memory usage**: N * r * 128 bytes

225

- **Mobile devices**: Use lower N values (4096-8192)

226

227

### HKDF

228

- **Input entropy**: Ensure IKM has sufficient entropy

229

- **Context separation**: Use different info for different purposes

230

- **Salt usage**: Optional but recommended for security

231

- **Key expansion**: Can generate multiple keys from one input

232

233

## Common Usage Patterns

234

235

### Password-to-Key Conversion

236

237

```javascript

238

const sjcl = require('sjcl');

239

240

function passwordToKey(password, options = {}) {

241

const salt = options.salt || sjcl.random.randomWords(4);

242

const iterations = options.iterations || 100000;

243

const keySize = options.keySize || 256;

244

245

// Use scrypt for higher security, PBKDF2 for compatibility

246

const useScrypt = options.useScrypt !== false;

247

248

let key;

249

if (useScrypt) {

250

const N = options.scryptN || 16384;

251

key = sjcl.misc.scrypt(password, salt, N, 8, 1, keySize);

252

} else {

253

key = sjcl.misc.pbkdf2(password, salt, iterations, keySize);

254

}

255

256

return {

257

key: key,

258

salt: salt,

259

iterations: iterations,

260

algorithm: useScrypt ? 'scrypt' : 'pbkdf2'

261

};

262

}

263

264

// Usage

265

const keyInfo = passwordToKey("userPassword", {

266

keySize: 256,

267

useScrypt: true,

268

scryptN: 32768

269

});

270

```

271

272

### Key Stretching for Weak Keys

273

274

```javascript

275

const sjcl = require('sjcl');

276

277

function stretchWeakKey(weakKey, targetLength = 256) {

278

const salt = sjcl.random.randomWords(4);

279

280

// Convert weak key to bit array if it's a string

281

const keyBits = typeof weakKey === 'string'

282

? sjcl.codec.utf8String.toBits(weakKey)

283

: weakKey;

284

285

// Use HKDF to expand the weak key

286

return sjcl.misc.hkdf(

287

keyBits,

288

targetLength,

289

salt,

290

sjcl.codec.utf8String.toBits("key-stretching")

291

);

292

}

293

294

// Usage

295

const weakKey = "short"; // Weak key material

296

const strongKey = stretchWeakKey(weakKey, 256);

297

```

298

299

## Performance Considerations

300

301

- **PBKDF2**: Fast, CPU-intensive only

302

- **scrypt**: Memory-hard, slower but more secure against hardware attacks

303

- **HKDF**: Very fast, for expanding existing good key material

304

- **Iteration counts**: Higher is more secure but slower

305

- **Memory usage**: scrypt requires N * r * 128 bytes of memory