From c8dd603ffb248f4785d9c07e9dc6d685b20840b0 Mon Sep 17 00:00:00 2001 From: Roland Groen Date: Mon, 14 Oct 2024 13:18:51 +0200 Subject: [PATCH 1/6] Move FixChainHeaders from x509_test_utils.go to x509_cert.go Relocate the FixChainHeaders function to x509_cert.go to align better with its primary responsibility and remove redundant import of the "strings" package from x509_test_utils.go. This change enhances code organization and ensures function relevance within the appropriate file. --- x509_cert/x509_cert.go | 17 +++++++++++++++++ x509_cert/x509_test_utils.go | 16 ---------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/x509_cert/x509_cert.go b/x509_cert/x509_cert.go index d042b6d..8721604 100644 --- a/x509_cert/x509_cert.go +++ b/x509_cert/x509_cert.go @@ -8,7 +8,9 @@ import ( "crypto/x509" "encoding/asn1" "fmt" + "github.com/lestrrat-go/jwx/v2/cert" "golang.org/x/crypto/sha3" + "strings" ) // SubjectAlternativeNameType represents the ASN.1 Object Identifier for Subject Alternative Name. @@ -91,3 +93,18 @@ func (c DefaultChainParser) ParsePrivateKey(der *[]byte) (*rsa.PrivateKey, error } return key.(*rsa.PrivateKey), err } + +// fixChainHeaders replaces newline characters in the certificate chain headers with escaped newline sequences. +// It processes each certificate in the provided chain and returns a new chain with the modified headers or an error if any occurs. +func FixChainHeaders(chain *cert.Chain) (*cert.Chain, error) { + rv := &cert.Chain{} + for i := 0; i < chain.Len(); i++ { + value, _ := chain.Get(i) + der := strings.ReplaceAll(string(value), "\n", "\\n") + err := rv.AddString(der) + if err != nil { + return nil, err + } + } + return rv, nil +} diff --git a/x509_cert/x509_test_utils.go b/x509_cert/x509_test_utils.go index 9bf4ce9..8fb50a1 100644 --- a/x509_cert/x509_test_utils.go +++ b/x509_cert/x509_test_utils.go @@ -10,7 +10,6 @@ import ( "fmt" "github.com/lestrrat-go/jwx/v2/cert" "math/big" - "strings" "time" ) @@ -263,18 +262,3 @@ func DebugUnmarshall(data []byte, depth int) error { return nil } - -// fixChainHeaders replaces newline characters in the certificate chain headers with escaped newline sequences. -// It processes each certificate in the provided chain and returns a new chain with the modified headers or an error if any occurs. -func FixChainHeaders(chain *cert.Chain) (*cert.Chain, error) { - rv := &cert.Chain{} - for i := 0; i < chain.Len(); i++ { - value, _ := chain.Get(i) - der := strings.ReplaceAll(string(value), "\n", "\\n") - err := rv.AddString(der) - if err != nil { - return nil, err - } - } - return rv, nil -} From 505b712694c1e3ca0ddaac6e5a67f89af623c0af Mon Sep 17 00:00:00 2001 From: Roland Groen Date: Mon, 14 Oct 2024 13:20:08 +0200 Subject: [PATCH 2/6] Reverse chain order in the x5c header. Refactored `marshalChain` function to process certificates in reverse order. --- uzi_vc_issuer/ura_issuer.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/uzi_vc_issuer/ura_issuer.go b/uzi_vc_issuer/ura_issuer.go index 660cbb6..b32f09c 100644 --- a/uzi_vc_issuer/ura_issuer.go +++ b/uzi_vc_issuer/ura_issuer.go @@ -184,15 +184,17 @@ func (v DefaultUraIssuer) BuildUraVerifiableCredential(certificates *[]x509.Cert // marshalChain converts a slice of x509.Certificate instances to a cert.Chain, encoding each certificate as PEM. // It returns the PEM-encoded cert.Chain and an error if the encoding or header fixation fails. func marshalChain(certificates *[]x509.Certificate) (*cert.Chain, error) { - chainPems := &cert.Chain{} - for _, certificate := range *certificates { - err := chainPems.Add(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certificate.Raw})) + rv := &cert.Chain{} + certs := *certificates + for i, _ := range certs { + certificate := certs[len(certs)-i-1] + err := rv.Add(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certificate.Raw})) if err != nil { return nil, err } } - headers, err := x509_cert.FixChainHeaders(chainPems) - return headers, err + rv, err := x509_cert.FixChainHeaders(rv) + return rv, err } func validateChain(certificates *[]x509.Certificate) error { From aa4ca20dc9506bd016b298c41d14ef2c75c27898 Mon Sep 17 00:00:00 2001 From: Roland Groen Date: Mon, 14 Oct 2024 14:57:01 +0200 Subject: [PATCH 3/6] Remove DidCreator and DidParser interfaces Eliminated the DidCreator and DidParser interfaces along with associated mock usages to simplify code and improve maintainability. Updated the UraVcBuilder, DefaultUraIssuer, and UraValidator implementations to directly use the CreateDid and ParseDid functions. --- did_x509/did_x509.go | 26 +----------- did_x509/did_x509_test.go | 69 +++++++++++++++++++++++++++++-- uzi_vc_issuer/ura_issuer.go | 9 ++-- uzi_vc_issuer/ura_issuer_test.go | 4 +- uzi_vc_validator/ura_validator.go | 9 ++-- 5 files changed, 76 insertions(+), 41 deletions(-) diff --git a/did_x509/did_x509.go b/did_x509/did_x509.go index d1f6397..a2c5ea9 100644 --- a/did_x509/did_x509.go +++ b/did_x509/did_x509.go @@ -19,28 +19,6 @@ type X509Did struct { SanType x509_cert.SanTypeName } -// DidCreator is an interface for creating a DID (Decentralized Identifier) given a chain of x509 certificates. -// The CreateDid method takes a slice of x509.Certificate and returns a DID as a string and an error if any. -type DidCreator interface { - CreateDid(chain *[]x509.Certificate) (string, error) -} - -type DidParser interface { - ParseDid(did string) (*X509Did, error) -} - -// DefaultDidProcessor is responsible for creating Decentralized Identifiers (DIDs) based on certificate chain information. -type DefaultDidProcessor struct { -} - -// NewDidCreator initializes and returns a new instance of DefaultDidProcessor. -func NewDidCreator() *DefaultDidProcessor { - return &DefaultDidProcessor{} -} -func NewDidParser() *DefaultDidProcessor { - return &DefaultDidProcessor{} -} - // FormatDid constructs a decentralized identifier (DID) from a certificate chain and an optional policy. // It returns the formatted DID string or an error if the root certificate or hash calculation fails. func FormatDid(chain *[]x509.Certificate, policy string) (string, error) { @@ -64,7 +42,7 @@ func FormatDid(chain *[]x509.Certificate, policy string) (string, error) { // CreateDid generates a Decentralized Identifier (DID) from a given certificate chain. // It extracts the Unique Registration Address (URA) from the chain, creates a policy with it, and formats the DID. // Returns the generated DID or an error if any step fails. -func (d *DefaultDidProcessor) CreateDid(chain *[]x509.Certificate) (string, error) { +func CreateDid(chain *[]x509.Certificate) (string, error) { certificate, _, err := x509_cert.FindSigningCertificate(chain) if err != nil || certificate == nil { return "", err @@ -77,7 +55,7 @@ func (d *DefaultDidProcessor) CreateDid(chain *[]x509.Certificate) (string, erro formattedDid, err := FormatDid(chain, policy) return formattedDid, err } -func (d *DefaultDidProcessor) ParseDid(didString string) (*X509Did, error) { +func ParseDid(didString string) (*X509Did, error) { x509Did := X509Did{} didObj := did.MustParseDID(didString) if didObj.Method != "x509" { diff --git a/did_x509/did_x509_test.go b/did_x509/did_x509_test.go index 772da77..50afd7d 100644 --- a/did_x509/did_x509_test.go +++ b/did_x509/did_x509_test.go @@ -16,7 +16,7 @@ func TestDefaultDidCreator_CreateDid(t *testing.T) { type args struct { chain *[]x509.Certificate } - chain, _, rootCert, _, _, err := x509_cert.BuildCertChain("A BIG STRING") + chain, _, rootCert, _, _, err := x509_cert.BuildCertChain("A_BIG_STRING") if err != nil { t.Fatal(err) } @@ -54,14 +54,13 @@ func TestDefaultDidCreator_CreateDid(t *testing.T) { name: "Happy path", fields: fields{}, args: args{chain: chain}, - want: strings.Join([]string{"did", "x509", "0", alg, rootHashString, "", "san", "otherName", "A BIG STRING"}, ":"), + want: strings.Join([]string{"did", "x509", "0", alg, rootHashString, "", "san", "otherName", "A_BIG_STRING"}, ":"), errMsg: "", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - d := &DefaultDidProcessor{} - got, err := d.CreateDid(tt.args.chain) + got, err := CreateDid(tt.args.chain) wantErr := tt.errMsg != "" if (err != nil) != wantErr { t.Errorf("DefaultDidProcessor.CreateDid() error = %v, errMsg %v", err, tt.errMsg) @@ -78,3 +77,65 @@ func TestDefaultDidCreator_CreateDid(t *testing.T) { }) } } + +// TestDefaultDidCreator_ParseDid tests the ParseDid function of DefaultDidProcessor by providing different DID strings. +// It checks for correct X509Did parsing and appropriate error messages. +func TestDefaultDidCreator_ParseDid(t *testing.T) { + type fields struct { + } + type args struct { + didString string + } + tests := []struct { + name string + fields fields + args args + want *X509Did + errMsg string + }{ + { + name: "Invalid DID method", + fields: fields{}, + args: args{didString: "did:abc:0:sha512:hash::san:otherName:A_BIG_STRING"}, + want: nil, + errMsg: "invalid didString method", + }, + { + name: "Invalid DID format", + fields: fields{}, + args: args{didString: "did:x509:0:sha512::san:otherName:A_BIG_STRING"}, + want: nil, + errMsg: "invalid didString format, expected didString:x509:0:alg:hash::san:type:ura", + }, + { + name: "Happy path", + fields: fields{}, + args: args{didString: "did:x509:0:sha512:hash::san:otherName:A_BIG_STRING"}, + want: &X509Did{Version: "0", RootCertificateHashAlg: "sha512", RootCertificateHash: "hash", SanType: "otherName", Ura: "A_BIG_STRING"}, + errMsg: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ParseDid(tt.args.didString) + wantErr := tt.errMsg != "" + if (err != nil) != wantErr { + t.Errorf("DefaultDidProcessor.ParseDid() error = %v, expected error = %v", err, tt.errMsg) + return + } else if wantErr { + if err.Error() != tt.errMsg { + t.Errorf("DefaultDidProcessor.ParseDid() expected = \"%v\", got = \"%v\"", tt.errMsg, err.Error()) + } + } + + if tt.want != nil && got != nil && + (tt.want.Version != got.Version || + tt.want.RootCertificateHashAlg != got.RootCertificateHashAlg || + tt.want.RootCertificateHash != got.RootCertificateHash || + tt.want.SanType != got.SanType || + tt.want.Ura != got.Ura) { + t.Errorf("DefaultDidProcessor.ParseDid() = %v, want = %v", got, tt.want) + } + }) + } +} diff --git a/uzi_vc_issuer/ura_issuer.go b/uzi_vc_issuer/ura_issuer.go index b32f09c..ff8530f 100644 --- a/uzi_vc_issuer/ura_issuer.go +++ b/uzi_vc_issuer/ura_issuer.go @@ -37,13 +37,12 @@ var RegexOtherNameValue = regexp.MustCompile(`2\.16\.528\.1\.1007.\d+\.\d+-\d+-\ // DefaultUraIssuer is responsible for building URA (UZI-register abonneenummer) Verifiable Credentials. // It utilizes a DidCreator to generate Decentralized Identifiers (DIDs) given a chain of x509 certificates. type DefaultUraIssuer struct { - didCreator did_x509.DidCreator chainParser x509_cert.ChainParser } // NewUraVcBuilder initializes and returns a new instance of DefaultUraIssuer with the provided DidCreator. -func NewUraVcBuilder(didCreator did_x509.DidCreator, chainParser x509_cert.ChainParser) *DefaultUraIssuer { - return &DefaultUraIssuer{didCreator, chainParser} +func NewUraVcBuilder(chainParser x509_cert.ChainParser) *DefaultUraIssuer { + return &DefaultUraIssuer{chainParser} } // Issue generates a URA Verifiable Credential using provided certificate, signing key, subject DID, and subject name. @@ -103,7 +102,7 @@ func (u DefaultUraIssuer) Issue(certificateFile string, signingKeyFile string, s if err != nil { return "", err } - validator := uzi_vc_validator.NewUraValidator(did_x509.NewDidParser(), test) + validator := uzi_vc_validator.NewUraValidator(test) jwtString := string(marshal) jwtString = jwtString[1:] // Chop start jwtString = jwtString[:len(jwtString)-1] // Chop end @@ -125,7 +124,7 @@ func (v DefaultUraIssuer) BuildUraVerifiableCredential(certificates *[]x509.Cert if err != nil { return nil, err } - did, err := v.didCreator.CreateDid(chain) + did, err := did_x509.CreateDid(chain) if err != nil { return nil, err } diff --git a/uzi_vc_issuer/ura_issuer_test.go b/uzi_vc_issuer/ura_issuer_test.go index 79158ec..cdc6986 100644 --- a/uzi_vc_issuer/ura_issuer_test.go +++ b/uzi_vc_issuer/ura_issuer_test.go @@ -5,7 +5,6 @@ import ( "crypto/rsa" "crypto/x509" "go.uber.org/mock/gomock" - "headease-nuts-pki-overheid-issuer/did_x509" "headease-nuts-pki-overheid-issuer/x509_cert" "math/big" "testing" @@ -40,9 +39,8 @@ func TestBuildUraVerifiableCredential(t *testing.T) { }, }, } - creator := did_x509.NewMockDidCreator(ctrl) parser := x509_cert.NewMockChainParser(ctrl) - builder := NewUraVcBuilder(creator, parser) + builder := NewUraVcBuilder(parser) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/uzi_vc_validator/ura_validator.go b/uzi_vc_validator/ura_validator.go index 3d4a152..0921e78 100644 --- a/uzi_vc_validator/ura_validator.go +++ b/uzi_vc_validator/ura_validator.go @@ -22,8 +22,7 @@ type UraValidator interface { } type UraValidatorImpl struct { - didParser did_x509.DidParser - test bool + test bool } type JwtHeaderValues struct { @@ -39,7 +38,7 @@ func (u UraValidatorImpl) Validate(jwtString string) error { if err != nil { return err } - parseDid, err := u.didParser.ParseDid(credential.Issuer.String()) + parseDid, err := did_x509.ParseDid(credential.Issuer.String()) if err != nil { return err } @@ -174,6 +173,6 @@ func parseJwtHeaderValues(jwtString string) (*JwtHeaderValues, error) { return metadata, nil } -func NewUraValidator(didParser did_x509.DidParser, test bool) *UraValidatorImpl { - return &UraValidatorImpl{didParser, test} +func NewUraValidator(test bool) *UraValidatorImpl { + return &UraValidatorImpl{test} } From 3d993b098a5e5464b951b556ef17fd6090ed0371 Mon Sep 17 00:00:00 2001 From: Roland Groen Date: Mon, 14 Oct 2024 15:02:46 +0200 Subject: [PATCH 4/6] Refactor: remove PemReader interface and simplify usage Removed the PemReader interface and associated methods to streamline the code. Function calls have been updated to directly use the ParseFileOrPath function without needing a PemReader instance. This simplifies the codebase and reduces redundancy. --- pem/pem_reader.go | 16 +--------------- pem/pem_reader_test.go | 18 ++++++------------ uzi_vc_issuer/ura_issuer.go | 5 ++--- 3 files changed, 9 insertions(+), 30 deletions(-) diff --git a/pem/pem_reader.go b/pem/pem_reader.go index f6c2e31..03e0db7 100644 --- a/pem/pem_reader.go +++ b/pem/pem_reader.go @@ -5,22 +5,8 @@ import ( "os" ) -// PemReader defines the interface for parsing PEM-encoded files from a given path. -type PemReader interface { - ParseFileOrPath(path string, pemType string) (*[][]byte, error) -} - -// DefaultPemReader handles reading and parsing of PEM files or directories containing PEM files. -type DefaultPemReader struct { -} - -// NewPemReader creates and returns a new instance of DefaultPemReader. -func NewPemReader() *DefaultPemReader { - return &DefaultPemReader{} -} - // ParseFileOrPath processes a file or directory at the given path and extracts PEM blocks of the specified pemType. -func (p *DefaultPemReader) ParseFileOrPath(path string, pemType string) (*[][]byte, error) { +func ParseFileOrPath(path string, pemType string) (*[][]byte, error) { fileInfo, err := os.Stat(path) if err != nil { return nil, err diff --git a/pem/pem_reader_test.go b/pem/pem_reader_test.go index e71c1ee..a46d8bb 100644 --- a/pem/pem_reader_test.go +++ b/pem/pem_reader_test.go @@ -21,15 +21,13 @@ func TestParseFileOrPath(t *testing.T) { pemType := "CERTIFICATE" t.Run("FileExistsAndIsNotDirectory", func(t *testing.T) { - pemReader := NewPemReader() - result, err := pemReader.ParseFileOrPath(tempFile.Name(), pemType) + result, err := ParseFileOrPath(tempFile.Name(), pemType) assert.NoError(t, err) assert.NotNil(t, result) }) t.Run("FileDoesNotExist", func(t *testing.T) { - pemReader := NewPemReader() - _, err := pemReader.ParseFileOrPath("nonexistent", pemType) + _, err := ParseFileOrPath("nonexistent", pemType) assert.Error(t, err) }) @@ -42,18 +40,15 @@ func TestParseFileOrPath(t *testing.T) { }(tempDir) t.Run("PathIsDirectory", func(t *testing.T) { - pemReader := NewPemReader() - _, err := pemReader.ParseFileOrPath(tempDir, pemType) + _, err := ParseFileOrPath(tempDir, pemType) assert.NoError(t, err) }) t.Run("PathDoesNotExist", func(t *testing.T) { - pemReader := NewPemReader() - _, err := pemReader.ParseFileOrPath("nonexistent/path", pemType) + _, err := ParseFileOrPath("nonexistent/path", pemType) assert.Error(t, err) }) t.Run("Happy flow single file", func(t *testing.T) { - pemReader := NewPemReader() file, err := os.CreateTemp(tempDir, "prefix") if err != nil { t.Fatal(err) @@ -78,7 +73,7 @@ func TestParseFileOrPath(t *testing.T) { t.Fail() } } - data, err := pemReader.ParseFileOrPath(file.Name(), pemType) + data, err := ParseFileOrPath(file.Name(), pemType) assert.NoError(t, err) for i := 0; i < len(*data); i++ { bytes := (*data)[i] @@ -91,7 +86,6 @@ func TestParseFileOrPath(t *testing.T) { }) t.Run("Happy flow directory", func(t *testing.T) { - pemReader := NewPemReader() certs, chainPem, _, _, _, err := x509_cert.BuildCertChain("A BIG STRING") assert.NoError(t, err) tempDir, _ := os.MkdirTemp("", "example") @@ -113,7 +107,7 @@ func TestParseFileOrPath(t *testing.T) { t.Fail() } } - data, err := pemReader.ParseFileOrPath(tempDir, pemType) + data, err := ParseFileOrPath(tempDir, pemType) assert.NoError(t, err) dataMap := make(map[string][]byte) for i := 0; i < len(*data); i++ { diff --git a/uzi_vc_issuer/ura_issuer.go b/uzi_vc_issuer/ura_issuer.go index ff8530f..c3d32bf 100644 --- a/uzi_vc_issuer/ura_issuer.go +++ b/uzi_vc_issuer/ura_issuer.go @@ -47,8 +47,7 @@ func NewUraVcBuilder(chainParser x509_cert.ChainParser) *DefaultUraIssuer { // Issue generates a URA Verifiable Credential using provided certificate, signing key, subject DID, and subject name. func (u DefaultUraIssuer) Issue(certificateFile string, signingKeyFile string, subjectDID string, test bool) (string, error) { - reader := pem2.NewPemReader() - certificate, err := reader.ParseFileOrPath(certificateFile, "CERTIFICATE") + certificate, err := pem2.ParseFileOrPath(certificateFile, "CERTIFICATE") if err != nil { return "", err } @@ -68,7 +67,7 @@ func (u DefaultUraIssuer) Issue(certificateFile string, signingKeyFile string, s _chain := append(*chain, *certificate...) chain = &_chain - signingKeys, err := reader.ParseFileOrPath(signingKeyFile, "PRIVATE KEY") + signingKeys, err := pem2.ParseFileOrPath(signingKeyFile, "PRIVATE KEY") if err != nil { return "", err } From 31c2122d6b14ff0de534dbba2579df9b07d225ac Mon Sep 17 00:00:00 2001 From: Roland Groen Date: Mon, 14 Oct 2024 15:09:51 +0200 Subject: [PATCH 5/6] Remove unused interfaces and simplify parser usage Eliminated UraIssuer and ChainParser interfaces and related mocks. Refactored code to call parsing functions directly, reducing complexity and improving readability. --- main.go | 7 +------ uzi_vc_issuer/ura_issuer.go | 29 ++++++----------------------- uzi_vc_issuer/ura_issuer_test.go | 7 +------ x509_cert/x509_cert.go | 21 ++------------------- x509_cert/x509_cert_test.go | 7 ++----- 5 files changed, 12 insertions(+), 59 deletions(-) diff --git a/main.go b/main.go index 6aa8e0a..691afdf 100644 --- a/main.go +++ b/main.go @@ -3,9 +3,7 @@ package main import ( "fmt" "github.com/alecthomas/kong" - "headease-nuts-pki-overheid-issuer/did_x509" "headease-nuts-pki-overheid-issuer/uzi_vc_issuer" - "headease-nuts-pki-overheid-issuer/x509_cert" "os" ) @@ -41,8 +39,5 @@ func main() { } func issueVc(vc VC) (string, error) { - didCreator := did_x509.NewDidCreator() - chainParser := x509_cert.NewDefaultChainParser() - issuer := uzi_vc_issuer.NewUraVcBuilder(didCreator, chainParser) - return issuer.Issue(vc.CertificateFile, vc.SigningKey, vc.SubjectDID, vc.Test) + return uzi_vc_issuer.Issue(vc.CertificateFile, vc.SigningKey, vc.SubjectDID, vc.Test) } diff --git a/uzi_vc_issuer/ura_issuer.go b/uzi_vc_issuer/ura_issuer.go index c3d32bf..a3219ef 100644 --- a/uzi_vc_issuer/ura_issuer.go +++ b/uzi_vc_issuer/ura_issuer.go @@ -26,32 +26,15 @@ import ( ) import "github.com/nuts-foundation/go-did/vc" -type UraIssuer interface { - - // Issue generates a digital certificate from the given certificate file and signing key file for the subject. - Issue(certificateFile string, signingKeyFile string, subjectDID string, subjectName string) (string, error) -} - var RegexOtherNameValue = regexp.MustCompile(`2\.16\.528\.1\.1007.\d+\.\d+-\d+-\d+-S-(\d+)-00\.000-\d+`) -// DefaultUraIssuer is responsible for building URA (UZI-register abonneenummer) Verifiable Credentials. -// It utilizes a DidCreator to generate Decentralized Identifiers (DIDs) given a chain of x509 certificates. -type DefaultUraIssuer struct { - chainParser x509_cert.ChainParser -} - -// NewUraVcBuilder initializes and returns a new instance of DefaultUraIssuer with the provided DidCreator. -func NewUraVcBuilder(chainParser x509_cert.ChainParser) *DefaultUraIssuer { - return &DefaultUraIssuer{chainParser} -} - // Issue generates a URA Verifiable Credential using provided certificate, signing key, subject DID, and subject name. -func (u DefaultUraIssuer) Issue(certificateFile string, signingKeyFile string, subjectDID string, test bool) (string, error) { +func Issue(certificateFile string, signingKeyFile string, subjectDID string, test bool) (string, error) { certificate, err := pem2.ParseFileOrPath(certificateFile, "CERTIFICATE") if err != nil { return "", err } - _certificates, err := u.chainParser.ParseCertificates(certificate) + _certificates, err := x509_cert.ParseCertificates(certificate) if err != nil { return "", err } @@ -83,17 +66,17 @@ func (u DefaultUraIssuer) Issue(certificateFile string, signingKeyFile string, s err := fmt.Errorf("no signing keys found") return "", err } - privateKey, err := u.chainParser.ParsePrivateKey(signingKey) + privateKey, err := x509_cert.ParsePrivateKey(signingKey) if err != nil { return "", err } - certChain, err := u.chainParser.ParseCertificates(chain) + certChain, err := x509_cert.ParseCertificates(chain) if err != nil { return "", err } - credential, err := u.BuildUraVerifiableCredential(certChain, privateKey, subjectDID) + credential, err := BuildUraVerifiableCredential(certChain, privateKey, subjectDID) if err != nil { return "", err } @@ -113,7 +96,7 @@ func (u DefaultUraIssuer) Issue(certificateFile string, signingKeyFile string, s } // BuildUraVerifiableCredential constructs a verifiable credential with specified certificates, signing key, subject DID. -func (v DefaultUraIssuer) BuildUraVerifiableCredential(certificates *[]x509.Certificate, signingKey *rsa.PrivateKey, subjectDID string) (*vc.VerifiableCredential, error) { +func BuildUraVerifiableCredential(certificates *[]x509.Certificate, signingKey *rsa.PrivateKey, subjectDID string) (*vc.VerifiableCredential, error) { signingCert, otherNameValue, err := x509_cert.FindSigningCertificate(certificates) if err != nil { return nil, err diff --git a/uzi_vc_issuer/ura_issuer_test.go b/uzi_vc_issuer/ura_issuer_test.go index cdc6986..b213054 100644 --- a/uzi_vc_issuer/ura_issuer_test.go +++ b/uzi_vc_issuer/ura_issuer_test.go @@ -4,15 +4,12 @@ import ( "crypto/rand" "crypto/rsa" "crypto/x509" - "go.uber.org/mock/gomock" - "headease-nuts-pki-overheid-issuer/x509_cert" "math/big" "testing" "time" ) func TestBuildUraVerifiableCredential(t *testing.T) { - ctrl := gomock.NewController(t) privKey, _ := rsa.GenerateKey(rand.Reader, 2048) template := x509.Certificate{ @@ -39,13 +36,11 @@ func TestBuildUraVerifiableCredential(t *testing.T) { }, }, } - parser := x509_cert.NewMockChainParser(ctrl) - builder := NewUraVcBuilder(parser) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { certificates, signingKey, subjectDID := tt.in() - _, err := builder.BuildUraVerifiableCredential(certificates, signingKey, subjectDID) + _, err := BuildUraVerifiableCredential(certificates, signingKey, subjectDID) if got := tt.want(err); !got { t.Errorf("BuildUraVerifiableCredential() error = %v", err) } diff --git a/x509_cert/x509_cert.go b/x509_cert/x509_cert.go index 8721604..7b61ba4 100644 --- a/x509_cert/x509_cert.go +++ b/x509_cert/x509_cert.go @@ -42,26 +42,9 @@ func Hash(data []byte, alg string) ([]byte, error) { return nil, fmt.Errorf("unsupported hash algorithm: %s", alg) } -type ChainParser interface { - - // ParseCertificates parses a chain of DER-encoded certificates into an array of x509.Certificate objects. - ParseCertificates(derChain *[][]byte) (*[]x509.Certificate, error) - - // ParsePrivateKey parses a DER-encoded byte slice into an rsa.PrivateKey object, returning an error if parsing fails. - ParsePrivateKey(der *[]byte) (*rsa.PrivateKey, error) -} - -// DefaultChainParser handles the parsing of certificate chains and private keys. -type DefaultChainParser struct{} - -// NewDefaultChainParser creates a new instance of DefaultChainParser. -func NewDefaultChainParser() *DefaultChainParser { - return &DefaultChainParser{} -} - // ParseCertificates parses a slice of DER-encoded byte arrays into a slice of x509.Certificate. // It returns an error if any of the certificates cannot be parsed. -func (c DefaultChainParser) ParseCertificates(derChain *[][]byte) (*[]x509.Certificate, error) { +func ParseCertificates(derChain *[][]byte) (*[]x509.Certificate, error) { if derChain == nil { return nil, fmt.Errorf("derChain is nil") } @@ -80,7 +63,7 @@ func (c DefaultChainParser) ParseCertificates(derChain *[][]byte) (*[]x509.Certi // ParsePrivateKey parses a DER-encoded private key into an *rsa.PrivateKey. // It returns an error if the key is not in PKCS8 format or not an RSA key. -func (c DefaultChainParser) ParsePrivateKey(der *[]byte) (*rsa.PrivateKey, error) { +func ParsePrivateKey(der *[]byte) (*rsa.PrivateKey, error) { if der == nil { return nil, fmt.Errorf("der is nil") } diff --git a/x509_cert/x509_cert_test.go b/x509_cert/x509_cert_test.go index 5e94e90..9686127 100644 --- a/x509_cert/x509_cert_test.go +++ b/x509_cert/x509_cert_test.go @@ -74,8 +74,6 @@ func TestHash(t *testing.T) { } } func TestParseChain(t *testing.T) { - parser := NewDefaultChainParser() - _, chainPem, _, _, _, err := BuildCertChain("9907878") assert.NoError(t, err) derChains := make([][]byte, chainPem.Len()) @@ -109,7 +107,7 @@ func TestParseChain(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - _, err := parser.ParseCertificates(tc.derChain) + _, err := ParseCertificates(tc.derChain) if err != nil { if err.Error() != tc.errMsg { t.Errorf("got error %v, want %v", err, tc.errMsg) @@ -120,7 +118,6 @@ func TestParseChain(t *testing.T) { } func TestParsePrivateKey(t *testing.T) { - parser := NewDefaultChainParser() _, _, _, privateKey, _, err := BuildCertChain("9907878") assert.NoError(t, err) privateKeyBytes, err := x509.MarshalPKCS8PrivateKey(privateKey) @@ -150,7 +147,7 @@ func TestParsePrivateKey(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - _, err := parser.ParsePrivateKey(tc.der) + _, err := ParsePrivateKey(tc.der) if err != nil { if err.Error() != tc.errMsg { t.Errorf("got error %v, want %v", err, tc.errMsg) From cc816938d7118655f27dedba2f907696cbf27a0c Mon Sep 17 00:00:00 2001 From: Roland Groen Date: Mon, 14 Oct 2024 15:10:00 +0200 Subject: [PATCH 6/6] Update mockgen source paths in makefile Adjusted the source paths for mock generation to reflect the new directory structure. This helps in organizing the mock files according to their respective components, improving maintainability and readability. --- makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index be34961..bd167ab 100644 --- a/makefile +++ b/makefile @@ -7,9 +7,9 @@ install-tools: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.60.1 gen-mocks: - mockgen -destination=uzi_vc_issuer/did_x509_mock.go -package=uzi_vc_issuer -source=uzi_vc_issuer/did_x509.go - mockgen -destination=uzi_vc_issuer/x509_cert_mock.go -package=uzi_vc_issuer -source=uzi_vc_issuer/x509_cert.go - mockgen -destination=uzi_vc_issuer/pem_reader_mock.go -package=uzi_vc_issuer -source=uzi_vc_issuer/pem_reader.go + mockgen -destination=uzi_vc_issuer/did_x509_mock.go -package=uzi_vc_issuer -source=did_x509/did_x509.go + mockgen -destination=uzi_vc_issuer/x509_cert_mock.go -package=uzi_vc_issuer -source=x509_cert/x509_cert.go + mockgen -destination=uzi_vc_issuer/pem_reader_mock.go -package=uzi_vc_issuer -source=pem/pem_reader.go lint: golangci-lint run -v