Skip to content
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

Introduce x509 DID method with PKI validation. #3446

Merged
merged 56 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
fc5ed34
Introduce x509 DID method with PKI validation.
rolandgroen Oct 3, 2024
62e3047
Fix variable assignment error in verifier.go
rolandgroen Oct 10, 2024
5565996
Refactor resolver and add SAN validation
rolandgroen Oct 10, 2024
8dea4f0
Add detailed error handling and improve certificate validation
rolandgroen Oct 11, 2024
79e77f3
Add certificate chain and resolver test utilities
rolandgroen Oct 11, 2024
d206def
Remove redundant closing braces in resolver_test.go
rolandgroen Oct 11, 2024
b4f4a0b
Refactor certificate creation with helper functions
rolandgroen Oct 25, 2024
a5520b6
Refactor metadata to use JwtProtectedHeaders map
rolandgroen Oct 28, 2024
c1ec60a
Refactor variable name in x509_utils.go
rolandgroen Oct 28, 2024
9c53345
Refactor and extend x509 DID resolver with new policy types
rolandgroen Oct 28, 2024
38c36a9
Add detailed error handling for subject policy in resolver
rolandgroen Oct 28, 2024
85c3de8
Improve URL unescaping logic and add robust error handling
rolandgroen Oct 28, 2024
330e12f
Add support for State and Street subject policies
rolandgroen Oct 28, 2024
ec97ed7
Update test utilities and resolver with generic examples
rolandgroen Oct 28, 2024
2c4997b
Fix function name case for SAN processing
rolandgroen Oct 28, 2024
453b8ec
Update vdr/didx509/x509_utils.go
rolandgroen Oct 28, 2024
477cfa4
Refine test descriptions for clarity
rolandgroen Oct 28, 2024
0a5d341
Add ExtractProtectedHeaders utility and refactor usage
rolandgroen Oct 29, 2024
a01b263
Refactor and improve ExtractProtectedHeaders function
rolandgroen Oct 29, 2024
3b5312a
CodeClimate: Refactor policy validation for clarity and reuse
rolandgroen Oct 29, 2024
871efea
Add X.509 certificate validation logic
rolandgroen Oct 29, 2024
16f2c20
Update vdr/didx509/x509_utils.go
rolandgroen Oct 29, 2024
78a2b80
Add missing authentication method and correct key agreement order
rolandgroen Oct 29, 2024
b3f0781
Remove unused SHA3 import from x509_utils.go
rolandgroen Oct 29, 2024
c3bcca0
Add fragment to DID URL in DID document creation
rolandgroen Oct 29, 2024
9b0c1f8
Update hash function to use sha512.Sum384
rolandgroen Oct 29, 2024
6b03762
Add PolicyNone handling in validation and resolver functions
rolandgroen Oct 29, 2024
832ebc2
Rename x509_test_utils.go to x509_utils_test.go
rolandgroen Oct 29, 2024
997edcc
Refactor policy validation to support multiple policies.
rolandgroen Oct 29, 2024
777ab5d
Refactor error assertion order in resolver tests
rolandgroen Oct 29, 2024
ce7179d
Fix certificate chain order in signature verifier test
rolandgroen Oct 29, 2024
c53281c
Refactor SAN value extraction logic.
rolandgroen Oct 29, 2024
953f917
Refactor ExtractProtectedHeaders and add failure test.
rolandgroen Oct 30, 2024
dda54b6
Add tests for x509 credential verification
rolandgroen Oct 30, 2024
3bb4ca7
Add validation for JWT signature count in ExtractProtectedHeaders
rolandgroen Oct 30, 2024
08b5c6e
Add error handling for missing x5t and x5t#S256 headers
rolandgroen Oct 30, 2024
5f654c0
Remove outdated comment from ExtractProtectedHeaders function
rolandgroen Oct 30, 2024
5d0a627
Improve error assertion style in resolver tests
rolandgroen Oct 30, 2024
efab4bf
Switch to `assert.EqualError` for error assertions
rolandgroen Oct 30, 2024
f05f2dc
Remove unused Return calls in resolver tests
rolandgroen Oct 30, 2024
9a80a81
Refactor error handling and add new test cases for cert utilities
rolandgroen Nov 1, 2024
fc20b9e
Add tests for ResolveMetadata protected header methods
rolandgroen Nov 1, 2024
89ebc2d
Merge branch 'master' into x509
rolandgroen Nov 1, 2024
b04da52
Update validation method to ValidateStrict fot x509
rolandgroen Nov 2, 2024
4e2c3ca
Add GPLv3 license headers to all source files.
rolandgroen Nov 4, 2024
bc424a7
Add comments for constants, errors, and functions
rolandgroen Nov 4, 2024
cb9d4ac
Made ValidatePolicy private
rolandgroen Nov 4, 2024
104af82
Added documentation for both GetProtectedHeaderString and GetProtecte…
rolandgroen Nov 4, 2024
6b1208f
Document the resolve method.
rolandgroen Nov 4, 2024
0f9723c
Move ExtractProtectedHeaders function to the crypto package
rolandgroen Nov 4, 2024
4ada7aa
Merge branch 'master' into x509
rolandgroen Nov 4, 2024
eded558
Support multiple SAN OtherName values in certificates
rolandgroen Nov 5, 2024
f9d5f5c
Merge branch 'master' into x509
rolandgroen Nov 5, 2024
69d17de
Add support for did:x509 format
rolandgroen Nov 5, 2024
ca6da44
Fix alignment of pkiValidator field
rolandgroen Nov 5, 2024
8570569
Fix issue with other types of SAN values
rolandgroen Nov 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion auth/client/iam/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ type testKeyResolver struct {
key *ecdsa.PrivateKey
}

func (t testKeyResolver) ResolveKeyByID(keyID string, validAt *time.Time, relationType resolver.RelationType) (crypto.PublicKey, error) {
func (t testKeyResolver) ResolveKeyByID(keyID string, metadata *resolver.ResolveMetadata, relationType resolver.RelationType) (crypto.PublicKey, error) {
return t.key.Public(), nil
}

Expand Down
5 changes: 4 additions & 1 deletion auth/services/oauth/authz_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,10 @@ func (s *authzServer) validateIssuer(vContext *validationContext) error {
}

validationTime := vContext.jwtBearerToken.IssuedAt()
if _, err := s.keyResolver.ResolveKeyByID(vContext.kid, &validationTime, resolver.NutsSigningKeyType); err != nil {
metadata := &resolver.ResolveMetadata{
ResolveTime: &validationTime,
}
if _, err := s.keyResolver.ResolveKeyByID(vContext.kid, metadata, resolver.NutsSigningKeyType); err != nil {
return fmt.Errorf(errInvalidIssuerKeyFmt, err)
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func CreateSystem(shutdownCallback context.CancelFunc) *core.System {
didStore := didstore.New(storageInstance.GetProvider(vdr.ModuleName))
eventManager := events.NewManager()
networkInstance := network.NewNetworkInstance(network.DefaultConfig(), didStore, cryptoInstance, eventManager, storageInstance.GetProvider(network.ModuleName), pkiInstance)
vdrInstance := vdr.NewVDR(cryptoInstance, networkInstance, didStore, eventManager, storageInstance)
vdrInstance := vdr.NewVDR(cryptoInstance, networkInstance, didStore, eventManager, storageInstance, pkiInstance)
credentialInstance := vcr.NewVCRInstance(cryptoInstance, vdrInstance, networkInstance, jsonld, eventManager, storageInstance, pkiInstance)
didmanInstance := didman.NewDidmanInstance(vdrInstance, credentialInstance, jsonld)
discoveryInstance := discovery.New(storageInstance, credentialInstance, vdrInstance, vdrInstance)
Expand Down
5 changes: 4 additions & 1 deletion crypto/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ func (w *Wrapper) resolvePublicKey(id *did.DIDURL) (key crypt.PublicKey, keyID s
if id.Fragment != "" {
// Assume it is a keyId
now := time.Now()
key, err = w.K.ResolveKeyByID(id.String(), &now, resolver.KeyAgreement)
metadata := &resolver.ResolveMetadata{
ResolveTime: &now,
}
key, err = w.K.ResolveKeyByID(id.String(), metadata, resolver.KeyAgreement)
if err != nil {
return nil, "", err
}
Expand Down
12 changes: 9 additions & 3 deletions vcr/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ func NewTestVCRContext(t *testing.T, keyStore crypto.KeyStore) TestVCRContext {
storageEngine := storage.NewTestStorageEngine(t)
networkInstance := network.NewTestNetworkInstance(t)
eventManager := events.NewTestManager(t)
vdrInstance := vdr.NewVDR(keyStore, networkInstance, didStore, eventManager, storageEngine)
ctrl := gomock.NewController(t)
pkiMock := pki.NewMockValidator(ctrl)
vdrInstance := vdr.NewVDR(keyStore, networkInstance, didStore, eventManager, storageEngine, pkiMock)
err := vdrInstance.Configure(core.TestServerConfig())
require.NoError(t, err)
newInstance := NewVCRInstance(
Expand Down Expand Up @@ -103,7 +105,9 @@ func NewTestVCRInstance(t *testing.T) *vcr {
config.Datadir = testDirectory
})
_ = networkInstance.Configure(serverCfg)
vdrInstance := vdr.NewVDR(keyStore, networkInstance, didStore, eventManager, storageEngine)
ctrl := gomock.NewController(t)
pkiMock := pki.NewMockValidator(ctrl)
vdrInstance := vdr.NewVDR(keyStore, networkInstance, didStore, eventManager, storageEngine, pkiMock)
err := vdrInstance.Configure(serverCfg)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -132,7 +136,9 @@ func NewTestVCRInstanceInDir(t *testing.T, testDirectory string) *vcr {
storageEngine := storage.NewTestStorageEngineInDir(t, testDirectory)
networkInstance := network.NewTestNetworkInstance(t)
eventManager := events.NewTestManager(t)
vdrInstance := vdr.NewVDR(nil, networkInstance, didStore, eventManager, storageEngine)
ctrl := gomock.NewController(t)
pkiMock := pki.NewMockValidator(ctrl)
vdrInstance := vdr.NewVDR(nil, networkInstance, didStore, eventManager, storageEngine, pkiMock)
err := vdrInstance.Configure(core.TestServerConfig())
if err != nil {
t.Fatal(err)
Expand Down
22 changes: 18 additions & 4 deletions vcr/verifier/signature_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
crypt "crypto"
"errors"
"fmt"
"github.com/nuts-foundation/nuts-node/vdr/didx509"
"strings"
"time"

Expand All @@ -41,6 +42,8 @@ type signatureVerifier struct {
jsonldManager jsonld.JSONLD
}

var ExtractProtectedHeaders = didx509.ExtractProtectedHeaders

// VerifySignature checks if the signature on a VP is valid at a given time
func (sv *signatureVerifier) VerifySignature(credentialToVerify vc.VerifiableCredential, validateAt *time.Time) error {
switch credentialToVerify.Format() {
Expand Down Expand Up @@ -102,7 +105,10 @@ func (sv *signatureVerifier) jsonldProof(documentToVerify any, issuer string, at
}

// find key
signingKey, err := sv.keyResolver.ResolveKeyByID(ldProof.VerificationMethod.String(), at, resolver.NutsSigningKeyType)
metadata := &resolver.ResolveMetadata{
ResolveTime: at,
}
signingKey, err := sv.keyResolver.ResolveKeyByID(ldProof.VerificationMethod.String(), metadata, resolver.NutsSigningKeyType)
if err != nil {
return fmt.Errorf("unable to resolve valid signing key: %w", err)
}
Expand All @@ -119,7 +125,15 @@ func (sv *signatureVerifier) jwtSignature(jwtDocumentToVerify string, issuer str
var keyID string
_, err := crypto.ParseJWT(jwtDocumentToVerify, func(kid string) (crypt.PublicKey, error) {
keyID = kid
return sv.resolveSigningKey(kid, issuer, at)
metadata := &resolver.ResolveMetadata{
ResolveTime: at,
}
headers, err := ExtractProtectedHeaders(jwtDocumentToVerify)
if err != nil {
return nil, err
}
rolandgroen marked this conversation as resolved.
Show resolved Hide resolved
metadata.JwtProtectedHeaders = headers
return sv.resolveSigningKey(kid, issuer, metadata)
}, jwt.WithClock(jwt.ClockFunc(func() time.Time {
if at == nil {
return time.Now()
Expand All @@ -135,7 +149,7 @@ func (sv *signatureVerifier) jwtSignature(jwtDocumentToVerify string, issuer str
return nil
}

func (sv *signatureVerifier) resolveSigningKey(kid string, issuer string, at *time.Time) (crypt.PublicKey, error) {
func (sv *signatureVerifier) resolveSigningKey(kid string, issuer string, metadata *resolver.ResolveMetadata) (crypt.PublicKey, error) {
// Compatibility: VC data model v1 puts key discovery out of scope and does not require the `kid` header.
// When `kid` isn't present use the JWT issuer as `kid`, then it is at least compatible with DID methods that contain a single verification method (did:jwk).
if kid == "" {
Expand All @@ -144,5 +158,5 @@ func (sv *signatureVerifier) resolveSigningKey(kid string, issuer string, at *ti
if strings.HasPrefix(kid, "did:jwk:") && !strings.Contains(kid, "#") {
kid += "#0"
}
return sv.keyResolver.ResolveKeyByID(kid, at, resolver.NutsSigningKeyType)
return sv.keyResolver.ResolveKeyByID(kid, metadata, resolver.NutsSigningKeyType)
}
Loading
Loading