-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
71b2ecc
commit 685c211
Showing
5 changed files
with
341 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
package utils | ||
|
||
import ( | ||
"errors" | ||
"strings" | ||
|
||
"github.com/iden3/iden3comm/v2" | ||
"github.com/iden3/iden3comm/v2/packers" | ||
"github.com/iden3/iden3comm/v2/protocol" | ||
) | ||
|
||
// ParseAcceptProfile parses the accept profile string and returns the AcceptProfile struct | ||
func ParseAcceptProfile(profile string) (protocol.AcceptProfile, error) { | ||
params := strings.Split(profile, ";") | ||
if len(params) < 2 { | ||
return protocol.AcceptProfile{}, errors.New("invalid accept profile value") | ||
} | ||
|
||
protocolVersion := strings.TrimSpace(params[0]) | ||
if !isProtocolVersion(protocolVersion) { | ||
return protocol.AcceptProfile{}, errors.New("protocol version '" + protocolVersion + "' not supported") | ||
} | ||
|
||
envParam := strings.Split(params[1], "=") | ||
if len(envParam) != 2 { | ||
return protocol.AcceptProfile{}, errors.New("invalid accept profile 'env' parameter") | ||
} | ||
|
||
env := strings.TrimSpace(envParam[1]) | ||
if !isMediaType(env) { | ||
return protocol.AcceptProfile{}, errors.New("envelop '" + env + "' not supported") | ||
} | ||
|
||
circuitsIndex := -1 | ||
for i, param := range params { | ||
if strings.Contains(param, "circuitId=") { | ||
circuitsIndex = i | ||
break | ||
} | ||
} | ||
|
||
if env != string(packers.MediaTypeZKPMessage) && circuitsIndex > 0 { | ||
return protocol.AcceptProfile{}, errors.New("circuits not supported for env '" + env + "'") | ||
} | ||
|
||
var circuits []protocol.AcceptAuthCircuits | ||
if circuitsIndex > 0 { | ||
circuitsStr := strings.Split(strings.Split(params[circuitsIndex], "=")[1], ",") | ||
for _, c := range circuitsStr { | ||
c = strings.TrimSpace(c) | ||
if !isAcceptAuthCircuits(c) { | ||
return protocol.AcceptProfile{}, errors.New("circuit '" + c + "' not supported") | ||
} | ||
circuits = append(circuits, protocol.AcceptAuthCircuits(c)) | ||
} | ||
} | ||
|
||
algIndex := -1 | ||
for i, param := range params { | ||
if strings.Contains(param, "alg=") { | ||
algIndex = i | ||
break | ||
} | ||
} | ||
|
||
var jwzAlgs []protocol.AcceptJwzAlgorithms | ||
var jwsAlgs []protocol.AcceptJwsAlgorithms | ||
var anoncryptAlgs []protocol.AcceptAnoncryptAlgorithms | ||
if algIndex > 0 { | ||
algStr := strings.Split(strings.Split(params[algIndex], "=")[1], ",") | ||
switch env { | ||
case string(packers.MediaTypeZKPMessage): | ||
for _, a := range algStr { | ||
a = strings.TrimSpace(a) | ||
if !isAcceptJwzAlgorithms(a) { | ||
return protocol.AcceptProfile{}, errors.New("algorithm '" + a + "' not supported for '" + env + "'") | ||
} | ||
jwzAlgs = append(jwzAlgs, protocol.AcceptJwzAlgorithms(a)) | ||
} | ||
case string(packers.MediaTypeSignedMessage): | ||
for _, a := range algStr { | ||
a = strings.TrimSpace(a) | ||
if !isAcceptJwsAlgorithms(a) { | ||
return protocol.AcceptProfile{}, errors.New("algorithm '" + a + "' not supported for '" + env + "'") | ||
} | ||
jwsAlgs = append(jwsAlgs, protocol.AcceptJwsAlgorithms(a)) | ||
} | ||
case string(packers.MediaTypeEncryptedMessage): | ||
for _, a := range algStr { | ||
a = strings.TrimSpace(a) | ||
if !isAcceptAnoncryptAlgorithms(a) { | ||
return protocol.AcceptProfile{}, errors.New("algorithm '" + a + "' not supported for '" + env + "'") | ||
} | ||
anoncryptAlgs = append(anoncryptAlgs, protocol.AcceptAnoncryptAlgorithms(a)) | ||
} | ||
default: | ||
return protocol.AcceptProfile{}, errors.New("algorithm not supported for '" + env + "'") | ||
} | ||
} | ||
|
||
return protocol.AcceptProfile{ | ||
ProtocolVersion: protocol.AcceptProtocolVersion(protocolVersion), | ||
Env: iden3comm.MediaType(env), | ||
Circuits: circuits, | ||
AcceptJwsAlgorithms: jwsAlgs, | ||
AcceptJwzAlgorithms: jwzAlgs, | ||
AcceptAnoncryptAlgorithms: anoncryptAlgs, | ||
}, nil | ||
} | ||
|
||
func isProtocolVersion(value string) bool { | ||
// List all possible protocol versions | ||
validVersions := []protocol.AcceptProtocolVersion{ | ||
protocol.ProtocolVersionV1, | ||
} | ||
for _, v := range validVersions { | ||
if protocol.AcceptProtocolVersion(value) == v { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func isAcceptAuthCircuits(value string) bool { | ||
// List all possible authentication circuits | ||
validCircuits := []protocol.AcceptAuthCircuits{ | ||
protocol.AcceptAuthCircuitsAuthV2, | ||
protocol.AcceptAuthCircuitsAuthV3, | ||
} | ||
for _, v := range validCircuits { | ||
if protocol.AcceptAuthCircuits(value) == v { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func isAcceptJwzAlgorithms(value string) bool { | ||
// List all possible JWZ algorithms | ||
validAlgorithms := []protocol.AcceptJwzAlgorithms{ | ||
protocol.AcceptJwzAlgorithmsGroth16, | ||
} | ||
for _, v := range validAlgorithms { | ||
if protocol.AcceptJwzAlgorithms(value) == v { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func isAcceptJwsAlgorithms(value string) bool { | ||
// List all possible JWS algorithms | ||
validAlgorithms := []protocol.AcceptJwsAlgorithms{ | ||
protocol.AcceptJwsAlgorithmsES256K, | ||
protocol.AcceptJwsAlgorithmsES256KR, | ||
} | ||
for _, v := range validAlgorithms { | ||
if protocol.AcceptJwsAlgorithms(value) == v { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func isAcceptAnoncryptAlgorithms(value string) bool { | ||
// List all possible Anoncrypt algorithms | ||
validAlgorithms := []protocol.AcceptAnoncryptAlgorithms{ | ||
protocol.AcceptAnoncryptECDHESA256KW, | ||
} | ||
for _, v := range validAlgorithms { | ||
if protocol.AcceptAnoncryptAlgorithms(value) == v { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func isMediaType(value string) bool { | ||
// List all possible JWS algorithms | ||
validAlgorithms := []iden3comm.MediaType{ | ||
packers.MediaTypeEncryptedMessage, | ||
packers.MediaTypePlainMessage, | ||
packers.MediaTypeZKPMessage, | ||
packers.MediaTypeSignedMessage, | ||
} | ||
for _, v := range validAlgorithms { | ||
if iden3comm.MediaType(value) == v { | ||
return true | ||
} | ||
} | ||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package utils | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
|
||
"github.com/iden3/iden3comm/v2/packers" | ||
"github.com/iden3/iden3comm/v2/protocol" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestAcceptProfileParser(t *testing.T) { | ||
type expected struct { | ||
profile protocol.AcceptProfile | ||
err error | ||
} | ||
for _, tc := range []struct { | ||
desc string | ||
accept string | ||
expected expected | ||
}{ | ||
{ | ||
desc: "Valid plain text accept profile", | ||
accept: "iden3comm/v1;env=application/iden3comm-plain-json", | ||
expected: expected{ | ||
profile: protocol.AcceptProfile{ | ||
ProtocolVersion: protocol.ProtocolVersionV1, | ||
Env: packers.MediaTypePlainMessage, | ||
}, | ||
}, | ||
}, | ||
{ | ||
desc: "Valid anoncrypt accept profile", | ||
accept: "iden3comm/v1;env=application/iden3comm-encrypted-json;alg=ECDH-ES+A256KW", | ||
expected: expected{ | ||
profile: protocol.AcceptProfile{ | ||
ProtocolVersion: protocol.ProtocolVersionV1, | ||
Env: packers.MediaTypeEncryptedMessage, | ||
AcceptAnoncryptAlgorithms: []protocol.AcceptAnoncryptAlgorithms{protocol.AcceptAnoncryptECDHESA256KW}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
desc: "Valid JWS accept profile", | ||
accept: "iden3comm/v1;env=application/iden3comm-signed-json;alg=ES256K-R", | ||
expected: expected{ | ||
profile: protocol.AcceptProfile{ | ||
ProtocolVersion: protocol.ProtocolVersionV1, | ||
Env: packers.MediaTypeSignedMessage, | ||
AcceptJwsAlgorithms: []protocol.AcceptJwsAlgorithms{protocol.AcceptJwsAlgorithmsES256KR}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
desc: "Valid JWZ accept profile", | ||
accept: "iden3comm/v1;env=application/iden3-zkp-json;circuitId=authV2,authV3;alg=groth16", | ||
expected: expected{ | ||
profile: protocol.AcceptProfile{ | ||
ProtocolVersion: protocol.ProtocolVersionV1, | ||
Env: packers.MediaTypeZKPMessage, | ||
AcceptJwzAlgorithms: []protocol.AcceptJwzAlgorithms{protocol.AcceptJwzAlgorithmsGroth16}, | ||
Circuits: []protocol.AcceptAuthCircuits{protocol.AcceptAuthCircuitsAuthV2, protocol.AcceptAuthCircuitsAuthV3}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
desc: "Invalid accept profile", | ||
accept: "iden3comm/v1", | ||
expected: expected{ | ||
err: errors.New("invalid accept profile value"), | ||
}, | ||
}, | ||
{ | ||
desc: "Invalid protocol version profile", | ||
accept: "iden3comm/v1000_000;env=application/iden3comm-plain-json", | ||
expected: expected{ | ||
err: errors.New("protocol version 'iden3comm/v1000_000' not supported"), | ||
}, | ||
}, | ||
{ | ||
desc: "Invalid envelop param", | ||
accept: "iden3comm/v1;application/iden3comm-plain-json", | ||
expected: expected{ | ||
err: errors.New("invalid accept profile 'env' parameter"), | ||
}, | ||
}, | ||
{ | ||
desc: "Invalid envelop", | ||
accept: "iden3comm/v1;env=application/iden3comm-rich-text", | ||
expected: expected{ | ||
err: errors.New("envelop 'application/iden3comm-rich-text' not supported"), | ||
}, | ||
}, | ||
{ | ||
desc: "Invalid circuit ID", | ||
accept: "iden3comm/v1;env=application/iden3-zkp-json;circuitId=authV2.5;alg=groth16", | ||
expected: expected{ | ||
err: errors.New("circuit 'authV2.5' not supported"), | ||
}, | ||
}, | ||
{ | ||
desc: "Invalid alg", | ||
accept: "iden3comm/v1;env=application/iden3-zkp-json;circuitId=authV2;alg=groth1", | ||
expected: expected{ | ||
err: errors.New("algorithm 'groth1' not supported for 'application/iden3-zkp-json'"), | ||
}, | ||
}, | ||
{ | ||
desc: "Alg for plain message", | ||
accept: "iden3comm/v1;env=application/iden3comm-plain-json;alg=someAlg", | ||
expected: expected{ | ||
err: errors.New("algorithm not supported for 'application/iden3comm-plain-json'"), | ||
}, | ||
}, | ||
} { | ||
t.Run(tc.desc, func(t *testing.T) { | ||
profile, err := ParseAcceptProfile(tc.accept) | ||
if tc.expected.err != nil { | ||
assert.Equal(t, err.Error(), tc.expected.err.Error()) | ||
} | ||
assert.Equal(t, profile, tc.expected.profile) | ||
}) | ||
} | ||
} |