or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aead.mdauth.mdbox.mded25519.mdhash.mdindex.mdkdf.mdkx.mdmemory.mdpwhash.mdrandom.mdsecretbox.mdsecretstream.mdshorthash.mdsign.mdstream.md

auth.mddocs/

0

# Message Authentication

1

2

Message authentication codes (MAC) using HMAC-SHA512 and Poly1305 for data integrity verification and authenticity.

3

4

## Capabilities

5

6

### HMAC-SHA512 Authentication

7

8

Compute and verify HMAC-SHA512 message authentication codes.

9

10

```javascript { .api }

11

/**

12

* Compute HMAC-SHA512 authentication tag

13

* @param out - Output buffer for authentication tag (must be BYTES long)

14

* @param input - Input buffer to authenticate

15

* @param k - Key buffer (must be KEYBYTES long)

16

* @throws Error if buffer sizes are incorrect or authentication fails

17

*/

18

function crypto_auth(out: Buffer, input: Buffer, k: Buffer): void;

19

20

/**

21

* Verify HMAC-SHA512 authentication tag

22

* @param h - Authentication tag to verify (must be BYTES long)

23

* @param input - Input buffer that was authenticated

24

* @param k - Key buffer (must be KEYBYTES long)

25

* @returns true if tag is valid, false otherwise

26

*/

27

function crypto_auth_verify(h: Buffer, input: Buffer, k: Buffer): boolean;

28

```

29

30

**Usage Example:**

31

32

```javascript

33

const sodium = require('sodium-native');

34

35

// Generate authentication key

36

const key = Buffer.alloc(sodium.crypto_auth_KEYBYTES);

37

sodium.randombytes_buf(key);

38

39

// Authenticate a message

40

const message = Buffer.from('Important message');

41

const tag = Buffer.alloc(sodium.crypto_auth_BYTES);

42

sodium.crypto_auth(tag, message, key);

43

44

// Verify the authentication tag

45

if (sodium.crypto_auth_verify(tag, message, key)) {

46

console.log('Message is authentic');

47

} else {

48

console.log('Message authentication failed');

49

}

50

```

51

52

### Poly1305 One-time Authentication

53

54

Poly1305 MAC for high-performance message authentication with one-time keys.

55

56

```javascript { .api }

57

/**

58

* Compute Poly1305 authentication tag

59

* @param out - Output buffer for authentication tag (must be BYTES long)

60

* @param input - Input buffer to authenticate

61

* @param k - One-time key buffer (must be KEYBYTES long)

62

* @throws Error if buffer sizes are incorrect or authentication fails

63

*/

64

function crypto_onetimeauth(out: Buffer, input: Buffer, k: Buffer): void;

65

66

/**

67

* Verify Poly1305 authentication tag

68

* @param h - Authentication tag to verify (must be BYTES long)

69

* @param input - Input buffer that was authenticated

70

* @param k - One-time key buffer (must be KEYBYTES long)

71

* @returns true if tag is valid, false otherwise

72

*/

73

function crypto_onetimeauth_verify(h: Buffer, input: Buffer, k: Buffer): boolean;

74

```

75

76

### Poly1305 Streaming Authentication

77

78

Initialize, update, and finalize Poly1305 authentication for large data.

79

80

```javascript { .api }

81

/**

82

* Initialize Poly1305 streaming authentication

83

* @param state - State buffer (must be STATEBYTES long)

84

* @param k - One-time key buffer (must be KEYBYTES long)

85

* @throws Error if initialization fails or buffer sizes incorrect

86

*/

87

function crypto_onetimeauth_init(state: Buffer, k: Buffer): void;

88

89

/**

90

* Update Poly1305 streaming authentication with more data

91

* @param state - State buffer from init

92

* @param input - Input buffer to add to authentication

93

* @throws Error if update fails

94

*/

95

function crypto_onetimeauth_update(state: Buffer, input: Buffer): void;

96

97

/**

98

* Finalize Poly1305 streaming authentication and get tag

99

* @param state - State buffer from init/update

100

* @param out - Output buffer for authentication tag (must be BYTES long)

101

* @throws Error if finalization fails

102

*/

103

function crypto_onetimeauth_final(state: Buffer, out: Buffer): void;

104

```

105

106

**Usage Example:**

107

108

```javascript

109

const sodium = require('sodium-native');

110

111

// Generate one-time key

112

const key = Buffer.alloc(sodium.crypto_onetimeauth_KEYBYTES);

113

sodium.randombytes_buf(key);

114

115

// Streaming authentication for large data

116

const state = Buffer.alloc(sodium.crypto_onetimeauth_STATEBYTES);

117

sodium.crypto_onetimeauth_init(state, key);

118

119

// Process data in chunks

120

const chunk1 = Buffer.from('First part of ');

121

const chunk2 = Buffer.from('large message');

122

123

sodium.crypto_onetimeauth_update(state, chunk1);

124

sodium.crypto_onetimeauth_update(state, chunk2);

125

126

const tag = Buffer.alloc(sodium.crypto_onetimeauth_BYTES);

127

sodium.crypto_onetimeauth_final(state, tag);

128

129

// Verify using one-shot function

130

const fullMessage = Buffer.concat([chunk1, chunk2]);

131

if (sodium.crypto_onetimeauth_verify(tag, fullMessage, key)) {

132

console.log('Message is authentic');

133

}

134

```

135

136

## Constants

137

138

```javascript { .api }

139

// HMAC-SHA512 constants

140

const crypto_auth_BYTES: number;

141

const crypto_auth_KEYBYTES: number;

142

143

// Poly1305 constants

144

const crypto_onetimeauth_STATEBYTES: number;

145

const crypto_onetimeauth_BYTES: number;

146

const crypto_onetimeauth_KEYBYTES: number;

147

```

148

149

## Security Considerations

150

151

- **Key Reuse**: HMAC keys can be reused safely, but Poly1305 keys must be used only once.

152

- **Key Generation**: Use cryptographically secure random key generation.

153

- **Timing Attacks**: Both implementations use constant-time comparison for verification.

154

- **Key Management**: Store authentication keys securely and separately from data.

155

156

## Common Patterns

157

158

### Message Integrity Service

159

160

```javascript

161

const sodium = require('sodium-native');

162

163

class MessageIntegrity {

164

constructor() {

165

this.hmacKey = Buffer.alloc(sodium.crypto_auth_KEYBYTES);

166

sodium.randombytes_buf(this.hmacKey);

167

}

168

169

sign(message) {

170

const tag = Buffer.alloc(sodium.crypto_auth_BYTES);

171

sodium.crypto_auth(tag, message, this.hmacKey);

172

173

return {

174

message: message,

175

tag: tag

176

};

177

}

178

179

verify(signedMessage) {

180

return sodium.crypto_auth_verify(

181

signedMessage.tag,

182

signedMessage.message,

183

this.hmacKey

184

);

185

}

186

187

// For one-time use (e.g., network packets)

188

signOneTime(message, oneTimeKey) {

189

const tag = Buffer.alloc(sodium.crypto_onetimeauth_BYTES);

190

sodium.crypto_onetimeauth(tag, message, oneTimeKey);

191

return tag;

192

}

193

194

verifyOneTime(message, tag, oneTimeKey) {

195

return sodium.crypto_onetimeauth_verify(tag, message, oneTimeKey);

196

}

197

}

198

```

199

200

### File Integrity Checker

201

202

```javascript

203

const sodium = require('sodium-native');

204

const fs = require('fs');

205

206

class FileIntegrityChecker {

207

constructor(keyFile) {

208

if (fs.existsSync(keyFile)) {

209

this.key = fs.readFileSync(keyFile);

210

} else {

211

this.key = Buffer.alloc(sodium.crypto_auth_KEYBYTES);

212

sodium.randombytes_buf(this.key);

213

fs.writeFileSync(keyFile, this.key);

214

}

215

}

216

217

createChecksum(filename) {

218

const data = fs.readFileSync(filename);

219

const checksum = Buffer.alloc(sodium.crypto_auth_BYTES);

220

sodium.crypto_auth(checksum, data, this.key);

221

222

// Save checksum file

223

fs.writeFileSync(`${filename}.checksum`, checksum);

224

return checksum;

225

}

226

227

verifyChecksum(filename) {

228

const checksumFile = `${filename}.checksum`;

229

if (!fs.existsSync(checksumFile)) {

230

throw new Error('Checksum file not found');

231

}

232

233

const data = fs.readFileSync(filename);

234

const storedChecksum = fs.readFileSync(checksumFile);

235

236

return sodium.crypto_auth_verify(storedChecksum, data, this.key);

237

}

238

239

// For streaming large files

240

createStreamingChecksum(filename) {

241

const state = Buffer.alloc(sodium.crypto_auth_STATEBYTES);

242

sodium.crypto_auth_init(state, this.key);

243

244

const fileStream = fs.createReadStream(filename, { highWaterMark: 64 * 1024 });

245

246

return new Promise((resolve, reject) => {

247

fileStream.on('data', (chunk) => {

248

sodium.crypto_auth_update(state, chunk);

249

});

250

251

fileStream.on('end', () => {

252

const checksum = Buffer.alloc(sodium.crypto_auth_BYTES);

253

sodium.crypto_auth_final(state, checksum);

254

resolve(checksum);

255

});

256

257

fileStream.on('error', reject);

258

});

259

}

260

}

261

```

262

263

### API Request Authentication

264

265

```javascript

266

const sodium = require('sodium-native');

267

268

class APIAuth {

269

constructor(secretKey) {

270

this.secretKey = Buffer.from(secretKey);

271

if (this.secretKey.length !== sodium.crypto_auth_KEYBYTES) {

272

throw new Error('Invalid secret key length');

273

}

274

}

275

276

signRequest(method, url, body, timestamp) {

277

const message = Buffer.from(`${method}|${url}|${body}|${timestamp}`);

278

const signature = Buffer.alloc(sodium.crypto_auth_BYTES);

279

280

sodium.crypto_auth(signature, message, this.secretKey);

281

282

return {

283

signature: signature.toString('hex'),

284

timestamp: timestamp

285

};

286

}

287

288

verifyRequest(method, url, body, signature, timestamp) {

289

const message = Buffer.from(`${method}|${url}|${body}|${timestamp}`);

290

const signatureBuffer = Buffer.from(signature, 'hex');

291

292

if (signatureBuffer.length !== sodium.crypto_auth_BYTES) {

293

return false;

294

}

295

296

return sodium.crypto_auth_verify(signatureBuffer, message, this.secretKey);

297

}

298

}

299

300

// Usage

301

const apiAuth = new APIAuth('your-secret-key-32-bytes-long!!!!!');

302

const timestamp = Date.now();

303

const auth = apiAuth.signRequest('GET', '/api/users', '', timestamp);

304

305

console.log('Authorization:', auth.signature);

306

console.log('Timestamp:', auth.timestamp);

307

```