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

symmetric-encryption.mddocs/

0

# Symmetric Encryption

1

2

SJCL provides AES (Advanced Encryption Standard) implementation supporting 128, 192, and 256-bit keys for secure symmetric encryption operations.

3

4

## Capabilities

5

6

### AES Cipher

7

8

The primary symmetric cipher in SJCL, providing industry-standard AES encryption with support for multiple key sizes.

9

10

```javascript { .api }

11

/**

12

* AES cipher constructor

13

* @param {BitArray} key - Encryption key as bit array (4, 6, or 8 words for 128/192/256-bit keys)

14

* @throws {sjcl.exception.invalid} If key size is not 4, 6, or 8 words

15

*/

16

new sjcl.cipher.aes(key);

17

```

18

19

**Instance Methods:**

20

21

```javascript { .api }

22

/**

23

* Encrypt a single 128-bit block

24

* @param {BitArray} data - 4-word (128-bit) plaintext block

25

* @returns {BitArray} 4-word (128-bit) ciphertext block

26

* @throws {sjcl.exception.invalid} If block size is not exactly 4 words

27

*/

28

sjcl.cipher.aes.prototype.encrypt(data);

29

30

/**

31

* Decrypt a single 128-bit block

32

* @param {BitArray} data - 4-word (128-bit) ciphertext block

33

* @returns {BitArray} 4-word (128-bit) plaintext block

34

* @throws {sjcl.exception.invalid} If block size is not exactly 4 words

35

*/

36

sjcl.cipher.aes.prototype.decrypt(data);

37

```

38

39

**Usage Examples:**

40

41

```javascript

42

const sjcl = require('sjcl');

43

44

// Generate a random 256-bit key

45

const key256 = sjcl.random.randomWords(8); // 8 words = 256 bits

46

const aes256 = new sjcl.cipher.aes(key256);

47

48

// Generate a 128-bit key from password (using PBKDF2)

49

const password = "mySecretPassword";

50

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

51

const key128 = sjcl.misc.pbkdf2(password, salt, 10000, 128);

52

const aes128 = new sjcl.cipher.aes(key128);

53

54

// Encrypt a single block

55

const plaintext = sjcl.codec.utf8String.toBits("Hello, World!!!!"); // Must be exactly 16 bytes

56

const paddedPlaintext = sjcl.bitArray.clamp(

57

sjcl.bitArray.concat(plaintext, [0, 0, 0, 0]),

58

128

59

); // Ensure exactly 128 bits

60

const ciphertext = aes128.encrypt(paddedPlaintext);

61

62

// Decrypt the block

63

const decrypted = aes128.decrypt(ciphertext);

64

const decryptedText = sjcl.codec.utf8String.fromBits(decrypted);

65

console.log(decryptedText.trim()); // "Hello, World!!!!"

66

```

67

68

### Key Sizes

69

70

AES supports three different key sizes, each providing different security levels:

71

72

```javascript

73

const sjcl = require('sjcl');

74

75

// 128-bit key (4 words) - Fast, good security

76

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

77

const aes128 = new sjcl.cipher.aes(key128);

78

79

// 192-bit key (6 words) - Medium security/performance

80

const key192 = sjcl.random.randomWords(6);

81

const aes192 = new sjcl.cipher.aes(key192);

82

83

// 256-bit key (8 words) - Highest security

84

const key256 = sjcl.random.randomWords(8);

85

const aes256 = new sjcl.cipher.aes(key256);

86

87

// Key from password using PBKDF2

88

function deriveAESKey(password, salt, keySize) {

89

const iterations = 10000;

90

const keyBits = keySize; // 128, 192, or 256

91

return sjcl.misc.pbkdf2(password, salt, iterations, keyBits);

92

}

93

94

const derivedKey = deriveAESKey("password", sjcl.random.randomWords(4), 256);

95

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

96

```

97

98

### Block Cipher Usage

99

100

AES is a block cipher that encrypts fixed-size 128-bit blocks. For practical use, it must be combined with a cipher mode:

101

102

```javascript

103

const sjcl = require('sjcl');

104

105

// Manual block-by-block encryption (not recommended for production)

106

function encryptMultipleBlocks(aes, plaintext) {

107

const blocks = [];

108

const data = sjcl.bitArray.clamp(plaintext, Math.floor(sjcl.bitArray.bitLength(plaintext) / 128) * 128);

109

110

for (let i = 0; i < data.length; i += 4) {

111

const block = data.slice(i, i + 4);

112

if (block.length === 4) {

113

blocks.push(...aes.encrypt(block));

114

}

115

}

116

117

return blocks;

118

}

119

120

// Better approach: Use cipher modes (see cipher-modes.md)

121

const key = sjcl.random.randomWords(8);

122

const plaintext = sjcl.codec.utf8String.toBits("This is a longer message that spans multiple blocks");

123

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

124

125

// Use GCM mode for authenticated encryption

126

const encrypted = sjcl.mode.gcm.encrypt(new sjcl.cipher.aes(key), plaintext, iv);

127

```

128

129

### Key Management

130

131

Proper key management is crucial for AES security:

132

133

```javascript

134

const sjcl = require('sjcl');

135

136

// Generate cryptographically secure keys

137

function generateAESKey(keySize = 256) {

138

const words = keySize / 32; // Convert bits to 32-bit words

139

return sjcl.random.randomWords(words);

140

}

141

142

// Derive keys from passwords

143

function deriveKeyFromPassword(password, salt, keySize = 256, iterations = 100000) {

144

// Ensure salt is provided and sufficiently random

145

if (!salt || sjcl.bitArray.bitLength(salt) < 128) {

146

throw new sjcl.exception.invalid("Salt must be at least 128 bits");

147

}

148

149

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

150

}

151

152

// Key derivation with automatic salt generation

153

function createKeyWithSalt(password, keySize = 256) {

154

const salt = sjcl.random.randomWords(4); // 128-bit salt

155

const key = deriveKeyFromPassword(password, salt, keySize);

156

157

return {

158

key: key,

159

salt: salt,

160

keySize: keySize

161

};

162

}

163

164

// Usage

165

const keyInfo = createKeyWithSalt("userPassword", 256);

166

const aes = new sjcl.cipher.aes(keyInfo.key);

167

// Store keyInfo.salt for later key reconstruction

168

```

169

170

### Performance Considerations

171

172

Different key sizes have different performance characteristics:

173

174

```javascript

175

const sjcl = require('sjcl');

176

177

// Benchmark different key sizes

178

function benchmarkAES() {

179

const testData = sjcl.random.randomWords(4); // One block

180

const iterations = 10000;

181

182

// Test 128-bit key

183

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

184

const aes128 = new sjcl.cipher.aes(key128);

185

console.time('AES-128');

186

for (let i = 0; i < iterations; i++) {

187

aes128.encrypt(testData);

188

}

189

console.timeEnd('AES-128');

190

191

// Test 256-bit key

192

const key256 = sjcl.random.randomWords(8);

193

const aes256 = new sjcl.cipher.aes(key256);

194

console.time('AES-256');

195

for (let i = 0; i < iterations; i++) {

196

aes256.encrypt(testData);

197

}

198

console.timeEnd('AES-256');

199

}

200

201

// benchmarkAES(); // Uncomment to run benchmark

202

```

203

204

## Security Recommendations

205

206

1. **Use AES-256** for maximum security, AES-128 for performance-critical applications

207

2. **Never reuse keys** for different data or purposes

208

3. **Use proper cipher modes** (GCM, CCM) instead of raw block encryption

209

4. **Generate keys securely** using `sjcl.random.randomWords()` or PBKDF2

210

5. **Store keys securely** and never log or expose them

211

6. **Use authenticated encryption modes** to prevent tampering

212

213

## Common Pitfalls

214

215

1. **Block size requirement**: AES requires exactly 128-bit (4-word) blocks

216

2. **Key reuse**: Never use the same key-IV pair twice

217

3. **Padding**: Raw AES doesn't handle padding - use cipher modes instead

218

4. **Weak key derivation**: Always use sufficient iterations in PBKDF2 (≥10,000)

219

5. **IV reuse**: Initialization vectors must be unique for each encryption