diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index b8bd6c3..ffc6f17 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -23,7 +23,7 @@ jobs: uses: golangci/golangci-lint-action@v2.5.2 with: args: --timeout=5m0s -c .golangci.yaml - version: v1.46.2 + version: v1.54.2 test: name: Test runs-on: ubuntu-latest diff --git a/README.md b/README.md index 5d5b3be..20148ee 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ func readKeyStore(filename string, password []byte) keystore.KeyStore { ks := keystore.New() if err := ks.Load(f, password); err != nil { - log.Fatal(err) // nolint: gocritic + log.Fatal(err) //nolint: gocritic } return ks @@ -52,7 +52,7 @@ func writeKeyStore(ks keystore.KeyStore, filename string, password []byte) { err = ks.Store(f, password) if err != nil { - log.Fatal(err) // nolint: gocritic + log.Fatal(err) //nolint: gocritic } } diff --git a/decoder.go b/decoder.go index 8047ca7..b746c23 100644 --- a/decoder.go +++ b/decoder.go @@ -130,9 +130,9 @@ func (d decoder) readPrivateKeyEntry(version uint32) (PrivateKeyEntry, error) { creationDateTime := time.UnixMilli(int64(creationTimeStamp)) privateKeyEntry := PrivateKeyEntry{ - encryptedPrivateKey: encryptedPrivateKey, - CreationTime: creationDateTime, - CertificateChain: chain, + PrivateKey: encryptedPrivateKey, + CreationTime: creationDateTime, + CertificateChain: chain, } return privateKeyEntry, nil diff --git a/encoder.go b/encoder.go index 31a7c3a..4047027 100644 --- a/encoder.go +++ b/encoder.go @@ -99,7 +99,7 @@ func (e encoder) writePrivateKeyEntry(alias string, pke PrivateKeyEntry) error { return fmt.Errorf("write creation timestamp: %w", err) } - length := uint64(len(pke.encryptedPrivateKey)) + length := uint64(len(pke.PrivateKey)) if length > math.MaxUint32 { return fmt.Errorf("got encrypted content %d bytes long, max length is %d", length, uint64(math.MaxUint32)) } @@ -108,7 +108,7 @@ func (e encoder) writePrivateKeyEntry(alias string, pke PrivateKeyEntry) error { return fmt.Errorf("filed to write length: %w", err) } - if err := e.writeBytes(pke.encryptedPrivateKey); err != nil { + if err := e.writeBytes(pke.PrivateKey); err != nil { return fmt.Errorf("write content: %w", err) } diff --git a/examples/compare/main.go b/examples/compare/main.go index 3cbde05..6a0c9c7 100644 --- a/examples/compare/main.go +++ b/examples/compare/main.go @@ -2,7 +2,6 @@ package main import ( "encoding/pem" - "io/ioutil" "log" "os" "reflect" @@ -14,7 +13,7 @@ import ( type nonRand struct { } -func (r nonRand) Read(p []byte) (n int, err error) { +func (r nonRand) Read(p []byte) (int, error) { for i := range p { p[i] = 1 } @@ -61,7 +60,7 @@ func writeKeyStore(ks keystore.KeyStore, filename string, password []byte) { } func readPrivateKey() []byte { - pkPEM, err := ioutil.ReadFile("./key.pem") + pkPEM, err := os.ReadFile("./key.pem") if err != nil { panic(err) } @@ -79,7 +78,7 @@ func readPrivateKey() []byte { } func readCertificate() []byte { - pkPEM, err := ioutil.ReadFile("./cert.pem") + pkPEM, err := os.ReadFile("./cert.pem") if err != nil { panic(err) } diff --git a/examples/keypass/main.go b/examples/keypass/main.go index 3b8d952..36fb808 100644 --- a/examples/keypass/main.go +++ b/examples/keypass/main.go @@ -22,7 +22,7 @@ func readKeyStore(filename string, password []byte) keystore.KeyStore { ks := keystore.New() if err := ks.Load(f, password); err != nil { - log.Fatal(err) // nolint: gocritic + log.Fatal(err) //nolint: gocritic } return ks @@ -34,9 +34,8 @@ func zeroing(buf []byte) { } } -// nolint: godot -// keytool -genkeypair -alias alias -storepass password -keypass keypassword -keyalg RSA -keystore keystore.jks func main() { + // keytool -genkeypair -alias alias -storepass password -keypass keypassword -keyalg RSA -keystore keystore.jks password := []byte{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'} defer zeroing(password) @@ -47,7 +46,7 @@ func main() { pke, err := ks.GetPrivateKeyEntry("alias", keyPassword) if err != nil { - log.Fatal(err) // nolint: gocritic + log.Fatal(err) //nolint: gocritic } key, err := x509.ParsePKCS8PrivateKey(pke.PrivateKey) diff --git a/examples/pem/main.go b/examples/pem/main.go index cb2d158..a80f6e5 100644 --- a/examples/pem/main.go +++ b/examples/pem/main.go @@ -3,7 +3,6 @@ package main import ( "crypto/x509" "encoding/pem" - "io/ioutil" "log" "os" "time" @@ -25,7 +24,7 @@ func readKeyStore(filename string, password []byte) keystore.KeyStore { ks := keystore.New() if err := ks.Load(f, password); err != nil { - log.Fatal(err) // nolint: gocritic + log.Fatal(err) //nolint: gocritic } return ks @@ -45,12 +44,12 @@ func writeKeyStore(ks keystore.KeyStore, filename string, password []byte) { err = ks.Store(f, password) if err != nil { - log.Fatal(err) // nolint: gocritic + log.Fatal(err) //nolint: gocritic } } func readPrivateKey() []byte { - pkPEM, err := ioutil.ReadFile("./key.pem") + pkPEM, err := os.ReadFile("./key.pem") if err != nil { log.Fatal(err) } @@ -68,7 +67,7 @@ func readPrivateKey() []byte { } func readCertificate() []byte { - pkPEM, err := ioutil.ReadFile("./cert.pem") + pkPEM, err := os.ReadFile("./cert.pem") if err != nil { log.Fatal(err) } @@ -91,9 +90,9 @@ func zeroing(buf []byte) { } } -// nolint: godot, lll -// openssl req -x509 -sha256 -nodes -days 365 -subj '/CN=localhost' -newkey rsa:2048 -outform pem -keyout key.pem -out cert.pem func main() { + //nolint: lll + // openssl req -x509 -sha256 -nodes -days 365 -subj '/CN=localhost' -newkey rsa:2048 -outform pem -keyout key.pem -out cert.pem password := []byte{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'} defer zeroing(password) @@ -111,7 +110,7 @@ func main() { } if err := ks1.SetPrivateKeyEntry("alias", pkeIn, password); err != nil { - log.Fatal(err) // nolint: gocritic + log.Fatal(err) //nolint: gocritic } writeKeyStore(ks1, "keystore.jks", password) diff --git a/examples/truststore/main.go b/examples/truststore/main.go index 95f056d..0f4c158 100644 --- a/examples/truststore/main.go +++ b/examples/truststore/main.go @@ -22,16 +22,16 @@ func readKeyStore(filename string, password []byte) keystore.KeyStore { ks := keystore.New() if err := ks.Load(f, password); err != nil { - log.Fatal(err) // nolint: gocritic + log.Fatal(err) //nolint: gocritic } return ks } -// nolint: godot, lll -// go run main.go "/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/cacerts" "changeit" func main() { - if len(os.Args) < 3 { // nolint: gomnd + //nolint: lll + // go run main.go "/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/cacerts" "changeit" + if len(os.Args) < 3 { //nolint: gomnd log.Fatal("usage: ") } diff --git a/keystore.go b/keystore.go index 38f4e22..2c3f222 100644 --- a/keystore.go +++ b/keystore.go @@ -33,8 +33,6 @@ type KeyStore struct { // PrivateKeyEntry is an entry for private keys and associated certificates. type PrivateKeyEntry struct { - encryptedPrivateKey []byte - CreationTime time.Time PrivateKey []byte CertificateChain []Certificate @@ -222,7 +220,7 @@ func (ks KeyStore) SetPrivateKeyEntry(alias string, entry PrivateKeyEntry, passw return fmt.Errorf("encrypt private key: %w", err) } - entry.encryptedPrivateKey = epk + entry.PrivateKey = epk ks.m[ks.convertAlias(alias)] = entry @@ -242,17 +240,32 @@ func (ks KeyStore) GetPrivateKeyEntry(alias string, password []byte) (PrivateKey return PrivateKeyEntry{}, ErrWrongEntryType } - dpk, err := decrypt(pke.encryptedPrivateKey, password) + dpk, err := decrypt(pke.PrivateKey, password) if err != nil { return PrivateKeyEntry{}, fmt.Errorf("decrypt private key: %w", err) } - pke.encryptedPrivateKey = nil pke.PrivateKey = dpk return pke, nil } +// GetPrivateKeyEntryCertificateChain returns certificate chain associated with +// PrivateKeyEntry from the keystore by the alias. +func (ks KeyStore) GetPrivateKeyEntryCertificateChain(alias string) ([]Certificate, error) { + e, ok := ks.m[ks.convertAlias(alias)] + if !ok { + return nil, ErrEntryNotFound + } + + pke, ok := e.(PrivateKeyEntry) + if !ok { + return nil, ErrWrongEntryType + } + + return pke.CertificateChain, nil +} + // IsPrivateKeyEntry returns true if the keystore has PrivateKeyEntry by the alias. func (ks KeyStore) IsPrivateKeyEntry(alias string) bool { _, ok := ks.m[ks.convertAlias(alias)].(PrivateKeyEntry) diff --git a/keystore_test.go b/keystore_test.go index 8858719..c773bc3 100644 --- a/keystore_test.go +++ b/keystore_test.go @@ -3,7 +3,6 @@ package keystore import ( "encoding/pem" "errors" - "io/ioutil" "os" "reflect" "sort" @@ -52,6 +51,11 @@ func TestSetGetMethods(t *testing.T) { t.Fatal(err) } + chainGet, err := ks.GetPrivateKeyEntryCertificateChain(pkeAlias) + if err != nil { + t.Fatal(err) + } + tceGet, err := ks.GetTrustedCertificateEntry(tceAlias) if err != nil { t.Fatal(err) @@ -61,6 +65,10 @@ func TestSetGetMethods(t *testing.T) { t.Fatal("private key entries not equal") } + if !reflect.DeepEqual(pke.CertificateChain, chainGet) { + t.Fatal("certificate chains of private key entries are not equal") + } + if !reflect.DeepEqual(tce, tceGet) { t.Fatal("private key entries not equal") } @@ -218,7 +226,7 @@ func TestLoad(t *testing.T) { t.Errorf("unexpected private key entry certificate chain length: '%d' '%d'", len(actualPKE.CertificateChain), 0) } - pkPEM, err := ioutil.ReadFile("./testdata/key.pem") + pkPEM, err := os.ReadFile("./testdata/key.pem") if err != nil { t.Fatalf("read expected private key file: %s", err) } @@ -272,7 +280,7 @@ func TestLoadKeyPassword(t *testing.T) { t.Errorf("unexpected private key entry certificate chain length: '%d' '%d'", len(actualPKE.CertificateChain), 0) } - pkPEM, err := ioutil.ReadFile("./testdata/key_keypass.pem") + pkPEM, err := os.ReadFile("./testdata/key_keypass.pem") if err != nil { t.Fatalf("read expected private key file: %s", err) } @@ -287,7 +295,7 @@ func TestLoadKeyPassword(t *testing.T) { func readPrivateKey(t *testing.T) []byte { t.Helper() - pkPEM, err := ioutil.ReadFile("./testdata/key.pem") + pkPEM, err := os.ReadFile("./testdata/key.pem") if err != nil { t.Fatal(err) } @@ -307,7 +315,7 @@ func readPrivateKey(t *testing.T) []byte { func readCertificate(t *testing.T) []byte { t.Helper() - pkPEM, err := ioutil.ReadFile("./testdata/cert.pem") + pkPEM, err := os.ReadFile("./testdata/cert.pem") if err != nil { t.Fatal(err) }