{"id":16188999,"url":"https://github.com/fogfish/cryptex","last_synced_at":"2025-06-11T09:32:12.059Z","repository":{"id":57576643,"uuid":"238260438","full_name":"fogfish/cryptex","owner":"fogfish","description":"Semi-automatic cipher for Algebraic Data Types in Golang","archived":false,"fork":false,"pushed_at":"2020-07-14T05:44:00.000Z","size":29,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-18T16:25:45.795Z","etag":null,"topics":["aws-kms","encryption","golang","json","sensitive-data"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fogfish.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-04T17:09:56.000Z","updated_at":"2020-07-14T05:43:58.000Z","dependencies_parsed_at":"2022-09-26T19:02:36.046Z","dependency_job_id":null,"html_url":"https://github.com/fogfish/cryptex","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fcryptex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fcryptex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fcryptex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fcryptex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fogfish","download_url":"https://codeload.github.com/fogfish/cryptex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fcryptex/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259238902,"owners_count":22826815,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-kms","encryption","golang","json","sensitive-data"],"created_at":"2024-10-10T07:33:17.785Z","updated_at":"2025-06-11T09:32:12.037Z","avatar_url":"https://github.com/fogfish.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\n  \u003ch3 align=\"center\"\u003eCryptex\u003c/h3\u003e\n  \u003cp align=\"center\"\u003e\u003cstrong\u003ePassing Sensitive Data with JSON\u003c/strong\u003e\u003c/p\u003e\n\n  \u003cp align=\"center\"\u003e\n    \u003c!-- Documentation --\u003e\n    \u003ca href=\"http://godoc.org/github.com/fogfish/cryptex\"\u003e\n      \u003cimg src=\"https://godoc.org/github.com/fogfish/cryptex?status.svg\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Build Status  --\u003e\n    \u003ca href=\"http://travis-ci.org/fogfish/cryptex\"\u003e\n      \u003cimg src=\"https://secure.travis-ci.org/fogfish/cryptex.svg?branch=master\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- GitHub --\u003e\n    \u003ca href=\"http://github.com/fogfish/cryptex\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/last-commit/fogfish/cryptex.svg\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Coverage --\u003e\n    \u003ca href=\"https://coveralls.io/github/fogfish/cryptex?branch=master\"\u003e\n      \u003cimg src=\"https://coveralls.io/repos/github/fogfish/cryptex/badge.svg?branch=master\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Go Card --\u003e\n    \u003ca href=\"https://goreportcard.com/report/github.com/fogfish/cryptex\"\u003e\n      \u003cimg src=\"https://goreportcard.com/badge/github.com/fogfish/cryptex\" /\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n--- \n\n\u003e The word cryptex is a neologism coined by the author Dan Brown for his 2003 novel The Da Vinci Code, denoting a portable vault used to hide secret messages.\n\nEncryption **in transit** and **at rest** are best practices to deal with sensitive data. Software engineers MUST ensure that the data is always transmitted using strong encryption standards and also protected with strong encryption at storages. Cloud Services offers rich variate of products to deal with it - [AWS Key Management](https://aws.amazon.com/kms/) is great example. It implements a centralized control over the cryptographic keys and integrates with other AWS services to encrypt data.\n\nThe encryption works transparently inside cloud services. It becomes a responsibility of engineers to handle sensitive data outside of the cloud. The usage of traditional operating system services opens few [issues](https://baffle.io/encrypting-data-is-complex):\n\n* disk level encryption protects against physical theft. Operating system services clear text to any one.\n\n* transparent data encryption protects against direct file system access. The database engine provides clear text to its applications.\n\nAWS KMS provides [SDK](https://docs.aws.amazon.com/sdk-for-go/api/service/kms/) for developers to integrate encryption to they application. You can benefit from strong encryption with ability of fine-grained access control to sensitive data for application that runs outside of AWS data centers. AWS KMS helps you with implementation of Application Level Encryption and Record Level Encryption - encryption of fields in a structured data using different keys for different instances. The IAM roles delegates rights to decrypt sensitive data. \n\n[The design of KMS](https://d0.awsstatic.com/whitepapers/KMS-Cryptographic-Details.pdf) ensures that no one, including AWS employees, can get access to your encryption keys. This key management solution is compliant with FIPS 140-2 and audited by independent groups.\n\n\n## Encryption of structured data\n\nHere we are continue discussion about the developer friendly solution to apply Application/Record Level Encryption with help of KMS for sensitive structured data (e.g. JSON). My design aims to address few requirements:\n\n* transparent for developers - encryption/decryption is built with semi-auto codec. It makes a \"magic\" of switching representation between crypto/plain texts. Developer just declares the intent to protect sensitive data. \n\n* compile time type-safeness - the sensitive data is modelled with algebraic data types. The type tagging (annotation) is used to declare the the intent to protect sensitive data. Golang compiler discover and prevents type errors or other glitches at the time it assembles binaries.\n\n* generic - encryption/decryption are generic algorithms applicable to any algebraic data types (not only to strings). The library provides ability to apply algorithms for any product type in developer's application context.\n\n* [data in use](https://en.wikipedia.org/wiki/Data_in_use) **is not supported**. Developers have to combine this library with [MemGuard](https://github.com/awnumar/memguard).   \n\n\n## Golang Encryption Codec\n\nGolang has excellent [built-in abstraction](https://blog.golang.org/json-and-go) to encode/decode structured data into JSON data interchange format. We embed crypto codec into `json.Marshal` and `json.Unmarshal` routines so that protection of sensitive data is semi-automatic during the process of data serialization.\n\n```go\nMyADT{Secret: \"plaintext\"} ⟷ {\"secret\":\"cGxhaW50ZXh0\"}\n```\n\nSemi-automatic encryption can be achieved either using [struct tags](https://medium.com/golangspec/tags-in-golang-3e5db0b8ef3e) or custom types. Struct tags is a feature to annotate algebraic data types but it requires usage of reflection, which do not provide compile type safeness. This library implements final type to encrypt/decrypt strings `cryptex.String` and generic type `cryptex.AnyT`, which allows to handle any application specific algebraic data types.\n\n### AWS KMS SDK\n\nCrypto binary data is produced either by [AWS KMS SDK](https://docs.aws.amazon.com/sdk-for-go/api/service/kms/) or AWS command line utility. The following code sketches usage of KMS to protect sensitive data. Note: error handling is skipped just to illustrate usage of api.\n\n```golang\nfunc Decrypt(cryptotext string) plaintext []byte {\n  bytes, err := base64.StdEncoding.DecodeString(cryptotext)\n\tinput := \u0026kms.DecryptInput{ CiphertextBlob: []byte(bytes) }\n\tresult, err := kms.api.Decrypt(input)\n\treturn result.Plaintext\n}\n\nfunc Encrypt(plaintext []byte) cryptotext string {\n\tinput := \u0026kms.EncryptInput{\n\t\tKeyId:     aws.String(kms.key),\n\t\tPlaintext: plaintext,\n\t}\n\tresult, err := kms.api.Encrypt(input)\n\treturn base64.StdEncoding.EncodeToString(result.CiphertextBlob)\n}\n```\n\n### Strings encryption\n\nUse `cryptex.String` to deal with sensitive textual content. Its implementation assumes that binary crypto text is encoded with base64url, which makes is usable with any text-based protocols, file names and URLs.\n\nThe usage of `cryptex.String` data type in your application is straight forward:\n\n```go\nimport (\n\t\"github.com/fogfish/cryptex\"\n\t\"github.com/fogfish/cryptex/cipher\"\n)\n\n// You have to define either KMS key id or its alias if your application needs to\n// encrypt data. You can skip this state if you application only decrypts data.\ncipher.Default.UseKey(\"alias/mykms-key\")\n\n// Do not use built-in `string` type for sensitive data in data structure, which\n// leaves boundaries of your application (e.g. sent to client, stored to disk, etc).\n// Use `cryptex.String` instead.\ntype User struct {\n  Password cryptex.String `json:\"password\"`\n}\n\n// The type of `cryptex.String` is used as usual to keep your plain text data in memory.\n// A sensitive value is not assignable to variable of type `string`. You have to either \n// use helper method `PlainText` e.g. `user.Password.PlainText()` or cast it to string.\n// A simple protection against accidental leakage.\nuser := User{\"sensitive data\"}\n\n// The data is automatically encrypted when you marshal it to the-wire format\n// The output JSON looks like {\"password\":\"cGShaW53ZXh0...\"}\nbytes, err := json.Marshal(\u0026user)\n\n// The data is automatically decrypted when you unmarshall it.\nerr := json.Unmarshal(bytes, \u0026user)\n```\n\n### Algebraic Data Types encryption\n\nYou might experience encryption overhead if multiple fields with sensitive textual data are involved. It becomes more efficient to use product data type as a container of sensitive data. Use [golem generic](https://github.com/fogfish/golem/tree/master/generic) to parametrize `cryptex.AnyT` with your data type. `cryptex.AnyT` converts Algebraic Data Types to JSON then encrypts and applies base64 transformation. Use `go generate` to parametrize generic algorithm with you data type. Here is a minimal example \n\n```go\n// Just create a package for your ADT. Add the following line to comments.\n// It instructs code generator to parametrize generic algorithm with you data type.\n//go:generate golem -T Identity -generic github.com/fogfish/cryptex/cryptex.go\npackage identity\n\n// Declare a type as standard golang struct.\ntype Identity struct {\n  Email    string `json:\"email\"`\n  Password string `json:\"password\"`\n  PinCode  int    `json:\"pincode\"`\n}\n```\n\nAs the result, you'll get new data type `identity.Cryptex`. It knows how to encrypt/decrypt your ADT. Its usage is straight forward:\n\n```go\nimport (\n  \".../identity\"\n)\n\n// Do not use plain text type. Use `identity.Cryptex` it ensures protection of\n// sensitive data when it leaves boundaries of your application.\ntype User struct {\n  Identity identity.Cryptex `json:\"identity\"`\n}\n\n// `identity.Cryptex` is an alias to `identity.Identity` type. Instantiate it with\n// same interface as original one.\nuser := User{\n  Identity: identity.Cryptex{\n    Email:    \"any@example.com\",\n    Password: \"sensitive data\",\n    PinCode:  1234,\n  },\n}\n\n// The data is automatically encrypted when you marshal it to the-wire format\n// The output JSON looks like {\"identity\":\"cGShaW53ZXh0...\"}. The data is\n// automatically decrypted and re-packed to struct when you unmarshall it.\nbytes, err := json.Marshal(\u0026user)\nerr := json.Unmarshal(bytes, \u0026user)\n```\n\n### Environment Variables\n\nUsage of Environment Variables is a [common approach](https://12factor.net/config) to store application configuration. Encryption is required to deal with credentials or other sensitive\ndata. Use AWS command-line and this library to protect your config:\n\n```bash\naws kms encrypt \\\n  --key-id alias/mykms-key \\\n  --plaintext \"PlainText\" \\\n  --query CiphertextBlob \\\n  --output text\n\nexport MY_CONFIG=...\n```\n\nCryptex library implements Golang standard semantic (`os` package) to deal with environment \nvariables. It transparently encrypt/decrypt them with KMS key.\n\n```go\ncryptex.Getenv(\"MY_CONFIG\")\ncryptex.LookupEnv(\"MY_CONFIG\")\n```\n\n\n## Afterwords\n\nSoftware engineers are responsible to retain confidentiality of sensitive data in they applications. The usage of cloud service offers variate of products to deal with data encryptions, which works transparently inside cloud services. It becomes a responsibility of engineers to handle sensitive data outside of the cloud.\n\nYou can benefit from this library. It implements semi-auto cipher codec of textual content and custom Algebraic Data Types. Encryption/Decryption process is transparent for developers. It is embedded into `json.Marshal` and `json.Unmarshal` routines so that protection of sensitive data happens during the process of data serialization.\n\nSee the complete example [here](example/main.go).\n\n## License\n\n[![See LICENSE](https://img.shields.io/github/license/fogfish/cryptex.svg?style=for-the-badge)](LICENSE)","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffogfish%2Fcryptex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffogfish%2Fcryptex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffogfish%2Fcryptex/lists"}