or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-sha3.mdcore-hashing.mdhmac-operations.mdindex.mdvariant-classes.md
tile.json

hmac-operations.mddocs/

0

# HMAC Operations

1

2

Hash-based Message Authentication Code (HMAC) functionality for creating and verifying message authenticity and integrity. jsSHA provides built-in HMAC support for all applicable SHA variants with flexible key input formats.

3

4

## Capabilities

5

6

### HMAC via Constructor Options (Recommended)

7

8

The preferred method for HMAC operations is to specify the HMAC key during object instantiation.

9

10

```typescript { .api }

11

/**

12

* HMAC options for TEXT input format with encoding support

13

*/

14

interface FixedLengthOptionsEncodingType {

15

hmacKey?: GenericInputType;

16

encoding?: EncodingType;

17

} | {

18

numRounds?: number;

19

encoding?: EncodingType;

20

}

21

22

/**

23

* HMAC options for non-TEXT input formats

24

*/

25

interface FixedLengthOptionsNoEncodingType {

26

hmacKey?: GenericInputType;

27

} | {

28

numRounds?: number;

29

}

30

31

/**

32

* Generic input specification for HMAC keys

33

*/

34

interface GenericInputType {

35

value: string;

36

format: "TEXT";

37

encoding?: EncodingType;

38

} | {

39

value: string;

40

format: "B64" | "HEX" | "BYTES";

41

} | {

42

value: ArrayBuffer;

43

format: "ARRAYBUFFER";

44

} | {

45

value: Uint8Array;

46

format: "UINT8ARRAY";

47

}

48

49

type EncodingType = "UTF8" | "UTF16BE" | "UTF16LE";

50

```

51

52

**Usage Examples:**

53

54

```typescript

55

import jsSHA from "jssha";

56

57

// HMAC with text key

58

const hmacText = new jsSHA("SHA-256", "TEXT", {

59

hmacKey: { value: "secret-key", format: "TEXT" },

60

encoding: "UTF8"

61

});

62

hmacText.update("Message to authenticate");

63

const hmac1 = hmacText.getHash("HEX");

64

65

// HMAC with hex key

66

const hmacHex = new jsSHA("SHA-512", "TEXT", {

67

hmacKey: { value: "deadbeef", format: "HEX" }

68

});

69

hmacHex.update("Another message");

70

const hmac2 = hmacHex.getHash("B64");

71

72

// HMAC with Base64 key

73

const hmacB64 = new jsSHA("SHA-1", "HEX", {

74

hmacKey: { value: "c2VjcmV0LWtleQ==", format: "B64" }

75

});

76

hmacB64.update("48656c6c6f"); // "Hello" in hex

77

const hmac3 = hmacB64.getHash("HEX");

78

79

// HMAC with ArrayBuffer key

80

const keyBuffer = new TextEncoder().encode("binary-key").buffer;

81

const hmacBuffer = new jsSHA("SHA-384", "ARRAYBUFFER", {

82

hmacKey: { value: keyBuffer, format: "ARRAYBUFFER" }

83

});

84

const messageBuffer = new TextEncoder().encode("Message").buffer;

85

hmacBuffer.update(messageBuffer);

86

const hmac4 = hmacBuffer.getHash("UINT8ARRAY");

87

88

// HMAC with Uint8Array key

89

const keyArray = new TextEncoder().encode("array-key");

90

const hmacArray = new jsSHA("SHA3-256", "UINT8ARRAY", {

91

hmacKey: { value: keyArray, format: "UINT8ARRAY" }

92

});

93

const messageArray = new TextEncoder().encode("Message");

94

hmacArray.update(messageArray);

95

const hmac5 = hmacArray.getHash("ARRAYBUFFER");

96

```

97

98

### Legacy setHMACKey Method (Deprecated)

99

100

The `setHMACKey` method is deprecated in favor of specifying the HMAC key in constructor options, but remains available for backward compatibility.

101

102

```typescript { .api }

103

/**

104

* Sets the HMAC key for TEXT format keys (DEPRECATED)

105

* @param key - The HMAC key as a string

106

* @param inputFormat - Must be "TEXT"

107

* @param options - Optional encoding configuration

108

*/

109

setHMACKey(key: string, inputFormat: "TEXT", options?: { encoding?: EncodingType }): void;

110

111

/**

112

* Sets the HMAC key for string-based formats (DEPRECATED)

113

* @param key - The HMAC key as a string

114

* @param inputFormat - Key format: B64, HEX, or BYTES

115

*/

116

setHMACKey(key: string, inputFormat: "B64" | "HEX" | "BYTES"): void;

117

118

/**

119

* Sets the HMAC key for ArrayBuffer format (DEPRECATED)

120

* @param key - The HMAC key as ArrayBuffer

121

* @param inputFormat - Must be "ARRAYBUFFER"

122

*/

123

setHMACKey(key: ArrayBuffer, inputFormat: "ARRAYBUFFER"): void;

124

125

/**

126

* Sets the HMAC key for Uint8Array format (DEPRECATED)

127

* @param key - The HMAC key as Uint8Array

128

* @param inputFormat - Must be "UINT8ARRAY"

129

*/

130

setHMACKey(key: Uint8Array, inputFormat: "UINT8ARRAY"): void;

131

```

132

133

**Usage Example (Deprecated Pattern):**

134

135

```typescript

136

import jsSHA from "jssha";

137

138

// Deprecated approach - avoid in new code

139

const shaObj = new jsSHA("SHA-256", "TEXT");

140

shaObj.setHMACKey("secret-key", "TEXT", { encoding: "UTF8" });

141

shaObj.update("Message to authenticate");

142

const hmac = shaObj.getHash("HEX"); // Use getHash, not getHMAC

143

```

144

145

### Legacy getHMAC Method (Deprecated)

146

147

The `getHMAC` method is deprecated in favor of using `getHash` after setting up HMAC in the constructor.

148

149

```typescript { .api }

150

/**

151

* Returns the HMAC in hexadecimal format (DEPRECATED)

152

* @param format - Must be "HEX"

153

* @param options - Optional formatting options

154

* @returns HMAC as hexadecimal string

155

*/

156

getHMAC(format: "HEX", options?: { outputUpper?: boolean }): string;

157

158

/**

159

* Returns the HMAC in Base64 format (DEPRECATED)

160

* @param format - Must be "B64"

161

* @param options - Optional formatting options

162

* @returns HMAC as Base64 string

163

*/

164

getHMAC(format: "B64", options?: { b64Pad?: string }): string;

165

166

/**

167

* Returns the HMAC as a byte string (DEPRECATED)

168

* @param format - Must be "BYTES"

169

* @returns HMAC as byte string

170

*/

171

getHMAC(format: "BYTES"): string;

172

173

/**

174

* Returns the HMAC as a Uint8Array (DEPRECATED)

175

* @param format - Must be "UINT8ARRAY"

176

* @returns HMAC as Uint8Array

177

*/

178

getHMAC(format: "UINT8ARRAY"): Uint8Array;

179

180

/**

181

* Returns the HMAC as an ArrayBuffer (DEPRECATED)

182

* @param format - Must be "ARRAYBUFFER"

183

* @returns HMAC as ArrayBuffer

184

*/

185

getHMAC(format: "ARRAYBUFFER"): ArrayBuffer;

186

```

187

188

## HMAC-Compatible Variants

189

190

HMAC is supported for the following SHA variants:

191

192

- **SHA-1**: HMAC-SHA1 (legacy, not recommended for new applications)

193

- **SHA-224**: HMAC-SHA224

194

- **SHA-256**: HMAC-SHA256 (most commonly used)

195

- **SHA-384**: HMAC-SHA384

196

- **SHA-512**: HMAC-SHA512

197

- **SHA3-224**: HMAC-SHA3-224

198

- **SHA3-256**: HMAC-SHA3-256

199

- **SHA3-384**: HMAC-SHA3-384

200

- **SHA3-512**: HMAC-SHA3-512

201

202

Note: HMAC is not applicable to variable-length variants (SHAKE, cSHAKE) or KMAC variants (which have their own keyed authentication mechanism).

203

204

## Key Format Considerations

205

206

### Text Keys

207

208

When using TEXT format keys, the encoding parameter determines how the string is converted to bytes:

209

210

```typescript

211

// UTF-8 encoding (default and recommended)

212

const hmac1 = new jsSHA("SHA-256", "TEXT", {

213

hmacKey: { value: "secret-key", format: "TEXT", encoding: "UTF8" }

214

});

215

216

// UTF-16 Big Endian encoding

217

const hmac2 = new jsSHA("SHA-256", "TEXT", {

218

hmacKey: { value: "secret-key", format: "TEXT", encoding: "UTF16BE" }

219

});

220

221

// UTF-16 Little Endian encoding

222

const hmac3 = new jsSHA("SHA-256", "TEXT", {

223

hmacKey: { value: "secret-key", format: "TEXT", encoding: "UTF16LE" }

224

});

225

```

226

227

### Binary Keys

228

229

For keys that are already in binary format or need specific byte representations:

230

231

```typescript

232

// Hexadecimal key (useful for keys generated as hex strings)

233

const hmacHex = new jsSHA("SHA-256", "TEXT", {

234

hmacKey: { value: "deadbeefcafebabe", format: "HEX" }

235

});

236

237

// Base64 key (useful for keys stored in Base64 format)

238

const hmacB64 = new jsSHA("SHA-256", "TEXT", {

239

hmacKey: { value: "c2VjcmV0LWtleQ==", format: "B64" }

240

});

241

242

// Raw bytes key (for precise byte control)

243

const hmacBytes = new jsSHA("SHA-256", "TEXT", {

244

hmacKey: { value: "\x00\x01\x02\x03", format: "BYTES" }

245

});

246

```

247

248

### Binary Object Keys

249

250

For keys provided as JavaScript binary objects:

251

252

```typescript

253

// ArrayBuffer key

254

const keyBuffer = new Uint8Array([0x00, 0x01, 0x02, 0x03]).buffer;

255

const hmacBuffer = new jsSHA("SHA-256", "TEXT", {

256

hmacKey: { value: keyBuffer, format: "ARRAYBUFFER" }

257

});

258

259

// Uint8Array key

260

const keyArray = new Uint8Array([0x00, 0x01, 0x02, 0x03]);

261

const hmacArray = new jsSHA("SHA-256", "TEXT", {

262

hmacKey: { value: keyArray, format: "UINT8ARRAY" }

263

});

264

```

265

266

## Common HMAC Patterns

267

268

### API Request Authentication

269

270

```typescript

271

import jsSHA from "jssha";

272

273

function signRequest(method: string, url: string, body: string, secretKey: string): string {

274

const message = `${method}\n${url}\n${body}`;

275

const hmac = new jsSHA("SHA-256", "TEXT", {

276

hmacKey: { value: secretKey, format: "TEXT" }

277

});

278

hmac.update(message);

279

return hmac.getHash("B64");

280

}

281

282

const signature = signRequest("POST", "/api/users", '{"name":"John"}', "my-secret-key");

283

// Use signature in Authorization header

284

```

285

286

### Message Integrity Verification

287

288

```typescript

289

import jsSHA from "jssha";

290

291

function verifyMessage(message: string, expectedHmac: string, secretKey: string): boolean {

292

const hmac = new jsSHA("SHA-256", "TEXT", {

293

hmacKey: { value: secretKey, format: "TEXT" }

294

});

295

hmac.update(message);

296

const computedHmac = hmac.getHash("HEX");

297

298

// Constant-time comparison to prevent timing attacks

299

return computedHmac === expectedHmac;

300

}

301

302

const isValid = verifyMessage("Hello, World!", "expected-hmac-hex", "shared-secret");

303

```

304

305

### JWT-style Token Signing

306

307

```typescript

308

import jsSHA from "jssha";

309

310

function createToken(header: string, payload: string, secret: string): string {

311

const message = `${header}.${payload}`;

312

const hmac = new jsSHA("SHA-256", "TEXT", {

313

hmacKey: { value: secret, format: "TEXT" }

314

});

315

hmac.update(message);

316

const signature = hmac.getHash("B64");

317

return `${message}.${signature}`;

318

}

319

320

const token = createToken("eyJhbGciOiJIUzI1NiJ9", "eyJ1c2VyIjoiam9obiJ9", "jwt-secret");

321

```

322

323

## Security Considerations

324

325

1. **Key Length**: HMAC keys should be at least as long as the hash output length for optimal security

326

2. **Key Storage**: Store HMAC keys securely and never log or expose them

327

3. **Timing Attacks**: Use constant-time comparison when verifying HMAC values

328

4. **Algorithm Choice**: Prefer SHA-256 or stronger variants for new applications

329

5. **Key Rotation**: Implement regular key rotation for long-lived applications

330

331

## Error Handling

332

333

HMAC operations can fail if:

334

- Invalid key formats are provided

335

- The specified SHA variant doesn't support HMAC

336

- `numRounds` parameter is used with HMAC (not supported)

337

338

```typescript

339

// This will work correctly

340

const validHmac = new jsSHA("SHA-256", "TEXT", {

341

hmacKey: { value: "secret", format: "TEXT" }

342

});

343

344

// This will NOT work - numRounds cannot be used with HMAC

345

try {

346

const invalidHmac = new jsSHA("SHA-256", "TEXT", {

347

hmacKey: { value: "secret", format: "TEXT" },

348

numRounds: 5 // Error: numRounds not valid with HMAC

349

});

350

} catch (error) {

351

console.error("Invalid HMAC configuration");

352

}

353

```