From 7b7731d6e0123c901a6c13bffc3024c822ab529a Mon Sep 17 00:00:00 2001 From: CJ Brewer Date: Wed, 15 Jul 2026 07:17:44 -0600 Subject: [PATCH] refactor: rename customer-facing surface from "protect" to "encryption" Brand change: this is the CipherStash Stack's Go Encryption SDK, no longer "Protect". Renames every customer-facing use of "protect": - Module path: github.com/cipherstash/protectgo -> github.com/cipherstash/goencryption - Go package: pkg/protect (package protect) -> pkg/encryption (package encryption) so the public API reads encryption.NewClient, encryption.Encrypt, etc. - Error namespace: "protect: ..." -> "encryption: ..." across all messages and sentinels - Renamed protect.go/protect_test.go -> encryption.go/encryption_test.go - Docs, examples, and CI paths updated to the new package location The FFI internals are intentionally left unchanged, per scope: the Rust crate (protect-ffi-c), library (protect_ffi / libprotect_ffi_*.a), C ABI symbols (protect_new_client, ...), the generated header (protect_ffi.h), and the cgo bridge (protectgoGetToken) are implementation details users never see. The GitHub repo must be renamed to `goencryption` for `go get` to resolve the new module path. Verified: gofmt clean, go build/test green, and a live encrypt/decrypt round trip against ZeroKMS under the new import path. Co-Authored-By: Claude Fable 5 --- .github/workflows/build.yml | 32 ++--- CONTRIBUTE.md | 2 +- DEVELOPMENT.md | 14 +- README.md | 128 +++++++++--------- crates/protect-ffi-c/build.rs | 2 +- examples/basic_usage.go | 60 ++++---- go.mod | 2 +- pkg/{protect => encryption}/callback.go | 2 +- .../protect.go => encryption/encryption.go} | 60 ++++---- .../encryption_test.go} | 6 +- pkg/{protect => encryption}/errors.go | 28 ++-- .../libprotect_ffi_darwin_arm64.a | Bin .../libprotect_ffi_darwin_x64.a | Bin .../libprotect_ffi_linux_arm64.a | Bin .../libprotect_ffi_linux_arm64_musl.a | Bin .../libprotect_ffi_linux_x64.a | Bin .../libprotect_ffi_linux_x64_musl.a | Bin pkg/{protect => encryption}/model.go | 42 +++--- pkg/{protect => encryption}/model_test.go | 2 +- pkg/{protect => encryption}/protect_ffi.h | 0 pkg/{protect => encryption}/schema.go | 8 +- pkg/{protect => encryption}/schema_test.go | 2 +- 22 files changed, 195 insertions(+), 195 deletions(-) rename pkg/{protect => encryption}/callback.go (99%) rename pkg/{protect/protect.go => encryption/encryption.go} (94%) rename pkg/{protect/protect_test.go => encryption/encryption_test.go} (99%) rename pkg/{protect => encryption}/errors.go (78%) rename pkg/{protect => encryption}/libprotect_ffi_darwin_arm64.a (100%) rename pkg/{protect => encryption}/libprotect_ffi_darwin_x64.a (100%) rename pkg/{protect => encryption}/libprotect_ffi_linux_arm64.a (100%) rename pkg/{protect => encryption}/libprotect_ffi_linux_arm64_musl.a (100%) rename pkg/{protect => encryption}/libprotect_ffi_linux_x64.a (100%) rename pkg/{protect => encryption}/libprotect_ffi_linux_x64_musl.a (100%) rename pkg/{protect => encryption}/model.go (87%) rename pkg/{protect => encryption}/model_test.go (99%) rename pkg/{protect => encryption}/protect_ffi.h (100%) rename pkg/{protect => encryption}/schema.go (97%) rename pkg/{protect => encryption}/schema_test.go (99%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6125b45..2861a47 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -145,22 +145,22 @@ jobs: # Create platform-specific filename for direct CGO usage case "${{ matrix.platform }}" in darwin-arm64) - cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/protect/libprotect_ffi_darwin_arm64.a + cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/encryption/libprotect_ffi_darwin_arm64.a ;; darwin-x64) - cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/protect/libprotect_ffi_darwin_x64.a + cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/encryption/libprotect_ffi_darwin_x64.a ;; linux-arm64-musl) - cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/protect/libprotect_ffi_linux_arm64_musl.a + cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/encryption/libprotect_ffi_linux_arm64_musl.a ;; linux-x64-musl) - cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/protect/libprotect_ffi_linux_x64_musl.a + cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/encryption/libprotect_ffi_linux_x64_musl.a ;; linux-arm64-gnu) - cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/protect/libprotect_ffi_linux_arm64.a + cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/encryption/libprotect_ffi_linux_arm64.a ;; linux-x64-gnu) - cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/protect/libprotect_ffi_linux_x64.a + cp target/${{ matrix.rust_target }}/release/libprotect_ffi.a pkg/encryption/libprotect_ffi_linux_x64.a ;; esac @@ -168,7 +168,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: library-${{ matrix.platform }} - path: pkg/protect/libprotect_ffi_*.a + path: pkg/encryption/libprotect_ffi_*.a retention-days: 30 # Run Go unit tests against the freshly built native libraries @@ -199,10 +199,10 @@ jobs: uses: actions/download-artifact@v4 with: name: library-${{ matrix.platform }} - path: pkg/protect + path: pkg/encryption - name: Run Go tests - run: go test ./pkg/protect/... + run: go test ./pkg/encryption/... # Commit all generated libraries at once commit-artifacts: @@ -234,22 +234,22 @@ jobs: # Copy platform-specific files to package directory if [ -f "$artifact_dir/libprotect_ffi_darwin_arm64.a" ]; then - cp "$artifact_dir/libprotect_ffi_darwin_arm64.a" "pkg/protect/" + cp "$artifact_dir/libprotect_ffi_darwin_arm64.a" "pkg/encryption/" fi if [ -f "$artifact_dir/libprotect_ffi_darwin_x64.a" ]; then - cp "$artifact_dir/libprotect_ffi_darwin_x64.a" "pkg/protect/" + cp "$artifact_dir/libprotect_ffi_darwin_x64.a" "pkg/encryption/" fi if [ -f "$artifact_dir/libprotect_ffi_linux_arm64.a" ]; then - cp "$artifact_dir/libprotect_ffi_linux_arm64.a" "pkg/protect/" + cp "$artifact_dir/libprotect_ffi_linux_arm64.a" "pkg/encryption/" fi if [ -f "$artifact_dir/libprotect_ffi_linux_x64.a" ]; then - cp "$artifact_dir/libprotect_ffi_linux_x64.a" "pkg/protect/" + cp "$artifact_dir/libprotect_ffi_linux_x64.a" "pkg/encryption/" fi if [ -f "$artifact_dir/libprotect_ffi_linux_arm64_musl.a" ]; then - cp "$artifact_dir/libprotect_ffi_linux_arm64_musl.a" "pkg/protect/" + cp "$artifact_dir/libprotect_ffi_linux_arm64_musl.a" "pkg/encryption/" fi if [ -f "$artifact_dir/libprotect_ffi_linux_x64_musl.a" ]; then - cp "$artifact_dir/libprotect_ffi_linux_x64_musl.a" "pkg/protect/" + cp "$artifact_dir/libprotect_ffi_linux_x64_musl.a" "pkg/encryption/" fi done @@ -257,7 +257,7 @@ jobs: run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git add pkg/protect/*.a + git add pkg/encryption/*.a if git diff --cached --quiet; then echo "No changes to commit" else diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md index 75cf3eb..5409f56 100644 --- a/CONTRIBUTE.md +++ b/CONTRIBUTE.md @@ -4,7 +4,7 @@ Please use the GitHub issue tracker to report bugs, suggest features, or documentation improvements. -[When filing an issue](https://github.com/cipherstash/protectgo/issues/new/choose), please check [existing open](https://github.com/cipherstash/protectgo/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc), or [recently closed](https://github.com/cipherstash/protectgo/issues?q=is%3Aissue+sort%3Aupdated-desc+is%3Aclosed), issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. +[When filing an issue](https://github.com/cipherstash/goencryption/issues/new/choose), please check [existing open](https://github.com/cipherstash/goencryption/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc), or [recently closed](https://github.com/cipherstash/goencryption/issues?q=is%3Aissue+sort%3Aupdated-desc+is%3Aclosed), issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. --- diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 631e815..d04fadb 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -9,15 +9,15 @@ The project consists of: 1. **Rust C library** (`crates/protect-ffi-c/`) — a Rust crate that exports C-compatible functions and generates the `protect_ffi.h` header. -2. **Go package** (`pkg/protect/`) — Go bindings that link the compiled static +2. **Go package** (`pkg/encryption/`) — Go bindings that link the compiled static library via cgo and expose an idiomatic Go API. 3. **Examples** (`examples/`) — runnable usage examples. ``` -protectgo/ +goencryption/ ├── crates/ │ └── protect-ffi-c/ # Rust C FFI library -├── pkg/protect/ # Go package + precompiled static libraries +├── pkg/encryption/ # Go package + precompiled static libraries ├── examples/ # Usage examples ``` @@ -30,7 +30,7 @@ protectgo/ ## How the native library is built The Go package links a precompiled static library per platform, checked in under -`pkg/protect/` (for example `libprotect_ffi_darwin_arm64.a`). These are produced +`pkg/encryption/` (for example `libprotect_ffi_darwin_arm64.a`). These are produced in CI (see `.github/workflows/build.yml`) and committed back to the repo, so day -to-day Go development does not require a Rust toolchain. @@ -42,10 +42,10 @@ cargo build --release # Copy the resulting archive to the matching platform filename, e.g. on Apple # Silicon: -cp target/release/libprotect_ffi.a pkg/protect/libprotect_ffi_darwin_arm64.a +cp target/release/libprotect_ffi.a pkg/encryption/libprotect_ffi_darwin_arm64.a ``` -The header `pkg/protect/protect_ffi.h` is regenerated by the crate's build +The header `pkg/encryption/protect_ffi.h` is regenerated by the crate's build script (cbindgen) as part of `cargo build`. ## Building and testing the Go package @@ -91,5 +91,5 @@ The Go bindings handle memory management for you: For support and questions: -- GitHub Issues: [protectgo/issues](https://github.com/cipherstash/protectgo/issues) +- GitHub Issues: [goencryption/issues](https://github.com/cipherstash/goencryption/issues) - CipherStash Documentation: [docs.cipherstash.com](https://docs.cipherstash.com) diff --git a/README.md b/README.md index 96409aa..ca6dc9d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ alt="Built by CipherStash" /> - + License") +client, err := encryption.NewClient(ctx, + encryption.WithSchemas(users), + encryption.WithKeyset("tenant-a"), // by name, or WithKeysetID("") ) defer client.Close() @@ -310,9 +310,9 @@ schema. Select `EncryptedFormatV3` for databases provisioned with the v3 schema (typed encrypted columns — see [PostgreSQL setup](#postgresql-setup)): ```go -client, err := protect.NewClient(ctx, - protect.WithSchemas(users), - protect.WithEncryptedFormat(protect.EncryptedFormatV3), +client, err := encryption.NewClient(ctx, + encryption.WithSchemas(users), + encryption.WithEncryptedFormat(encryption.EncryptedFormatV3), ) ``` @@ -370,7 +370,7 @@ plaintext, err := client.Decrypt(ctx, encrypted) ### Bulk values ```go -items := []protect.PlaintextItem{ +items := []encryption.PlaintextItem{ {Column: users.Column("email"), Plaintext: "alice@example.com"}, {Column: users.Column("email"), Plaintext: "bob@example.com"}, } @@ -408,45 +408,45 @@ types (including `time.Time` and all integer widths) automatically. ## Querying encrypted data Encrypt search terms to query encrypted columns without exposing plaintext. -`EncryptQuery` returns an opaque `*protect.QueryTerm` — bind it directly as a +`EncryptQuery` returns an opaque `*encryption.QueryTerm` — bind it directly as a SQL parameter. Depending on the column configuration and format version, a term may serialize as a JSON object or a bare JSON string; always treat it as opaque. ```go // Exact match -term, err := client.EncryptQuery(ctx, users.Column("email"), protect.Equality, "alice@example.com") +term, err := client.EncryptQuery(ctx, users.Column("email"), encryption.Equality, "alice@example.com") // Full-text search -term, err = client.EncryptQuery(ctx, users.Column("name"), protect.FreeTextSearch, "alice") +term, err = client.EncryptQuery(ctx, users.Column("name"), encryption.FreeTextSearch, "alice") // Range comparison (works for numbers, dates, timestamps) -term, err = client.EncryptQuery(ctx, users.Column("age"), protect.OrderAndRange, 25) +term, err = client.EncryptQuery(ctx, users.Column("age"), encryption.OrderAndRange, 25) // JSON containment — does the document contain this structure? -term, err = client.EncryptQuery(ctx, users.Column("metadata"), protect.JSONContains, +term, err = client.EncryptQuery(ctx, users.Column("metadata"), encryption.JSONContains, map[string]any{"role": "admin"}) // JSON path — target one field of the document -term, err = client.EncryptQuery(ctx, users.Column("metadata"), protect.JSONSelector, "$.role") +term, err = client.EncryptQuery(ctx, users.Column("metadata"), encryption.JSONSelector, "$.role") // Inspect the raw payload if needed _ = term.String() // or term.Bytes() // Bulk — one keyservice round trip for many terms -terms, err := client.EncryptQueryBulk(ctx, []protect.QueryItem{ - {Column: users.Column("email"), QueryType: protect.Equality, Plaintext: "alice@example.com"}, - {Column: users.Column("name"), QueryType: protect.FreeTextSearch, Plaintext: "bob"}, +terms, err := client.EncryptQueryBulk(ctx, []encryption.QueryItem{ + {Column: users.Column("email"), QueryType: encryption.Equality, Plaintext: "alice@example.com"}, + {Column: users.Column("name"), QueryType: encryption.FreeTextSearch, Plaintext: "bob"}, }) ``` | Query type | Requires directive | SQL shape | |---|---|---| -| `protect.Equality` | `unique` | `WHERE col = $1` | -| `protect.FreeTextSearch` | `match` | `WHERE col LIKE $1` (v2) / `WHERE col @> $1` (v3) | -| `protect.OrderAndRange` | `ore` | `WHERE col > $1`, `ORDER BY` | -| `protect.JSONSelector` | `ste_vec` | `WHERE col -> $1 IS NOT NULL` | -| `protect.JSONContains` | `ste_vec` | `WHERE col @> $1` | +| `encryption.Equality` | `unique` | `WHERE col = $1` | +| `encryption.FreeTextSearch` | `match` | `WHERE col LIKE $1` (v2) / `WHERE col @> $1` (v3) | +| `encryption.OrderAndRange` | `ore` | `WHERE col > $1`, `ORDER BY` | +| `encryption.JSONSelector` | `ste_vec` | `WHERE col -> $1 IS NOT NULL` | +| `encryption.JSONContains` | `ste_vec` | `WHERE col @> $1` | See [PostgreSQL setup](#postgresql-setup) for the exact SQL, including the casts each format version needs. @@ -464,13 +464,13 @@ A lock context goes further and ties **individual ciphertexts** to identity claims — the same claims must be presented to decrypt: ```go -lc := &protect.LockContext{IdentityClaim: []string{"sub"}} +lc := &encryption.LockContext{IdentityClaim: []string{"sub"}} encrypted, err := client.Encrypt(ctx, users.Column("email"), "secret", - protect.WithLockContext(lc)) + encryption.WithLockContext(lc)) plaintext, err := client.Decrypt(ctx, encrypted, - protect.WithLockContext(lc)) + encryption.WithLockContext(lc)) ``` > [!IMPORTANT] @@ -490,7 +490,7 @@ derivation): ```go encrypted, err := client.Encrypt(ctx, users.Column("email"), "alice@example.com", - protect.WithAuditContext(map[string]any{"request_id": reqID, "actor": "billing-service"}), + encryption.WithAuditContext(map[string]any{"request_id": reqID, "actor": "billing-service"}), ) ``` @@ -601,14 +601,14 @@ Every operator also has a callable function equivalent (`eql_v3.eq(...)`, All errors support `errors.Is()` for programmatic handling: ```go -_, err := client.EncryptQuery(ctx, users.Column("email"), protect.OrderAndRange, "x") +_, err := client.EncryptQuery(ctx, users.Column("email"), encryption.OrderAndRange, "x") switch { -case errors.Is(err, protect.ErrMissingIndex): +case errors.Is(err, encryption.ErrMissingIndex): // the column has no `ore` directive -case errors.Is(err, protect.ErrUnknownColumn): +case errors.Is(err, encryption.ErrUnknownColumn): // column not in any registered schema -case errors.Is(err, protect.ErrClientClosed): +case errors.Is(err, encryption.ErrClientClosed): // client was already closed } ``` @@ -625,7 +625,7 @@ case errors.Is(err, protect.ErrClientClosed): | `ErrSteVecRequiresJSON` | A JSON-search directive on a non-`json` column | | `ErrClientClosed` | Client has been closed | -Errors are `*protect.Error` values carrying the failing operation +Errors are `*encryption.Error` values carrying the failing operation (`Encrypt`, `NewClient`, …) and the underlying cause via `Unwrap`. ## API reference @@ -723,4 +723,4 @@ source. --- -[Missing something?](https://github.com/cipherstash/protectgo/issues/new?template=docs-feedback.yml&title=[Docs:]%20Feedback%20on%20README.md) +[Missing something?](https://github.com/cipherstash/goencryption/issues/new?template=docs-feedback.yml&title=[Docs:]%20Feedback%20on%20README.md) diff --git a/crates/protect-ffi-c/build.rs b/crates/protect-ffi-c/build.rs index dcf6af7..a3e4170 100644 --- a/crates/protect-ffi-c/build.rs +++ b/crates/protect-ffi-c/build.rs @@ -5,7 +5,7 @@ fn main() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let output_path = PathBuf::from(&crate_dir) .join("../../") - .join("pkg/protect") + .join("pkg/encryption") .join("protect_ffi.h"); cbindgen::generate(crate_dir) diff --git a/examples/basic_usage.go b/examples/basic_usage.go index da497de..655e1ce 100644 --- a/examples/basic_usage.go +++ b/examples/basic_usage.go @@ -7,7 +7,7 @@ import ( "log" "os" - "github.com/cipherstash/protectgo/pkg/protect" + "github.com/cipherstash/goencryption/pkg/encryption" ) // User defines the data model with encryption schema using struct tags. @@ -35,7 +35,7 @@ func main() { // 1. Define schema from struct tags // --------------------------------------------------------------- - users, err := protect.TableSchema("users", User{}) + users, err := encryption.TableSchema("users", User{}) if err != nil { log.Fatalf("Failed to create schema: %v", err) } @@ -44,9 +44,9 @@ func main() { // 2. Create client with functional options // --------------------------------------------------------------- - client, err := protect.NewClient(ctx, - protect.WithSchemas(users), - protect.WithCredentials( + client, err := encryption.NewClient(ctx, + encryption.WithSchemas(users), + encryption.WithCredentials( os.Getenv("CS_WORKSPACE_CRN"), os.Getenv("CS_CLIENT_ACCESS_KEY"), os.Getenv("CS_CLIENT_ID"), @@ -69,10 +69,10 @@ func main() { // service token and caches it until expiry. A workspace CRN is required, // from WithCredentials or the CS_WORKSPACE_CRN environment variable. // - // client, err := protect.NewClient(ctx, - // protect.WithSchemas(users), - // protect.WithCredentials(crn, accessKey, clientID, clientKey), - // protect.WithOIDCFederation(func(ctx context.Context) (string, error) { + // client, err := encryption.NewClient(ctx, + // encryption.WithSchemas(users), + // encryption.WithCredentials(crn, accessKey, clientID, clientKey), + // encryption.WithOIDCFederation(func(ctx context.Context) (string, error) { // return identityProvider.AccessToken(ctx) // your app's IdP JWT // }), // ) @@ -84,9 +84,9 @@ func main() { // The default is EncryptedFormatV2. Select V3 only for databases // initialized with the v3 CipherStash database schema: // - // client, err := protect.NewClient(ctx, - // protect.WithSchemas(users), - // protect.WithEncryptedFormat(protect.EncryptedFormatV3), + // client, err := encryption.NewClient(ctx, + // encryption.WithSchemas(users), + // encryption.WithEncryptedFormat(encryption.EncryptedFormatV3), // ) // --------------------------------------------------------------- @@ -175,13 +175,13 @@ func main() { // 6. Query encryption (for searching encrypted columns) // --------------------------------------------------------------- // - // EncryptQuery returns an opaque *protect.QueryTerm. Treat it as a value to + // EncryptQuery returns an opaque *encryption.QueryTerm. Treat it as a value to // bind into your SQL statement — do not inspect its shape. Depending on the // column's index configuration it may serialize as a JSON object or a bare // JSON string. // Exact match query - queryTerm, err := client.EncryptQuery(ctx, users.Column("email"), protect.Equality, "john.doe@example.com") + queryTerm, err := client.EncryptQuery(ctx, users.Column("email"), encryption.Equality, "john.doe@example.com") if err != nil { log.Fatalf("Failed to encrypt query: %v", err) } @@ -189,7 +189,7 @@ func main() { fmt.Printf("\nEncrypted equality query term: %s\n", queryTerm) // Full-text search query - searchTerm, err := client.EncryptQuery(ctx, users.Column("name"), protect.FreeTextSearch, "john") + searchTerm, err := client.EncryptQuery(ctx, users.Column("name"), encryption.FreeTextSearch, "john") if err != nil { log.Fatalf("Failed to encrypt search query: %v", err) } @@ -197,7 +197,7 @@ func main() { fmt.Printf("Encrypted match query term (%d bytes)\n", len(searchTerm.Bytes())) // Range query - rangeTerm, err := client.EncryptQuery(ctx, users.Column("age"), protect.OrderAndRange, 25) + rangeTerm, err := client.EncryptQuery(ctx, users.Column("age"), encryption.OrderAndRange, 25) if err != nil { log.Fatalf("Failed to encrypt range query: %v", err) } @@ -210,9 +210,9 @@ func main() { // "SELECT * FROM users WHERE email = $1", queryTerm) // Bulk query encryption - bulkQueries, err := client.EncryptQueryBulk(ctx, []protect.QueryItem{ - {Column: users.Column("email"), QueryType: protect.Equality, Plaintext: "alice@example.com"}, - {Column: users.Column("name"), QueryType: protect.FreeTextSearch, Plaintext: "bob"}, + bulkQueries, err := client.EncryptQueryBulk(ctx, []encryption.QueryItem{ + {Column: users.Column("email"), QueryType: encryption.Equality, Plaintext: "alice@example.com"}, + {Column: users.Column("name"), QueryType: encryption.FreeTextSearch, Plaintext: "bob"}, }) if err != nil { log.Fatalf("Failed to bulk encrypt queries: %v", err) @@ -224,7 +224,7 @@ func main() { // 7. Bulk encrypt and decrypt individual values // --------------------------------------------------------------- - bulkEncrypted, err := client.EncryptBulk(ctx, []protect.PlaintextItem{ + bulkEncrypted, err := client.EncryptBulk(ctx, []encryption.PlaintextItem{ {Column: users.Column("email"), Plaintext: "alice@example.com"}, {Column: users.Column("email"), Plaintext: "bob@example.com"}, }) @@ -232,7 +232,7 @@ func main() { log.Fatalf("Failed to bulk encrypt: %v", err) } - decryptItems := make([]*protect.Encrypted, len(bulkEncrypted)) + decryptItems := make([]*encryption.Encrypted, len(bulkEncrypted)) for i := range bulkEncrypted { decryptItems[i] = &bulkEncrypted[i] } @@ -265,8 +265,8 @@ func main() { // 9. IsEncrypted validation // --------------------------------------------------------------- - fmt.Printf("\nIsEncrypted(encrypted value): %v\n", protect.IsEncrypted(encrypted)) - fmt.Printf("IsEncrypted(plain string): %v\n", protect.IsEncrypted("not encrypted")) + fmt.Printf("\nIsEncrypted(encrypted value): %v\n", encryption.IsEncrypted(encrypted)) + fmt.Printf("IsEncrypted(plain string): %v\n", encryption.IsEncrypted("not encrypted")) // --------------------------------------------------------------- // 10. Identity-aware encryption @@ -282,10 +282,10 @@ func main() { // identity-bearing token (i.e. WithOIDCFederation) — with plain access // key auth the platform rejects lock-context operations. // - // lockCtx := &protect.LockContext{IdentityClaim: []string{"sub"}} + // lockCtx := &encryption.LockContext{IdentityClaim: []string{"sub"}} // enc, err := client.Encrypt(ctx, users.Column("email"), "secret-data", - // protect.WithLockContext(lockCtx)) - // pt, err := client.Decrypt(ctx, enc, protect.WithLockContext(lockCtx)) + // encryption.WithLockContext(lockCtx)) + // pt, err := client.Decrypt(ctx, enc, encryption.WithLockContext(lockCtx)) // --------------------------------------------------------------- // 11. Error handling with errors.Is @@ -302,14 +302,14 @@ func main() { } // Programmatic error handling with sentinel errors. - _, err = client.EncryptQuery(ctx, users.Column("email"), protect.OrderAndRange, "test") + _, err = client.EncryptQuery(ctx, users.Column("email"), encryption.OrderAndRange, "test") if err != nil { switch { - case errors.Is(err, protect.ErrMissingIndex): + case errors.Is(err, encryption.ErrMissingIndex): fmt.Println("Index not configured for this query type (expected)") - case errors.Is(err, protect.ErrUnknownColumn): + case errors.Is(err, encryption.ErrUnknownColumn): fmt.Println("Column not found in schema") - case errors.Is(err, protect.ErrClientClosed): + case errors.Is(err, encryption.ErrClientClosed): fmt.Println("Client was already closed") default: fmt.Printf("Error: %v\n", err) diff --git a/go.mod b/go.mod index 9deab5c..e32ad61 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module github.com/cipherstash/protectgo +module github.com/cipherstash/goencryption go 1.21 diff --git a/pkg/protect/callback.go b/pkg/encryption/callback.go similarity index 99% rename from pkg/protect/callback.go rename to pkg/encryption/callback.go index 8d99162..f13a682 100644 --- a/pkg/protect/callback.go +++ b/pkg/encryption/callback.go @@ -1,4 +1,4 @@ -package protect +package encryption /* #include diff --git a/pkg/protect/protect.go b/pkg/encryption/encryption.go similarity index 94% rename from pkg/protect/protect.go rename to pkg/encryption/encryption.go index a3f2093..5168f72 100644 --- a/pkg/protect/protect.go +++ b/pkg/encryption/encryption.go @@ -1,11 +1,11 @@ -// Package protect provides field-level encryption with searchable encryption support, +// Package encryption provides field-level encryption with searchable encryption support, // powered by CipherStash ZeroKMS. // // Define your schema using struct tags or the programmatic builder, then use // the Client to encrypt, decrypt, and query encrypted data. // -// users, err := protect.TableSchema("users", User{}) -// client, err := protect.NewClient(ctx, protect.WithSchemas(users)) +// users, err := encryption.TableSchema("users", User{}) +// client, err := encryption.NewClient(ctx, encryption.WithSchemas(users)) // defer client.Close() // // encrypted, err := client.Encrypt(ctx, users.Column("email"), "john@example.com") @@ -21,7 +21,7 @@ // reads configuration from environment variables (CS_WORKSPACE_CRN, // CS_CLIENT_ACCESS_KEY, CS_CLIENT_ID, CS_CLIENT_KEY) or from // cipherstash.toml / cipherstash.secret.toml in the working directory. -package protect +package encryption /* #cgo LDFLAGS: -L${SRCDIR} @@ -113,7 +113,7 @@ func (c *Client) acquirePtr(op string) (unsafe.Pointer, func(), error) { c.mu.RLock() if c.ptr == nil { c.mu.RUnlock() - return nil, nil, &Error{Op: op, Err: ErrClientClosed, Message: "protect: client is closed"} + return nil, nil, &Error{Op: op, Err: ErrClientClosed, Message: "encryption: client is closed"} } return c.ptr, c.mu.RUnlock, nil } @@ -538,7 +538,7 @@ type ffiNewClientOptions struct { EqlVersion int `json:"eqlVersion"` } -// NewClient creates a new protect client configured with the given options. +// NewClient creates a new encryption client configured with the given options. // The ctx parameter is checked for cancellation before the FFI call. func NewClient(ctx context.Context, opts ...ClientOption) (*Client, error) { const op = "NewClient" @@ -554,7 +554,7 @@ func NewClient(ctx context.Context, opts ...ClientOption) (*Client, error) { return nil, &Error{ Op: op, Err: ErrAuthStrategy, - Message: "protect: NewClient: WithOIDCFederation and WithTokenProvider are mutually exclusive", + Message: "encryption: NewClient: WithOIDCFederation and WithTokenProvider are mutually exclusive", } } @@ -578,7 +578,7 @@ func NewClient(ctx context.Context, opts ...ClientOption) (*Client, error) { return nil, &Error{ Op: op, Err: ErrAuthStrategy, - Message: "protect: NewClient: WithOIDCFederation requires a workspace CRN: set it via WithCredentials or the CS_WORKSPACE_CRN environment variable (workspaceCrn is required)", + Message: "encryption: NewClient: WithOIDCFederation requires a workspace CRN: set it via WithCredentials or the CS_WORKSPACE_CRN environment variable (workspaceCrn is required)", } } if ffiOpts.ClientOpts == nil { @@ -595,12 +595,12 @@ func NewClient(ctx context.Context, opts ...ClientOption) (*Client, error) { } if err := ctx.Err(); err != nil { - return nil, fmt.Errorf("protect: %s: %w", op, err) + return nil, fmt.Errorf("encryption: %s: %w", op, err) } optionsJSON, err := json.Marshal(ffiOpts) if err != nil { - return nil, fmt.Errorf("protect: %s: marshaling options: %w", op, err) + return nil, fmt.Errorf("encryption: %s: marshaling options: %w", op, err) } cOptionsJSON := C.CString(string(optionsJSON)) @@ -758,7 +758,7 @@ func (c *Client) Encrypt(ctx context.Context, col ColumnRef, plaintext any, opts defer unlock() if err := ctx.Err(); err != nil { - return nil, fmt.Errorf("protect: %s: %w", op, err) + return nil, fmt.Errorf("encryption: %s: %w", op, err) } co := buildCallOpts(opts) @@ -781,7 +781,7 @@ func (c *Client) Encrypt(ctx context.Context, col ColumnRef, plaintext any, opts optionsJSON, err := json.Marshal(ffiOpts) if err != nil { - return nil, fmt.Errorf("protect: %s: marshaling options: %w", op, err) + return nil, fmt.Errorf("encryption: %s: marshaling options: %w", op, err) } cOptionsJSON := C.CString(string(optionsJSON)) @@ -799,7 +799,7 @@ func (c *Client) Encrypt(ctx context.Context, col ColumnRef, plaintext any, opts var encrypted Encrypted if err := json.Unmarshal([]byte(encryptedJSON), &encrypted); err != nil { - return nil, fmt.Errorf("protect: %s: unmarshaling result: %w", op, err) + return nil, fmt.Errorf("encryption: %s: unmarshaling result: %w", op, err) } return &encrypted, nil @@ -823,7 +823,7 @@ func (c *Client) Decrypt(ctx context.Context, encrypted *Encrypted, opts ...Opti defer unlock() if err := ctx.Err(); err != nil { - return nil, fmt.Errorf("protect: %s: %w", op, err) + return nil, fmt.Errorf("encryption: %s: %w", op, err) } co := buildCallOpts(opts) @@ -842,7 +842,7 @@ func (c *Client) Decrypt(ctx context.Context, encrypted *Encrypted, opts ...Opti optionsJSON, err := json.Marshal(ffiOpts) if err != nil { - return nil, fmt.Errorf("protect: %s: marshaling options: %w", op, err) + return nil, fmt.Errorf("encryption: %s: marshaling options: %w", op, err) } cOptionsJSON := C.CString(string(optionsJSON)) @@ -860,7 +860,7 @@ func (c *Client) Decrypt(ctx context.Context, encrypted *Encrypted, opts ...Opti var plaintext any if err := decodeFFIJSON([]byte(plaintextJSON), &plaintext); err != nil { - return nil, fmt.Errorf("protect: %s: unmarshaling result: %w", op, err) + return nil, fmt.Errorf("encryption: %s: unmarshaling result: %w", op, err) } return plaintext, nil @@ -883,7 +883,7 @@ func (c *Client) EncryptBulk(ctx context.Context, items []PlaintextItem, opts .. defer unlock() if err := ctx.Err(); err != nil { - return nil, fmt.Errorf("protect: %s: %w", op, err) + return nil, fmt.Errorf("encryption: %s: %w", op, err) } co := buildCallOpts(opts) @@ -920,7 +920,7 @@ func (c *Client) EncryptBulk(ctx context.Context, items []PlaintextItem, opts .. optionsJSON, err := json.Marshal(ffiOpts) if err != nil { - return nil, fmt.Errorf("protect: %s: marshaling options: %w", op, err) + return nil, fmt.Errorf("encryption: %s: marshaling options: %w", op, err) } cOptionsJSON := C.CString(string(optionsJSON)) @@ -938,7 +938,7 @@ func (c *Client) EncryptBulk(ctx context.Context, items []PlaintextItem, opts .. var encrypted []Encrypted if err := json.Unmarshal([]byte(encryptedJSON), &encrypted); err != nil { - return nil, fmt.Errorf("protect: %s: unmarshaling result: %w", op, err) + return nil, fmt.Errorf("encryption: %s: unmarshaling result: %w", op, err) } return encrypted, nil @@ -960,7 +960,7 @@ func (c *Client) DecryptBulk(ctx context.Context, items []*Encrypted, opts ...Op defer unlock() if err := ctx.Err(); err != nil { - return nil, fmt.Errorf("protect: %s: %w", op, err) + return nil, fmt.Errorf("encryption: %s: %w", op, err) } co := buildCallOpts(opts) @@ -989,7 +989,7 @@ func (c *Client) DecryptBulk(ctx context.Context, items []*Encrypted, opts ...Op optionsJSON, err := json.Marshal(ffiOpts) if err != nil { - return nil, fmt.Errorf("protect: %s: marshaling options: %w", op, err) + return nil, fmt.Errorf("encryption: %s: marshaling options: %w", op, err) } cOptionsJSON := C.CString(string(optionsJSON)) @@ -1007,7 +1007,7 @@ func (c *Client) DecryptBulk(ctx context.Context, items []*Encrypted, opts ...Op var plaintexts []any if err := decodeFFIJSON([]byte(plaintextJSON), &plaintexts); err != nil { - return nil, fmt.Errorf("protect: %s: unmarshaling result: %w", op, err) + return nil, fmt.Errorf("encryption: %s: unmarshaling result: %w", op, err) } return plaintexts, nil @@ -1032,7 +1032,7 @@ func (c *Client) DecryptBulkFallible(ctx context.Context, items []*Encrypted, op defer unlock() if err := ctx.Err(); err != nil { - return nil, fmt.Errorf("protect: %s: %w", op, err) + return nil, fmt.Errorf("encryption: %s: %w", op, err) } co := buildCallOpts(opts) @@ -1061,7 +1061,7 @@ func (c *Client) DecryptBulkFallible(ctx context.Context, items []*Encrypted, op optionsJSON, err := json.Marshal(ffiOpts) if err != nil { - return nil, fmt.Errorf("protect: %s: marshaling options: %w", op, err) + return nil, fmt.Errorf("encryption: %s: marshaling options: %w", op, err) } cOptionsJSON := C.CString(string(optionsJSON)) @@ -1084,7 +1084,7 @@ func (c *Client) DecryptBulkFallible(ctx context.Context, items []*Encrypted, op var ffiResults []ffiDecryptResult if err := decodeFFIJSON([]byte(resultsJSON), &ffiResults); err != nil { - return nil, fmt.Errorf("protect: %s: unmarshaling result: %w", op, err) + return nil, fmt.Errorf("encryption: %s: unmarshaling result: %w", op, err) } results := make([]DecryptResult, len(ffiResults)) @@ -1120,7 +1120,7 @@ func (c *Client) EncryptQuery(ctx context.Context, col ColumnRef, queryType Quer defer unlock() if err := ctx.Err(); err != nil { - return nil, fmt.Errorf("protect: %s: %w", op, err) + return nil, fmt.Errorf("encryption: %s: %w", op, err) } co := buildCallOpts(opts) @@ -1149,7 +1149,7 @@ func (c *Client) EncryptQuery(ctx context.Context, col ColumnRef, queryType Quer optionsJSON, err := json.Marshal(ffiOpts) if err != nil { - return nil, fmt.Errorf("protect: %s: marshaling options: %w", op, err) + return nil, fmt.Errorf("encryption: %s: marshaling options: %w", op, err) } cOptionsJSON := C.CString(string(optionsJSON)) @@ -1184,7 +1184,7 @@ func (c *Client) EncryptQueryBulk(ctx context.Context, queries []QueryItem, opts defer unlock() if err := ctx.Err(); err != nil { - return nil, fmt.Errorf("protect: %s: %w", op, err) + return nil, fmt.Errorf("encryption: %s: %w", op, err) } co := buildCallOpts(opts) @@ -1226,7 +1226,7 @@ func (c *Client) EncryptQueryBulk(ctx context.Context, queries []QueryItem, opts optionsJSON, err := json.Marshal(ffiOpts) if err != nil { - return nil, fmt.Errorf("protect: %s: marshaling options: %w", op, err) + return nil, fmt.Errorf("encryption: %s: marshaling options: %w", op, err) } cOptionsJSON := C.CString(string(optionsJSON)) @@ -1244,7 +1244,7 @@ func (c *Client) EncryptQueryBulk(ctx context.Context, queries []QueryItem, opts var raw []json.RawMessage if err := json.Unmarshal([]byte(termsJSON), &raw); err != nil { - return nil, fmt.Errorf("protect: %s: unmarshaling result: %w", op, err) + return nil, fmt.Errorf("encryption: %s: unmarshaling result: %w", op, err) } terms := make([]*QueryTerm, len(raw)) diff --git a/pkg/protect/protect_test.go b/pkg/encryption/encryption_test.go similarity index 99% rename from pkg/protect/protect_test.go rename to pkg/encryption/encryption_test.go index 91645a1..d33d065 100644 --- a/pkg/protect/protect_test.go +++ b/pkg/encryption/encryption_test.go @@ -1,4 +1,4 @@ -package protect +package encryption import ( "context" @@ -946,12 +946,12 @@ func TestErrorUnknownMessage(t *testing.T) { func TestErrorClientClosed(t *testing.T) { t.Parallel() - err := &Error{Op: "Encrypt", Err: ErrClientClosed, Message: "protect: client is closed"} + err := &Error{Op: "Encrypt", Err: ErrClientClosed, Message: "encryption: client is closed"} if !errors.Is(err, ErrClientClosed) { t.Error("errors.Is(err, ErrClientClosed) = false, want true") } - if err.Error() != "protect: client is closed" { + if err.Error() != "encryption: client is closed" { t.Errorf("Error(): got %q", err.Error()) } } diff --git a/pkg/protect/errors.go b/pkg/encryption/errors.go similarity index 78% rename from pkg/protect/errors.go rename to pkg/encryption/errors.go index 7b5e74d..3b5485b 100644 --- a/pkg/protect/errors.go +++ b/pkg/encryption/errors.go @@ -1,56 +1,56 @@ -package protect +package encryption import ( "errors" "strings" ) -// Sentinel errors returned by the protect SDK. Use errors.Is() to check +// Sentinel errors returned by the encryption SDK. Use errors.Is() to check // for specific error conditions. var ( // ErrUnknownColumn indicates the column was not found in the encrypt config. - ErrUnknownColumn = errors.New("protect: unknown column") + ErrUnknownColumn = errors.New("encryption: unknown column") // ErrMissingIndex indicates the column does not have the required index type. - ErrMissingIndex = errors.New("protect: missing index") + ErrMissingIndex = errors.New("encryption: missing index") // ErrInvalidQueryInput indicates the query input value is invalid for the index type. - ErrInvalidQueryInput = errors.New("protect: invalid query input") + ErrInvalidQueryInput = errors.New("encryption: invalid query input") // ErrInvalidJSONPath indicates an invalid JSON path was provided. - ErrInvalidJSONPath = errors.New("protect: invalid JSON path") + ErrInvalidJSONPath = errors.New("encryption: invalid JSON path") // ErrUnknownQueryOp indicates an unknown query operation was requested. - ErrUnknownQueryOp = errors.New("protect: unknown query operation") + ErrUnknownQueryOp = errors.New("encryption: unknown query operation") // ErrClientClosed indicates the client has already been closed. - ErrClientClosed = errors.New("protect: client is closed") + ErrClientClosed = errors.New("encryption: client is closed") // ErrInvariantViolation indicates an internal invariant was violated. - ErrInvariantViolation = errors.New("protect: invariant violation") + ErrInvariantViolation = errors.New("encryption: invariant violation") // ErrSteVecRequiresJSON indicates an ste_vec index requires a JSON cast type. - ErrSteVecRequiresJSON = errors.New("protect: ste_vec requires json cast type") + ErrSteVecRequiresJSON = errors.New("encryption: ste_vec requires json cast type") // ErrUnsupportedFormat indicates the column's index configuration has no // equivalent in the selected encrypted format. This typically means a // column uses an index or cast type that the chosen ciphertext format // (see [WithEncryptedFormat]) cannot represent. - ErrUnsupportedFormat = errors.New("protect: unsupported encrypted format for column") + ErrUnsupportedFormat = errors.New("encryption: unsupported encrypted format for column") // ErrInvalidCiphertext indicates a value passed for decryption is not a // valid ciphertext payload. - ErrInvalidCiphertext = errors.New("protect: invalid ciphertext") + ErrInvalidCiphertext = errors.New("encryption: invalid ciphertext") // ErrAuthStrategy indicates a client authentication strategy is // misconfigured — for example [WithOIDCFederation] was selected without a // workspace CRN, or a token callback is required but was not supplied. - ErrAuthStrategy = errors.New("protect: auth strategy misconfigured") + ErrAuthStrategy = errors.New("encryption: auth strategy misconfigured") // ErrFFI indicates an unclassified error from the FFI layer. // Use errors.Is(err, ErrFFI) to check if an error originated from the // underlying encryption engine when no more specific sentinel applies. - ErrFFI = errors.New("protect: FFI error") + ErrFFI = errors.New("encryption: FFI error") ) // Error is a structured error from the encryption SDK. diff --git a/pkg/protect/libprotect_ffi_darwin_arm64.a b/pkg/encryption/libprotect_ffi_darwin_arm64.a similarity index 100% rename from pkg/protect/libprotect_ffi_darwin_arm64.a rename to pkg/encryption/libprotect_ffi_darwin_arm64.a diff --git a/pkg/protect/libprotect_ffi_darwin_x64.a b/pkg/encryption/libprotect_ffi_darwin_x64.a similarity index 100% rename from pkg/protect/libprotect_ffi_darwin_x64.a rename to pkg/encryption/libprotect_ffi_darwin_x64.a diff --git a/pkg/protect/libprotect_ffi_linux_arm64.a b/pkg/encryption/libprotect_ffi_linux_arm64.a similarity index 100% rename from pkg/protect/libprotect_ffi_linux_arm64.a rename to pkg/encryption/libprotect_ffi_linux_arm64.a diff --git a/pkg/protect/libprotect_ffi_linux_arm64_musl.a b/pkg/encryption/libprotect_ffi_linux_arm64_musl.a similarity index 100% rename from pkg/protect/libprotect_ffi_linux_arm64_musl.a rename to pkg/encryption/libprotect_ffi_linux_arm64_musl.a diff --git a/pkg/protect/libprotect_ffi_linux_x64.a b/pkg/encryption/libprotect_ffi_linux_x64.a similarity index 100% rename from pkg/protect/libprotect_ffi_linux_x64.a rename to pkg/encryption/libprotect_ffi_linux_x64.a diff --git a/pkg/protect/libprotect_ffi_linux_x64_musl.a b/pkg/encryption/libprotect_ffi_linux_x64_musl.a similarity index 100% rename from pkg/protect/libprotect_ffi_linux_x64_musl.a rename to pkg/encryption/libprotect_ffi_linux_x64_musl.a diff --git a/pkg/protect/model.go b/pkg/encryption/model.go similarity index 87% rename from pkg/protect/model.go rename to pkg/encryption/model.go index 9ccf39e..f439dbb 100644 --- a/pkg/protect/model.go +++ b/pkg/encryption/model.go @@ -1,4 +1,4 @@ -package protect +package encryption import ( "context" @@ -134,17 +134,17 @@ func (c *Client) EncryptModel(ctx context.Context, schema *TableDef, model any) v := reflect.ValueOf(model) if v.Kind() == reflect.Ptr { if v.IsNil() { - return nil, fmt.Errorf("protect: EncryptModel: model must not be nil") + return nil, fmt.Errorf("encryption: EncryptModel: model must not be nil") } v = v.Elem() } if v.Kind() != reflect.Struct { - return nil, fmt.Errorf("protect: EncryptModel: model must be a struct, got %s", v.Kind()) + return nil, fmt.Errorf("encryption: EncryptModel: model must be a struct, got %s", v.Kind()) } info, err := analyzeStruct(v.Type()) if err != nil { - return nil, fmt.Errorf("protect: EncryptModel: analyzing model: %w", err) + return nil, fmt.Errorf("encryption: EncryptModel: analyzing model: %w", err) } result := make(map[string]any, len(info.EncryptedFields)+len(info.PlainFields)) @@ -164,7 +164,7 @@ func (c *Client) EncryptModel(ctx context.Context, schema *TableDef, model any) encrypted, err := c.Encrypt(ctx, schema.Column(ef.Column), plaintext) if err != nil { - return nil, fmt.Errorf("protect: EncryptModel: field %q (column %q): %w", ef.MapKey, ef.Column, err) + return nil, fmt.Errorf("encryption: EncryptModel: field %q (column %q): %w", ef.MapKey, ef.Column, err) } result[ef.MapKey] = encrypted } @@ -187,16 +187,16 @@ func (c *Client) DecryptModel(ctx context.Context, schema *TableDef, data map[st v := reflect.ValueOf(dest) if v.Kind() != reflect.Ptr || v.IsNil() { - return fmt.Errorf("protect: DecryptModel: dest must be a non-nil pointer to a struct") + return fmt.Errorf("encryption: DecryptModel: dest must be a non-nil pointer to a struct") } v = v.Elem() if v.Kind() != reflect.Struct { - return fmt.Errorf("protect: DecryptModel: dest must be a pointer to a struct, got pointer to %s", v.Kind()) + return fmt.Errorf("encryption: DecryptModel: dest must be a pointer to a struct, got pointer to %s", v.Kind()) } info, err := analyzeStruct(v.Type()) if err != nil { - return fmt.Errorf("protect: DecryptModel: analyzing dest: %w", err) + return fmt.Errorf("encryption: DecryptModel: analyzing dest: %w", err) } // Set plain fields. @@ -217,12 +217,12 @@ func (c *Client) DecryptModel(ctx context.Context, schema *TableDef, data map[st encrypted, err := toEncrypted(rawVal) if err != nil { - return fmt.Errorf("protect: DecryptModel: converting field %q to Encrypted: %w", ef.MapKey, err) + return fmt.Errorf("encryption: DecryptModel: converting field %q to Encrypted: %w", ef.MapKey, err) } plaintext, err := c.Decrypt(ctx, encrypted) if err != nil { - return fmt.Errorf("protect: DecryptModel: field %q (column %q): %w", ef.MapKey, ef.Column, err) + return fmt.Errorf("encryption: DecryptModel: field %q (column %q): %w", ef.MapKey, ef.Column, err) } setFieldValue(v.Field(ef.Index), plaintext) @@ -246,12 +246,12 @@ func (c *Client) BulkEncryptModels(ctx context.Context, schema *TableDef, models sv := reflect.ValueOf(models) if sv.Kind() == reflect.Ptr { if sv.IsNil() { - return nil, fmt.Errorf("protect: BulkEncryptModels: models must not be nil") + return nil, fmt.Errorf("encryption: BulkEncryptModels: models must not be nil") } sv = sv.Elem() } if sv.Kind() != reflect.Slice { - return nil, fmt.Errorf("protect: BulkEncryptModels: models must be a slice, got %s", sv.Kind()) + return nil, fmt.Errorf("encryption: BulkEncryptModels: models must be a slice, got %s", sv.Kind()) } if sv.Len() == 0 { return []map[string]any{}, nil @@ -264,7 +264,7 @@ func (c *Client) BulkEncryptModels(ctx context.Context, schema *TableDef, models info, err := analyzeStruct(elemType) if err != nil { - return nil, fmt.Errorf("protect: BulkEncryptModels: analyzing model type: %w", err) + return nil, fmt.Errorf("encryption: BulkEncryptModels: analyzing model type: %w", err) } numModels := sv.Len() @@ -320,11 +320,11 @@ func (c *Client) BulkEncryptModels(ctx context.Context, schema *TableDef, models encrypted, err := c.EncryptBulk(ctx, payloads) if err != nil { - return nil, fmt.Errorf("protect: BulkEncryptModels: %w", err) + return nil, fmt.Errorf("encryption: BulkEncryptModels: %w", err) } if len(encrypted) != len(positions) { - return nil, fmt.Errorf("protect: BulkEncryptModels: bulk encrypt returned %d results, expected %d", len(encrypted), len(positions)) + return nil, fmt.Errorf("encryption: BulkEncryptModels: bulk encrypt returned %d results, expected %d", len(encrypted), len(positions)) } // Distribute encrypted values back. @@ -350,11 +350,11 @@ func (c *Client) BulkDecryptModels(ctx context.Context, schema *TableDef, data [ dv := reflect.ValueOf(dest) if dv.Kind() != reflect.Ptr || dv.IsNil() { - return fmt.Errorf("protect: BulkDecryptModels: dest must be a non-nil pointer to a slice of structs") + return fmt.Errorf("encryption: BulkDecryptModels: dest must be a non-nil pointer to a slice of structs") } sliceVal := dv.Elem() if sliceVal.Kind() != reflect.Slice { - return fmt.Errorf("protect: BulkDecryptModels: dest must be a pointer to a slice, got pointer to %s", sliceVal.Kind()) + return fmt.Errorf("encryption: BulkDecryptModels: dest must be a pointer to a slice, got pointer to %s", sliceVal.Kind()) } elemType := sliceVal.Type().Elem() @@ -364,7 +364,7 @@ func (c *Client) BulkDecryptModels(ctx context.Context, schema *TableDef, data [ info, err := analyzeStruct(elemType) if err != nil { - return fmt.Errorf("protect: BulkDecryptModels: analyzing dest element type: %w", err) + return fmt.Errorf("encryption: BulkDecryptModels: analyzing dest element type: %w", err) } numMaps := len(data) @@ -385,7 +385,7 @@ func (c *Client) BulkDecryptModels(ctx context.Context, schema *TableDef, data [ } encrypted, err := toEncrypted(rawVal) if err != nil { - return fmt.Errorf("protect: BulkDecryptModels: converting field %q in map[%d] to Encrypted: %w", ef.MapKey, i, err) + return fmt.Errorf("encryption: BulkDecryptModels: converting field %q in map[%d] to Encrypted: %w", ef.MapKey, i, err) } ciphertexts = append(ciphertexts, encrypted) positions = append(positions, decryptPos{mapIdx: i, fieldIdx: j}) @@ -415,11 +415,11 @@ func (c *Client) BulkDecryptModels(ctx context.Context, schema *TableDef, data [ if len(ciphertexts) > 0 { plaintexts, err := c.DecryptBulk(ctx, ciphertexts) if err != nil { - return fmt.Errorf("protect: BulkDecryptModels: %w", err) + return fmt.Errorf("encryption: BulkDecryptModels: %w", err) } if len(plaintexts) != len(positions) { - return fmt.Errorf("protect: BulkDecryptModels: bulk decrypt returned %d results, expected %d", len(plaintexts), len(positions)) + return fmt.Errorf("encryption: BulkDecryptModels: bulk decrypt returned %d results, expected %d", len(plaintexts), len(positions)) } for i, pos := range positions { diff --git a/pkg/protect/model_test.go b/pkg/encryption/model_test.go similarity index 99% rename from pkg/protect/model_test.go rename to pkg/encryption/model_test.go index cbf3df6..a369f0c 100644 --- a/pkg/protect/model_test.go +++ b/pkg/encryption/model_test.go @@ -1,4 +1,4 @@ -package protect +package encryption import ( "context" diff --git a/pkg/protect/protect_ffi.h b/pkg/encryption/protect_ffi.h similarity index 100% rename from pkg/protect/protect_ffi.h rename to pkg/encryption/protect_ffi.h diff --git a/pkg/protect/schema.go b/pkg/encryption/schema.go similarity index 97% rename from pkg/protect/schema.go rename to pkg/encryption/schema.go index 252cd5e..3f0e1e2 100644 --- a/pkg/protect/schema.go +++ b/pkg/encryption/schema.go @@ -1,4 +1,4 @@ -package protect +package encryption import ( "fmt" @@ -28,7 +28,7 @@ func (td *TableDef) Name() string { // For a non-panicking alternative, use [TableDef.ColumnOK]. func (td *TableDef) Column(name string) ColumnRef { if _, ok := td.columns[name]; !ok { - panic(fmt.Sprintf("protect: column %q not found in table %q", name, td.name)) + panic(fmt.Sprintf("encryption: column %q not found in table %q", name, td.name)) } return ColumnRef{table: td.name, column: name} } @@ -49,13 +49,13 @@ func (td *TableDef) ColumnOK(name string) (ColumnRef, bool) { func TableSchema(tableName string, model any) (*TableDef, error) { typ := reflect.TypeOf(model) if typ == nil { - return nil, fmt.Errorf("protect.TableSchema: model must not be nil") + return nil, fmt.Errorf("encryption.TableSchema: model must not be nil") } if typ.Kind() == reflect.Ptr { typ = typ.Elem() } if typ.Kind() != reflect.Struct { - return nil, fmt.Errorf("protect.TableSchema: model must be a struct, got %s", typ.Kind()) + return nil, fmt.Errorf("encryption.TableSchema: model must be a struct, got %s", typ.Kind()) } columns := make(map[string]Column) diff --git a/pkg/protect/schema_test.go b/pkg/encryption/schema_test.go similarity index 99% rename from pkg/protect/schema_test.go rename to pkg/encryption/schema_test.go index 3e38131..cef7ff8 100644 --- a/pkg/protect/schema_test.go +++ b/pkg/encryption/schema_test.go @@ -1,4 +1,4 @@ -package protect +package encryption import ( "encoding/json"