-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use hash size as KSF output size, expose KSF parameters & salt in configuration #73
base: main
Are you sure you want to change the base?
Conversation
OPRF: opaque.RistrettoSha512, | ||
KDF: crypto.SHA512, | ||
MAC: crypto.SHA512, | ||
Hash: crypto.SHA512, | ||
KSF: opaque.KSFConfiguration{ | ||
Identifier: ksf.Argon2id, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OPRF: opaque.RistrettoSha512, | |
KDF: crypto.SHA512, | |
MAC: crypto.SHA512, | |
Hash: crypto.SHA512, | |
KSF: opaque.KSFConfiguration{ | |
Identifier: ksf.Argon2id, | |
}, | |
OPRF: opaque.RistrettoSha512, | |
KDF: crypto.SHA512, | |
MAC: crypto.SHA512, | |
Hash: crypto.SHA512, | |
KSF: opaque.KSFConfiguration{ | |
Identifier: ksf.Argon2id, | |
}, |
type KSFConfiguration struct { | ||
Identifier ksf.Identifier `json:"identifier"` | ||
Parameters []int `json:"parameters"` | ||
Salt []byte `json:"salt"` | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type KSFConfiguration struct { | |
Identifier ksf.Identifier `json:"identifier"` | |
Parameters []int `json:"parameters"` | |
Salt []byte `json:"salt"` | |
} | |
type KSFConfiguration struct { | |
Parameters []int `json:"parameters"` | |
Salt []byte `json:"salt"` | |
Identifier ksf.Identifier `json:"identifier"` | |
} | |
aligns better in memory
Parameters []int `json:"parameters"` | ||
Salt []byte `json:"salt"` | ||
} | ||
|
||
// Configuration represents an OPAQUE configuration. Note that OprfGroup and AKEGroup are recommended to be the same, | ||
// as well as KDF, MAC, Hash should be the same. | ||
type Configuration struct { | ||
Context []byte |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Context []byte |
KDF crypto.Hash `json:"kdf"` | ||
MAC crypto.Hash `json:"mac"` | ||
Hash crypto.Hash `json:"hash"` | ||
OPRF Group `json:"oprf"` | ||
KSF KSFConfiguration `json:"ksf"` | ||
AKE Group `json:"group"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
KDF crypto.Hash `json:"kdf"` | |
MAC crypto.Hash `json:"mac"` | |
Hash crypto.Hash `json:"hash"` | |
OPRF Group `json:"oprf"` | |
KSF KSFConfiguration `json:"ksf"` | |
AKE Group `json:"group"` | |
KSF KSFConfiguration `json:"ksf"` | |
Context []byte | |
KDF crypto.Hash `json:"kdf"` | |
MAC crypto.Hash `json:"mac"` | |
Hash crypto.Hash `json:"hash"` | |
OPRF Group `json:"oprf"` | |
KSF KSFConfiguration `json:"ksf"` | |
AKE Group `json:"group"` |
memory alignement
var ksfEncodedParams []byte | ||
for _, param := range c.KSF.Parameters { | ||
ksfEncodedParams = append(ksfEncodedParams, encoding.I2OSP(param, 4)...) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | |
} | |
@@ -228,21 +248,50 @@ func (c *Configuration) GetFakeRecord(credentialIdentifier []byte) (*ClientRecor | |||
|
|||
// DeserializeConfiguration decodes the input and returns a Parameter structure. | |||
func DeserializeConfiguration(encoded []byte) (*Configuration, error) { | |||
if len(encoded) < confLength+2 { // corresponds to the configuration length + 2-byte encoding of empty context | |||
if len(encoded) < confIdsLength+2 { // corresponds to the configuration length + 2-byte encoding of empty context |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if len(encoded) < confIdsLength+2 { // corresponds to the configuration length + 2-byte encoding of empty context | |
if len(encoded) < confIdsLength+6 { // corresponds to the configuration length + 3*2-byte encoding of empty context and KSF parameters |
return nil, internal.ErrConfigurationInvalidLength | ||
} | ||
|
||
ctx, _, err := encoding.DecodeVector(encoded[confLength:]) | ||
ctx, _, err := encoding.DecodeVector(encoded[confIdsLength:]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ctx, _, err := encoding.DecodeVector(encoded[confIdsLength:]) | |
ctx, offset, err := encoding.DecodeVector(encoded[confIdsLength:]) |
use the returned offset
var ksfParams []int | ||
ksfParamOffset := confIdsLength + 2 + len(ctx) | ||
|
||
if len(encoded) >= ksfParamOffset+2 { | ||
ksfEncodedParams, _, err := encoding.DecodeVector(encoded[ksfParamOffset:]) | ||
if err != nil { | ||
return nil, fmt.Errorf("decoding the ksf configuration parameters: %w", err) | ||
} | ||
for i := 0; i < len(ksfEncodedParams); i += 4 { | ||
ksfParams = append(ksfParams, encoding.OS2IP(ksfEncodedParams[i:i+4])) | ||
} | ||
} | ||
|
||
var ksfSalt []byte | ||
ksfSaltOffset := ksfParamOffset + 2 + (len(ksfParams) * 4) | ||
if len(encoded) >= ksfSaltOffset+2 { | ||
ksfSalt, _, err = encoding.DecodeVector(encoded[ksfSaltOffset:]) | ||
if err != nil { | ||
return nil, fmt.Errorf("decoding the ksf salt: %w", err) | ||
} | ||
if len(ksfSalt) == 0 { | ||
ksfSalt = nil | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var ksfParams []int | |
ksfParamOffset := confIdsLength + 2 + len(ctx) | |
if len(encoded) >= ksfParamOffset+2 { | |
ksfEncodedParams, _, err := encoding.DecodeVector(encoded[ksfParamOffset:]) | |
if err != nil { | |
return nil, fmt.Errorf("decoding the ksf configuration parameters: %w", err) | |
} | |
for i := 0; i < len(ksfEncodedParams); i += 4 { | |
ksfParams = append(ksfParams, encoding.OS2IP(ksfEncodedParams[i:i+4])) | |
} | |
} | |
var ksfSalt []byte | |
ksfSaltOffset := ksfParamOffset + 2 + (len(ksfParams) * 4) | |
if len(encoded) >= ksfSaltOffset+2 { | |
ksfSalt, _, err = encoding.DecodeVector(encoded[ksfSaltOffset:]) | |
if err != nil { | |
return nil, fmt.Errorf("decoding the ksf salt: %w", err) | |
} | |
if len(ksfSalt) == 0 { | |
ksfSalt = nil | |
} | |
} | |
offset += confIdsLength | |
ksfEncodedParams, offsetKSF, err := encoding.DecodeVector(encoded[offset:]) | |
if err != nil { | |
return nil, fmt.Errorf("decoding the ksf configuration parameters: %w", err) | |
} | |
offset += offsetKSF | |
var ksfParams []int | |
for i := 0; i < len(ksfEncodedParams); i += 4 { | |
ksfParams = append(ksfParams, encoding.OS2IP(ksfEncodedParams[i:i+4])) | |
} | |
ksfSalt, _, err := encoding.DecodeVector(encoded[offset:]) | |
if err != nil { | |
return nil, fmt.Errorf("decoding the ksf salt: %w", err) | |
} | |
if len(ksfSalt) == 0 { | |
ksfSalt = nil | |
} |
we can use the offset argument returned by DecodeVector
func TestDeserializeConfiguration_InvalidContextHeader(t *testing.T) { | ||
d := opaque.DefaultConfiguration().Serialize() | ||
d[7] = 3 | ||
|
||
expected := "decoding the configuration context: " | ||
if _, err := opaque.DeserializeConfiguration(d); err == nil || !strings.HasPrefix(err.Error(), expected) { | ||
t.Errorf( | ||
"DeserializeConfiguration did not return the appropriate error for vector invalid header. want %q, got %q", | ||
expected, | ||
err, | ||
) | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we should keep this error detection test.
Hi @DJAndries ! Thank you for this PR, this is an excellent contribution :) I left some comments for some minor code changes. |
Have you noticed other differences in Kevin's implementation that would be interesting to add here? |
A couple of changes to achieve interoperability with facebook/opaque-ke: