Skip to content

Commit fabe5d7

Browse files
authored
Move client key derivation parameters to client input options (bytemare#100)
* Move client key derivation parameters to input options Signed-off-by: bytemare <[email protected]> * remove unnecessary test Signed-off-by: bytemare <[email protected]> * update ecc Signed-off-by: bytemare <[email protected]> --------- Signed-off-by: bytemare <[email protected]>
1 parent f9937c2 commit fabe5d7

15 files changed

+249
-340
lines changed

client.go

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ func (c *Client) GetConf() *internal.Configuration {
6565
}
6666

6767
// buildPRK derives the randomized password from the OPRF output.
68-
func (c *Client) buildPRK(evaluation *ecc.Element) []byte {
68+
func (c *Client) buildPRK(evaluation *ecc.Element, ksfSalt, kdfSalt []byte, ksfLength int) []byte {
6969
output := c.OPRF.Finalize(evaluation)
70-
stretched := c.conf.KSF.Harden(output, c.conf.KSFSalt, c.conf.Hash.Size())
70+
stretched := c.conf.KSF.Harden(output, ksfSalt, ksfLength)
7171

72-
return c.conf.KDF.Extract(nil, encoding.Concat(output, stretched))
72+
return c.conf.KDF.Extract(kdfSalt, encoding.Concat(output, stretched))
7373
}
7474

7575
// ClientRegistrationInitOptions enables setting internal client values for the client registration.
@@ -106,31 +106,50 @@ type ClientRegistrationFinalizeOptions struct {
106106
ServerIdentity []byte
107107
// EnvelopeNonce : optional.
108108
EnvelopeNonce []byte
109+
// KDFSalt: optional.
110+
KDFSalt []byte
111+
// KSFSalt: optional.
112+
KSFSalt []byte
113+
// KSFParameters: optional.
114+
KSFParameters []int
115+
// KSFLength: optional.
116+
KSFLength uint32
109117
}
110118

111-
func initClientRegistrationFinalizeOptions(options []ClientRegistrationFinalizeOptions) *keyrecovery.Credentials {
119+
func (c *Client) initClientRegistrationFinalizeOptions(
120+
options []ClientRegistrationFinalizeOptions,
121+
) (*keyrecovery.Credentials, []byte, []byte, int) {
112122
if len(options) == 0 {
113123
return &keyrecovery.Credentials{
114124
ClientIdentity: nil,
115125
ServerIdentity: nil,
116126
EnvelopeNonce: nil,
117-
}
127+
}, nil, nil, c.conf.Group.ElementLength()
128+
}
129+
130+
if len(options[0].KSFParameters) != 0 {
131+
c.conf.KSF.Parameterize(options[0].KSFParameters...)
132+
}
133+
134+
ksfLength := int(options[0].KSFLength)
135+
if ksfLength == 0 {
136+
ksfLength = c.conf.Group.ElementLength()
118137
}
119138

120139
return &keyrecovery.Credentials{
121140
ClientIdentity: options[0].ClientIdentity,
122141
ServerIdentity: options[0].ServerIdentity,
123142
EnvelopeNonce: options[0].EnvelopeNonce,
124-
}
143+
}, options[0].KSFSalt, options[0].KDFSalt, ksfLength
125144
}
126145

127146
// RegistrationFinalize returns a RegistrationRecord message given the identities and the server's RegistrationResponse.
128147
func (c *Client) RegistrationFinalize(
129148
resp *message.RegistrationResponse,
130149
options ...ClientRegistrationFinalizeOptions,
131150
) (record *message.RegistrationRecord, exportKey []byte) {
132-
credentials := initClientRegistrationFinalizeOptions(options)
133-
randomizedPassword := c.buildPRK(resp.EvaluatedMessage)
151+
credentials, ksfSalt, kdfSalt, ksfLength := c.initClientRegistrationFinalizeOptions(options)
152+
randomizedPassword := c.buildPRK(resp.EvaluatedMessage, ksfSalt, kdfSalt, ksfLength)
134153
maskingKey := c.conf.KDF.Expand(randomizedPassword, []byte(tag.MaskingKey), c.conf.KDF.Size())
135154
envelope, clientPublicKey, exportKey := keyrecovery.Store(c.conf, randomizedPassword, resp.Pks, credentials)
136155

@@ -151,20 +170,16 @@ type GenerateKE1Options struct {
151170
// AKENonce: optional.
152171
AKENonce []byte
153172
// AKENonceLength: optional, overrides the default length of the nonce to be created if no nonce is provided.
154-
AKENonceLength uint
155-
}
156-
157-
func (c GenerateKE1Options) get() (*ecc.Scalar, ake.Options) {
158-
return c.OPRFBlind, ake.Options{
159-
KeyShareSeed: c.KeyShareSeed,
160-
Nonce: c.AKENonce,
161-
NonceLength: c.AKENonceLength,
162-
}
173+
AKENonceLength uint32
163174
}
164175

165176
func getGenerateKE1Options(options []GenerateKE1Options) (*ecc.Scalar, ake.Options) {
166177
if len(options) != 0 {
167-
return options[0].get()
178+
return options[0].OPRFBlind, ake.Options{
179+
KeyShareSeed: options[0].KeyShareSeed,
180+
Nonce: options[0].AKENonce,
181+
NonceLength: options[0].AKENonceLength,
182+
}
168183
}
169184

170185
return nil, ake.Options{
@@ -191,20 +206,37 @@ type GenerateKE3Options struct {
191206
ClientIdentity []byte
192207
// ServerIdentity: optional.
193208
ServerIdentity []byte
209+
// KDFSalt: optional.
210+
KDFSalt []byte
211+
// KSFSalt: optional.
212+
KSFSalt []byte
213+
// KSFParameters: optional.
214+
KSFParameters []int
215+
// KSFLength: optional.
216+
KSFLength uint32
194217
}
195218

196-
func initGenerateKE3Options(options []GenerateKE3Options) *ake.Identities {
219+
func (c *Client) initGenerateKE3Options(options []GenerateKE3Options) (*ake.Identities, []byte, []byte, int) {
197220
if len(options) == 0 {
198221
return &ake.Identities{
199222
ClientIdentity: nil,
200223
ServerIdentity: nil,
201-
}
224+
}, nil, nil, c.conf.Group.ElementLength()
225+
}
226+
227+
if len(options[0].KSFParameters) != 0 {
228+
c.conf.KSF.Parameterize(options[0].KSFParameters...)
229+
}
230+
231+
ksfLength := int(options[0].KSFLength)
232+
if ksfLength == 0 {
233+
ksfLength = c.conf.Group.ElementLength()
202234
}
203235

204236
return &ake.Identities{
205237
ClientIdentity: options[0].ClientIdentity,
206238
ServerIdentity: options[0].ServerIdentity,
207-
}
239+
}, options[0].KSFSalt, options[0].KDFSalt, ksfLength
208240
}
209241

210242
// GenerateKE3 returns a KE3 message given the server's KE2 response message and the identities. If the idc
@@ -221,10 +253,10 @@ func (c *Client) GenerateKE3(
221253
return nil, nil, errInvalidMaskedLength
222254
}
223255

224-
identities := initGenerateKE3Options(options)
256+
identities, ksfSalt, kdfSalt, ksfLength := c.initGenerateKE3Options(options)
225257

226258
// Finalize the OPRF.
227-
randomizedPassword := c.buildPRK(ke2.EvaluatedMessage)
259+
randomizedPassword := c.buildPRK(ke2.EvaluatedMessage, ksfSalt, kdfSalt, ksfLength)
228260

229261
// Decrypt the masked response.
230262
serverPublicKey, serverPublicKeyBytes,

examples_test.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,12 @@ func Example_configuration() {
4848
defaultConf := opaque.DefaultConfiguration()
4949

5050
customConf := &opaque.Configuration{
51-
OPRF: opaque.RistrettoSha512,
52-
KDF: crypto.SHA512,
53-
MAC: crypto.SHA512,
54-
Hash: crypto.SHA512,
55-
KSF: opaque.KSFConfiguration{
56-
Identifier: ksf.Argon2id,
57-
},
51+
OPRF: opaque.RistrettoSha512,
5852
AKE: opaque.RistrettoSha512,
53+
KSF: ksf.Argon2id,
54+
KDF: crypto.SHA512,
55+
MAC: crypto.SHA512,
56+
Hash: crypto.SHA512,
5957
Context: nil,
6058
}
6159

@@ -81,7 +79,7 @@ func Example_configuration() {
8179

8280
fmt.Println("OPAQUE configuration is easy!")
8381

84-
// Output: Encoded Configuration: 010707070101000000000000
82+
// Output: Encoded Configuration: 0101010707070000
8583
// OPAQUE configuration is easy!
8684
}
8785

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/bytemare/opaque
33
go 1.24.2
44

55
require (
6-
github.com/bytemare/ecc v0.8.5
6+
github.com/bytemare/ecc v0.9.0
77
github.com/bytemare/hash v0.5.2
88
github.com/bytemare/ksf v0.3.0
99
)
@@ -12,7 +12,7 @@ require (
1212
filippo.io/edwards25519 v1.1.0 // indirect
1313
filippo.io/nistec v0.0.3 // indirect
1414
github.com/bytemare/hash2curve v0.5.4 // indirect
15-
github.com/bytemare/secp256k1 v0.2.2 // indirect
15+
github.com/bytemare/secp256k1 v0.3.0 // indirect
1616
github.com/gtank/ristretto255 v0.1.2 // indirect
1717
golang.org/x/crypto v0.38.0 // indirect
1818
golang.org/x/sys v0.33.0 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
22
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
33
filippo.io/nistec v0.0.3 h1:h336Je2jRDZdBCLy2fLDUd9E2unG32JLwcJi0JQE9Cw=
44
filippo.io/nistec v0.0.3/go.mod h1:84fxC9mi+MhC2AERXI4LSa8cmSVOzrFikg6hZ4IfCyw=
5-
github.com/bytemare/ecc v0.8.5 h1:6GhdqyJlXqMPoQ5EM1nzC/2QrM1vSzTKpZ4y/HlzkfE=
6-
github.com/bytemare/ecc v0.8.5/go.mod h1:qdA3X7uwWcux0AMTco4cdmY5lnjcCTgSNrhbknsOGlY=
5+
github.com/bytemare/ecc v0.9.0 h1:6+gqn9l63bd82nQVwIpW3LFtsnIsy8V4mvlybAYq6II=
6+
github.com/bytemare/ecc v0.9.0/go.mod h1:3sdNyM1oi4YwcUkxlogZT/CnahwrH38T7a1wc8JsICQ=
77
github.com/bytemare/hash v0.5.2 h1:quCTPpPMh+Elg1autId1hQhI6QyVKj3d9Prn0l2X8oY=
88
github.com/bytemare/hash v0.5.2/go.mod h1:SfyIe/M9RA+p48z/kYLMJCMVYepaLLkvxrnnqUaY6Yw=
99
github.com/bytemare/hash2curve v0.5.4 h1:WLgEKcoZKHZ41a/TApFMxhaLYHNh9lL2DNAIZCVCLuM=
1010
github.com/bytemare/hash2curve v0.5.4/go.mod h1:XxXWaFy2g3AsIPovVp4Q8g9GDHNfr2NStnYNC+z1WRo=
1111
github.com/bytemare/ksf v0.3.0 h1:5gxry79Ql6TcBfgKFJqFQA3GmTbWP7660zwvb5NaNek=
1212
github.com/bytemare/ksf v0.3.0/go.mod h1:QJDwBqGhcd1G5mx+Hir5a0pxRIzRdAXUbR9dSDp6dTU=
13-
github.com/bytemare/secp256k1 v0.2.2 h1:cTHROEWfo6Qj37xNkUh9e6dvTBnwCXMAmUqKNtRs4To=
14-
github.com/bytemare/secp256k1 v0.2.2/go.mod h1:Z2HjKm36tC+Qz51fe1eqMsAM99oTTNlvSuPmPyVXGm0=
13+
github.com/bytemare/secp256k1 v0.3.0 h1:Te2HjAtTRKbqRDBOIMKDFkILTqd6YZ+sIgXvrJ7BaB0=
14+
github.com/bytemare/secp256k1 v0.3.0/go.mod h1:Z2HjKm36tC+Qz51fe1eqMsAM99oTTNlvSuPmPyVXGm0=
1515
github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc=
1616
github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o=
1717
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=

internal/ake/3dh.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
package ake
1111

1212
import (
13-
"math"
14-
1513
"github.com/bytemare/ecc"
1614

1715
"github.com/bytemare/opaque/internal"
@@ -68,7 +66,7 @@ type Options struct {
6866
// Nonce: optional.
6967
Nonce []byte
7068
// NonceLength: optional, overrides the default length of the nonce to be created if no nonce is provided.
71-
NonceLength uint
69+
NonceLength uint32
7270
}
7371

7472
func (o *Options) init() {
@@ -80,12 +78,8 @@ func (o *Options) init() {
8078
o.NonceLength = internal.NonceLength
8179
}
8280

83-
if o.NonceLength > math.MaxInt {
84-
panic("invalid nonce length")
85-
}
86-
8781
if len(o.Nonce) == 0 {
88-
o.Nonce = internal.RandomBytes(int(o.NonceLength)) //nolint:gosec // overflow is checked beforehand.
82+
o.Nonce = internal.RandomBytes(int(o.NonceLength))
8983
}
9084
}
9185

internal/configuration.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ type Configuration struct {
3636
MAC *Mac
3737
Hash *Hash
3838
KSF *KSF
39-
KSFSalt []byte
4039
OPRF oprf.Identifier
4140
Context []byte
4241
NonceLen int

internal/hash.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ type KSF struct {
108108
type ksfInterface interface {
109109
// Harden uses default parameters for the key derivation function over the input password and salt.
110110
Harden(password, salt []byte, length int) []byte
111+
112+
// Parameterize replaces the functions parameters with the new ones.
113+
// Must match the amount of parameters for the KSF.
111114
Parameterize(parameters ...int)
112115
}
113116

0 commit comments

Comments
 (0)