Skip to content

Commit

Permalink
add new vector; update code for vectors besides gateways
Browse files Browse the repository at this point in the history
  • Loading branch information
gabe committed Apr 2, 2024
1 parent a8b8917 commit a962d4e
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 39 deletions.
2 changes: 1 addition & 1 deletion impl/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.22

require (
github.com/BurntSushi/toml v1.3.2
github.com/TBD54566975/ssi-sdk v0.0.4-alpha.0.20240321215515-97ccd06a631d
github.com/TBD54566975/ssi-sdk v0.0.4-alpha.0.20240402005820-2c6b20991baa
github.com/allegro/bigcache/v3 v3.1.0
github.com/anacrolix/dht/v2 v2.21.1
github.com/anacrolix/log v0.15.2
Expand Down
8 changes: 6 additions & 2 deletions impl/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ github.com/RoaringBitmap/roaring v0.4.17/go.mod h1:D3qVegWTmfCaX4Bl5CrBE9hfrSrrX
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/TBD54566975/ssi-sdk v0.0.4-alpha.0.20240321215515-97ccd06a631d h1:lEekCCpwjxtQBNNUoUmPiDg35t3quQzDgtetug5xbx4=
github.com/TBD54566975/ssi-sdk v0.0.4-alpha.0.20240321215515-97ccd06a631d/go.mod h1:UoNlAhXuPb1VxsAkNbLyr4XYeyHhLvcwSbkmsaOeGjM=
github.com/TBD54566975/ssi-sdk v0.0.4-alpha.0.20240401231222-6550aeed8a9d h1:M/dYJOKyLNBDh97VYAyLvzO7sS01K1eIBwNcAK2SFDQ=
github.com/TBD54566975/ssi-sdk v0.0.4-alpha.0.20240401231222-6550aeed8a9d/go.mod h1:nyTjplXnrari2nQg63ztI4C0rgMb7Jjn3gfn0OM656g=
github.com/TBD54566975/ssi-sdk v0.0.4-alpha.0.20240402005210-f282aecaa186 h1:XIaS0WBSrg2wU00Cx45NO9H3x3ca7WEI35sSef6NC5c=
github.com/TBD54566975/ssi-sdk v0.0.4-alpha.0.20240402005210-f282aecaa186/go.mod h1:nyTjplXnrari2nQg63ztI4C0rgMb7Jjn3gfn0OM656g=
github.com/TBD54566975/ssi-sdk v0.0.4-alpha.0.20240402005820-2c6b20991baa h1:1kJozfMxe8fRI0jjKUbKhj7/o16d1oTDOfZJLOMTU28=
github.com/TBD54566975/ssi-sdk v0.0.4-alpha.0.20240402005820-2c6b20991baa/go.mod h1:nyTjplXnrari2nQg63ztI4C0rgMb7Jjn3gfn0OM656g=
github.com/alecthomas/assert/v2 v2.0.0-alpha3 h1:pcHeMvQ3OMstAWgaeaXIAL8uzB9xMm2zlxt+/4ml8lk=
github.com/alecthomas/assert/v2 v2.0.0-alpha3/go.mod h1:+zD0lmDXTeQj7TgDgCt0ePWxb0hMC1G+PGTsTCv1B9o=
github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8=
Expand Down
74 changes: 59 additions & 15 deletions impl/internal/did/did.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/TBD54566975/ssi-sdk/crypto/jwx"
"github.com/TBD54566975/ssi-sdk/cryptosuite"
"github.com/TBD54566975/ssi-sdk/did"
"github.com/lestrrat-go/jwx/v2/jwa"
"github.com/miekg/dns"
"github.com/tv42/zbase32"
)
Expand All @@ -22,9 +23,8 @@ type (

const (
// Prefix did:dht prefix
Prefix = "did:dht"
DHTMethod did.Method = "dht"
JSONWebKeyType cryptosuite.LDKeyType = "JsonWebKey"
Prefix = "did:dht"
DHTMethod did.Method = "dht"

// Version corresponds to the version fo the specification https://did-dht.com/#dids-as-dns-records
Version int = 0
Expand Down Expand Up @@ -137,7 +137,7 @@ func CreateDIDDHTDID(pubKey ed25519.PublicKey, opts CreateDIDDHTOpts) (*did.Docu
if seenIDs[vm.VerificationMethod.ID] {
return nil, fmt.Errorf("verification method id %s is not unique", vm.VerificationMethod.ID)
}
if vm.VerificationMethod.Type != JSONWebKeyType {
if vm.VerificationMethod.Type != cryptosuite.JSONWebKeyType {
return nil, fmt.Errorf("verification method type %s is not supported", vm.VerificationMethod.Type)
}
if vm.VerificationMethod.PublicKeyJWK == nil {
Expand Down Expand Up @@ -204,12 +204,14 @@ func CreateDIDDHTDID(pubKey ed25519.PublicKey, opts CreateDIDDHTOpts) (*did.Docu
// create the did document
kid := "0"
key0JWK, err := jwx.PublicKeyToPublicKeyJWK(&kid, pubKey)
// temporary workaround until https://github.com/TBD54566975/ssi-sdk/issues/520 is in place
key0JWK.ALG = string(crypto.Ed25519DSA)
if err != nil {
return nil, err
}
vm0 := did.VerificationMethod{
ID: id + "#0",
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
Controller: id,
PublicKeyJWK: key0JWK,
}
Expand Down Expand Up @@ -287,9 +289,9 @@ func (d DHT) ToDNSPacket(doc did.Document, types []TypeIndex) (*dns.Msg, error)
recordIdentifier := fmt.Sprintf("k%d", i)
keyLookup[vm.ID] = recordIdentifier

keyType := keyTypeByAlg(crypto.SignatureAlgorithm(vm.PublicKeyJWK.ALG))
keyType := keyTypeForJWK(*vm.PublicKeyJWK)
if keyType < 0 {
return nil, fmt.Errorf("unsupported key type given alg: %s", vm.PublicKeyJWK.ALG)
return nil, fmt.Errorf("+unsupported key type given alg: %s", vm.PublicKeyJWK.ALG)
}

// convert the public key to a base64url encoded string
Expand All @@ -307,6 +309,13 @@ func (d DHT) ToDNSPacket(doc did.Document, types []TypeIndex) (*dns.Msg, error)
keyBase64URL := base64.RawURLEncoding.EncodeToString(pubKeyBytes)
vmKeyFragment := vm.ID[strings.LastIndex(vm.ID, "#")+1:]
txtRecord := fmt.Sprintf("id=%s;t=%d;k=%s", vmKeyFragment, keyType, keyBase64URL)

// only include the alg if it's not the default alg for the key type
forKeyType := algIsDefaultForKeyType(*vm.PublicKeyJWK)
if !forKeyType {
txtRecord += fmt.Sprintf(";alg=%s", vm.PublicKeyJWK.ALG)
}

// note the controller if it differs from the DID
if vm.Controller != doc.ID {
// handle the case where the controller of the identity key is not the DID itself
Expand Down Expand Up @@ -531,7 +540,7 @@ func (d DHT) FromDNSPacket(msg *dns.Msg) (*did.Document, []TypeIndex, error) {

vm := did.VerificationMethod{
ID: d.String() + "#" + vmID,
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
Controller: d.String(),
PublicKeyJWK: pubKeyJWK,
}
Expand Down Expand Up @@ -647,6 +656,30 @@ func parseTxtData(data string) map[string]string {
return result
}

// algIsDefaultForKeyType returns true if the given JWK ALG is the default for the given key type
// according to the key type index https://did-dht.com/registry/#key-type-index
func algIsDefaultForKeyType(jwk jwx.PublicKeyJWK) bool {
// Ed25519 : Ed25519
if jwk.CRV == crypto.Ed25519.String() && jwk.KTY == jwa.OKP.String() {
return jwk.ALG == string(crypto.Ed25519DSA)
}
// secp256k1 : ES256K
if jwk.CRV == crypto.SECP256k1.String() && jwk.KTY == jwa.EC.String() {
return jwk.ALG == string(crypto.ES256K)
}
// P-256 : ES256
if jwk.CRV == crypto.P256.String() && jwk.KTY == jwa.EC.String() {
return jwk.ALG == string(crypto.ES256)
}
// X25519 : ECDH-ES+A256KW
if jwk.CRV == crypto.X25519.String() && jwk.KTY == jwa.OKP.String() {
return jwk.ALG == string(crypto.ECDHESA256KW)
}
return false
}

// keyTypeLookUp returns the key type for the given key type index
// https://did-dht.com/registry/#key-type-index
func keyTypeLookUp(keyType string) crypto.KeyType {
switch keyType {
case "0":
Expand All @@ -655,20 +688,31 @@ func keyTypeLookUp(keyType string) crypto.KeyType {
return crypto.SECP256k1
case "2":
return crypto.P256
case "3":
return crypto.X25519
default:
return ""
}
}

func keyTypeByAlg(alg crypto.SignatureAlgorithm) int {
switch alg {
case crypto.EdDSA:
// keyTypeForJWK returns the key type index for the given JWK according to the key type index
// https://did-dht.com/registry/#key-type-index
func keyTypeForJWK(jwk jwx.PublicKeyJWK) int {
// Ed25519 : Ed25519 : 0
if jwk.CRV == crypto.Ed25519.String() && jwk.KTY == jwa.OKP.String() {
return 0
case crypto.ES256K:
}
// secp256k1 : ES256K : 1
if jwk.CRV == crypto.SECP256k1.String() && jwk.KTY == jwa.EC.String() {
return 1
case crypto.ES256:
}
// P-256 : ES256 : 2
if jwk.CRV == crypto.P256.String() && jwk.KTY == jwa.EC.String() {
return 2
default:
return -1
}
// X25519 : ECDH-ES+A256KW : 3
if jwk.CRV == crypto.X25519.String() && jwk.KTY == jwa.OKP.String() {
return 3
}
return -1
}
84 changes: 71 additions & 13 deletions impl/internal/did/did_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"testing"

"github.com/TBD54566975/ssi-sdk/cryptosuite"
"github.com/goccy/go-json"

"github.com/TBD54566975/ssi-sdk/crypto"
Expand Down Expand Up @@ -55,7 +56,7 @@ func TestGenerateDIDDHT(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: "key1",
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
Controller: "did:dht:123456789abcdefghi",
PublicKeyJWK: pubKeyJWK,
},
Expand Down Expand Up @@ -173,7 +174,7 @@ func TestToDNSPacket(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: "key1",
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: pubKeyJWK,
},
Purposes: []did.PublicKeyPurpose{did.AssertionMethod, did.CapabilityInvocation},
Expand Down Expand Up @@ -277,7 +278,7 @@ func TestVectors(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: secpJWK.KID,
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &secpJWK,
},
Purposes: []did.PublicKeyPurpose{did.AssertionMethod, did.CapabilityInvocation},
Expand Down Expand Up @@ -323,6 +324,63 @@ func TestVectors(t *testing.T) {
assert.Contains(t, s, expectedRecord.Record)
}
})

t.Run("test vector 3", func(t *testing.T) {
var pubKeyJWK jwx.PublicKeyJWK
retrieveTestVectorAs(t, vector3PublicKeyJWK1, &pubKeyJWK)

pubKey, err := pubKeyJWK.ToPublicKey()
require.NoError(t, err)

var x25519JWK jwx.PublicKeyJWK
retrieveTestVectorAs(t, vector3PublicKeyJWK2, &x25519JWK)

doc, err := CreateDIDDHTDID(pubKey.(ed25519.PublicKey), CreateDIDDHTOpts{
VerificationMethods: []VerificationMethod{
{
VerificationMethod: did.VerificationMethod{
ID: x25519JWK.KID,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &x25519JWK,
},
Purposes: []did.PublicKeyPurpose{did.KeyAgreement},
},
},
})
require.NoError(t, err)
require.NotEmpty(t, doc)

var expectedDIDDocument did.Document
retrieveTestVectorAs(t, vector3DIDDocument, &expectedDIDDocument)

docJSON, err := json.Marshal(doc)
require.NoError(t, err)

expectedDIDDocJSON, err := json.Marshal(expectedDIDDocument)
require.NoError(t, err)

assert.JSONEq(t, string(expectedDIDDocJSON), string(docJSON))

didID := DHT(doc.ID)
packet, err := didID.ToDNSPacket(*doc, nil)
require.NoError(t, err)
require.NotEmpty(t, packet)

println(packet.String())

var expectedDNSRecords map[string]testVectorDNSRecord
retrieveTestVectorAs(t, vector3DNSRecords, &expectedDNSRecords)

for _, record := range packet.Answer {
expectedRecord, ok := expectedDNSRecords[record.Header().Name]
require.True(t, ok, "record not found: %s", record.Header().Name)

s := record.String()
assert.Contains(t, s, expectedRecord.RecordType)
assert.Contains(t, s, expectedRecord.TTL)
assert.Contains(t, s, expectedRecord.Record)
}
})
}

func TestMisc(t *testing.T) {
Expand Down Expand Up @@ -353,7 +411,7 @@ func TestMisc(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: secpJWK.KID,
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &secpJWK,
},
Purposes: []did.PublicKeyPurpose{did.AssertionMethod, did.CapabilityInvocation},
Expand All @@ -378,7 +436,7 @@ func TestMisc(t *testing.T) {
VerificationMethods: []VerificationMethod{
{
VerificationMethod: did.VerificationMethod{
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &secpJWK,
},
Purposes: []did.PublicKeyPurpose{did.AssertionMethod, did.CapabilityInvocation},
Expand All @@ -404,7 +462,7 @@ func TestMisc(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: secpJWK.KID,
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &secpJWK,
},
Purposes: []did.PublicKeyPurpose{did.AssertionMethod, did.CapabilityInvocation},
Expand All @@ -430,7 +488,7 @@ func TestMisc(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: "#key-1",
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &secpJWK,
},
Purposes: []did.PublicKeyPurpose{did.AssertionMethod, did.CapabilityInvocation},
Expand All @@ -456,7 +514,7 @@ func TestMisc(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: secpJWK.KID,
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &secpJWK,
},
Purposes: []did.PublicKeyPurpose{did.Authentication, did.KeyAgreement, did.CapabilityDelegation},
Expand Down Expand Up @@ -493,7 +551,7 @@ func TestCreationFailures(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: "#0",
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &secpJWK,
},
Purposes: []did.PublicKeyPurpose{did.AssertionMethod, did.CapabilityInvocation},
Expand All @@ -518,15 +576,15 @@ func TestCreationFailures(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: secpJWK.KID,
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &secpJWK,
},
Purposes: []did.PublicKeyPurpose{did.AssertionMethod, did.CapabilityInvocation},
},
{
VerificationMethod: did.VerificationMethod{
ID: secpJWK.KID,
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &secpJWK,
},
Purposes: []did.PublicKeyPurpose{did.AssertionMethod, did.CapabilityInvocation},
Expand Down Expand Up @@ -578,7 +636,7 @@ func TestCreationFailures(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: secpJWK.KID,
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: nil,
},
Purposes: []did.PublicKeyPurpose{did.AssertionMethod, did.CapabilityInvocation},
Expand All @@ -604,7 +662,7 @@ func TestCreationFailures(t *testing.T) {
{
VerificationMethod: did.VerificationMethod{
ID: secpJWK.KID,
Type: JSONWebKeyType,
Type: cryptosuite.JSONWebKeyType,
PublicKeyJWK: &secpJWK,
},
Purposes: []did.PublicKeyPurpose{"fake purpose"},
Expand Down
2 changes: 1 addition & 1 deletion impl/internal/did/testdata/vector-1-did-document.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"kty": "OKP",
"crv": "Ed25519",
"x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE",
"alg": "EdDSA",
"alg": "Ed25519",
"kid": "0"
}
}
Expand Down
2 changes: 1 addition & 1 deletion impl/internal/did/testdata/vector-1-public-key-jwk-1.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"kty": "OKP",
"crv": "Ed25519",
"x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE",
"alg": "EdDSA",
"alg": "Ed25519",
"kid": "0"
}
2 changes: 1 addition & 1 deletion impl/internal/did/testdata/vector-2-did-document.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"kty": "OKP",
"crv": "Ed25519",
"x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE",
"alg": "EdDSA",
"alg": "Ed25519",
"kid": "0"
}
},
Expand Down
Loading

0 comments on commit a962d4e

Please sign in to comment.