or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

box.mdindex.mdlowlevel.mdscalarmult.mdsecretbox.mdsign.mdutilities.md

scalarmult.mddocs/

0

# Scalar Multiplication

1

2

Low-level scalar multiplication using x25519. These functions provide the underlying elliptic curve operations used by the higher-level box functions, enabling custom cryptographic protocols and key derivation.

3

4

## Capabilities

5

6

### Scalar Multiplication Operations

7

8

Perform elliptic curve scalar multiplication operations.

9

10

```javascript { .api }

11

/**

12

* Multiplies an integer scalar by a group element (point on the curve)

13

* @param {Uint8Array} n - The scalar (32 bytes)

14

* @param {Uint8Array} p - The group element/point (32 bytes)

15

* @returns {Uint8Array} Resulting group element (32 bytes)

16

*/

17

nacl.scalarMult(n, p): Uint8Array

18

19

/**

20

* Multiplies an integer scalar by the standard base point of the curve

21

* @param {Uint8Array} n - The scalar (32 bytes)

22

* @returns {Uint8Array} Resulting group element (32 bytes)

23

*/

24

nacl.scalarMult.base(n): Uint8Array

25

```

26

27

**Usage Examples:**

28

29

```javascript

30

const nacl = require('tweetnacl');

31

32

// Generate a random scalar (private key)

33

const scalar = nacl.randomBytes(nacl.scalarMult.scalarLength);

34

35

// Multiply scalar by base point to get public key

36

const publicKey = nacl.scalarMult.base(scalar);

37

console.log(publicKey.length); // 32

38

39

// Perform Diffie-Hellman key exchange

40

const aliceSecret = nacl.randomBytes(32);

41

const bobSecret = nacl.randomBytes(32);

42

43

const alicePublic = nacl.scalarMult.base(aliceSecret);

44

const bobPublic = nacl.scalarMult.base(bobSecret);

45

46

// Both parties can compute the same shared secret

47

const aliceShared = nacl.scalarMult(aliceSecret, bobPublic);

48

const bobShared = nacl.scalarMult(bobSecret, alicePublic);

49

50

// Verify shared secrets are identical

51

const secretsMatch = aliceShared.every((byte, i) => byte === bobShared[i]);

52

console.log(secretsMatch); // true

53

```

54

55

**Key Derivation Example:**

56

57

```javascript

58

const nacl = require('tweetnacl');

59

60

// Master key derivation

61

const masterKey = nacl.randomBytes(32);

62

const basePoint = nacl.scalarMult.base(masterKey);

63

64

// Derive child keys using different scalars

65

const childScalar1 = nacl.hash(new TextEncoder().encode("child1")).slice(0, 32);

66

const childScalar2 = nacl.hash(new TextEncoder().encode("child2")).slice(0, 32);

67

68

const childKey1 = nacl.scalarMult(childScalar1, basePoint);

69

const childKey2 = nacl.scalarMult(childScalar2, basePoint);

70

71

console.log("Child key 1:", childKey1);

72

console.log("Child key 2:", childKey2);

73

```

74

75

## Constants

76

77

```javascript { .api }

78

nacl.scalarMult.scalarLength: number // 32 - Length of scalar in bytes

79

nacl.scalarMult.groupElementLength: number // 32 - Length of group element in bytes

80

```

81

82

## Advanced Usage

83

84

### Custom Diffie-Hellman Implementation

85

86

```javascript

87

const nacl = require('tweetnacl');

88

89

function createDiffieHellmanKeyPair() {

90

const secretKey = nacl.randomBytes(nacl.scalarMult.scalarLength);

91

const publicKey = nacl.scalarMult.base(secretKey);

92

return { secretKey, publicKey };

93

}

94

95

function computeSharedSecret(mySecretKey, theirPublicKey) {

96

return nacl.scalarMult(mySecretKey, theirPublicKey);

97

}

98

99

// Usage

100

const alice = createDiffieHellmanKeyPair();

101

const bob = createDiffieHellmanKeyPair();

102

103

const sharedSecretAlice = computeSharedSecret(alice.secretKey, bob.publicKey);

104

const sharedSecretBob = computeSharedSecret(bob.secretKey, alice.publicKey);

105

106

// Both shared secrets are identical

107

console.log(sharedSecretAlice.every((byte, i) => byte === sharedSecretBob[i])); // true

108

```

109

110

### Key Validation

111

112

```javascript

113

const nacl = require('tweetnacl');

114

115

function isValidGroupElement(element) {

116

if (element.length !== nacl.scalarMult.groupElementLength) {

117

return false;

118

}

119

120

// Check if all bytes are zero (invalid point)

121

const allZero = element.every(byte => byte === 0);

122

return !allZero;

123

}

124

125

function isValidScalar(scalar) {

126

if (scalar.length !== nacl.scalarMult.scalarLength) {

127

return false;

128

}

129

130

// Check if all bytes are zero (invalid scalar)

131

const allZero = scalar.every(byte => byte === 0);

132

return !allZero;

133

}

134

135

// Example validation

136

const publicKey = nacl.scalarMult.base(nacl.randomBytes(32));

137

console.log(isValidGroupElement(publicKey)); // true

138

139

const zeroKey = new Uint8Array(32); // All zeros

140

console.log(isValidGroupElement(zeroKey)); // false

141

```

142

143

## Security Considerations

144

145

- **Scalar Validation**: Ensure scalars are not all zeros and are properly random when used as private keys.

146

- **Point Validation**: Group elements should be validated to ensure they represent valid curve points.

147

- **Side-Channel Resistance**: The scalar multiplication is designed to be constant-time to prevent timing attacks.

148

- **Key Management**: When using these functions to implement custom protocols, follow proper key management practices.

149

- **Protocol Design**: These are low-level primitives. Most applications should use the higher-level `nacl.box` functions instead.

150

151

## Relationship to Box Functions

152

153

The `nacl.box` functions internally use scalar multiplication:

154

- `nacl.box.keyPair()` uses `nacl.scalarMult.base()` to generate public keys

155

- `nacl.box.before()` uses `nacl.scalarMult()` to compute shared secrets

156

157

Understanding scalar multiplication helps in designing custom protocols or optimizing performance-critical applications.