diff --git a/crypter.go b/crypter.go index b94d268..c99e0a7 100644 --- a/crypter.go +++ b/crypter.go @@ -21,10 +21,19 @@ type Crypterer interface { // Init sets the encryption provider used by Encrypt() and Decrypt() // and can only ever be called once. Repeated calls have no effect. -func Init(c Crypterer) { +// +// An errors is returned if the Crypter is nil, so that encryption does +// not get silently disabled for the lifetime of the process. +func Init(c Crypterer) error { + if c == nil { + return ErrInitWithNil + } + once.Do(func() { crypter = c }) + + return nil } // Encrypt reads plaintext from an io.Reader diff --git a/crypter_test.go b/crypter_test.go index cdff4e5..90ecbda 100644 --- a/crypter_test.go +++ b/crypter_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/pkg/errors" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -59,9 +58,16 @@ var _ Crypterer = (*base64Crypter)(nil) func Test_Set(t *testing.T) { c := &base64Crypter{} - Init(c) + err := Init(c) + require.NoError(t, err) + require.Equal(t, crypter, c) +} - assert.Equal(t, crypter, c) +func Test_Init_Nil(t *testing.T) { + err := Init(nil) + require.Error(t, err) + require.Contains(t, err.Error(), "Init() called with nil crypter") + require.ErrorIs(t, err, ErrInitWithNil) } func Test_Encrypt(t *testing.T) { @@ -75,7 +81,7 @@ func Test_Encrypt(t *testing.T) { err := Encrypt(writer, reader) require.NoError(t, err) - assert.Equal(t, ciphertext, writer.String()) + require.Equal(t, ciphertext, writer.String()) } func Test_Encrypt_NotInitialized(t *testing.T) { @@ -91,7 +97,7 @@ func Test_Encrypt_NotInitialized(t *testing.T) { err := Encrypt(writer, reader) require.Error(t, err) - assert.ErrorIs(t, err, ErrCrypterNotInitialized) + require.ErrorIs(t, err, ErrCrypterNotInitialized) } func Test_Decrypt(t *testing.T) { @@ -105,7 +111,7 @@ func Test_Decrypt(t *testing.T) { err := Decrypt(writer, reader) require.NoError(t, err) - assert.Equal(t, plaintext, writer.String()) + require.Equal(t, plaintext, writer.String()) } func Test_Decrypt_NotInitialized(t *testing.T) { @@ -121,5 +127,5 @@ func Test_Decrypt_NotInitialized(t *testing.T) { err := Decrypt(writer, reader) require.Error(t, err) - assert.ErrorIs(t, err, ErrCrypterNotInitialized) + require.ErrorIs(t, err, ErrCrypterNotInitialized) } diff --git a/errors.go b/errors.go index e015a2e..36b68eb 100644 --- a/errors.go +++ b/errors.go @@ -2,6 +2,11 @@ package sqlcrypter import "errors" -// ErrCrypterNotInitialized indicates that Init() has not been called -// with a valid Crypterer before Encrypt()/Decrypt() usage. -var ErrCrypterNotInitialized = errors.New("sqlcrypter: crypter is not initialized") +var ( + // ErrInitWithNil indicates that Init() has been called with a nil Crypterer. + ErrInitWithNil = errors.New("sqlcrypter: Init() called with nil crypter") + + // ErrCrypterNotInitialized indicates that Init() has not been called + // with a valid Crypterer before Encrypt()/Decrypt() usage. + ErrCrypterNotInitialized = errors.New("sqlcrypter: crypter is not initialized") +) diff --git a/example/go.mod b/example/go.mod index 83df6df..073b8f2 100644 --- a/example/go.mod +++ b/example/go.mod @@ -1,6 +1,6 @@ module github.com/bincyber/go-sqlcrypter/example -go 1.25.0 +go 1.26 require ( github.com/bincyber/go-sqlcrypter v0.3.0 @@ -17,8 +17,8 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-sqlite3 v1.14.40 // indirect github.com/pkg/errors v0.9.1 // indirect - golang.org/x/sys v0.42.0 // indirect - golang.org/x/text v0.35.0 // indirect + golang.org/x/sys v0.44.0 // indirect + golang.org/x/text v0.37.0 // indirect ) replace github.com/bincyber/go-sqlcrypter => ../ diff --git a/example/go.sum b/example/go.sum index b4bf5dd..622d21f 100644 --- a/example/go.sum +++ b/example/go.sum @@ -36,10 +36,10 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= -golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/example/main.go b/example/main.go index 51ff200..69658e7 100644 --- a/example/main.go +++ b/example/main.go @@ -44,7 +44,10 @@ func main() { logger.Error("failed to create AES GCM crypter") } - sqlcrypter.Init(aesCrypter) + if err := sqlcrypter.Init(aesCrypter); err != nil { + logger.Error("failed to create init crypter") + os.Exit(1) + } // Connect to the sqlite database db, err := gorm.Open(sqlite.Open("example.db"), &gorm.Config{})