Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use std base64 with env so that it is compatible with cli #5

Merged
merged 1 commit into from
Jul 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 32 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,13 @@ Golang has excellent [built-in abstraction](https://blog.golang.org/json-and-go)
MyADT{Secret: "plaintext"} ⟷ {"secret":"cGxhaW50ZXh0"}
```

Semi-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. The 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.
Semi-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.

### Strings encryption
### AWS KMS SDK

Use `cryptex.String` to deal with sensitive textual content. Its implementation assumes that binary crypto text is encoded with base64, which makes is usable with any text-based protocols. Crypto 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
Crypto 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.

```golang
// from example
func Decrypt(cryptotext string) plaintext []byte {
bytes, err := base64.StdEncoding.DecodeString(cryptotext)
input := &kms.DecryptInput{ CiphertextBlob: []byte(bytes) }
Expand All @@ -89,6 +88,10 @@ func Encrypt(plaintext []byte) cryptotext string {
}
```

### Strings encryption

Use `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.

The usage of `cryptex.String` data type in your application is straight forward:

```go
Expand All @@ -99,7 +102,7 @@ import (

// You have to define either KMS key id or its alias if your application needs to
// encrypt data. You can skip this state if you application only decrypts data.
cipher.Default.UseKey("alias/mykms/key")
cipher.Default.UseKey("alias/mykms-key")

// Do not use built-in `string` type for sensitive data in data structure, which
// leaves boundaries of your application (e.g. sent to client, stored to disk, etc).
Expand Down Expand Up @@ -170,6 +173,30 @@ bytes, err := json.Marshal(&user)
err := json.Unmarshal(bytes, &user)
```

### Environment Variables

Usage 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
data. Use AWS command-line and this library to protect your config:

```bash
aws kms encrypt \
--key-id alias/mykms-key \
--plaintext "PlainText" \
--query CiphertextBlob \
--output text

export MY_CONFIG=...
```

Cryptex library implements Golang standard semantic (`os` package) to deal with environment
variables. It transparently encrypt/decrypt them with KMS key.

```go
cryptex.Getenv("MY_CONFIG")
cryptex.LookupEnv("MY_CONFIG")
```


## Afterwords

Software 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.
Expand Down
16 changes: 14 additions & 2 deletions cipher/kms.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
package cipher

import (
"encoding/base64"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/kms"
Expand Down Expand Up @@ -40,7 +42,12 @@ func (c *KMS) UseKey(key string) {

// Decrypt uses AWS KMS API to decrypt cryptotext.
func (c *KMS) Decrypt(cryptotext string) (plaintext []byte, err error) {
bytes, err := b64.DecodeString(cryptotext)
return c.Decrypt64(b64, cryptotext)
}

// Decrypt64 uses AWS KMS API to decrypt cryptotext.
func (c *KMS) Decrypt64(codec *base64.Encoding, cryptotext string) (plaintext []byte, err error) {
bytes, err := codec.DecodeString(cryptotext)
if err != nil {
return
}
Expand All @@ -59,6 +66,11 @@ func (c *KMS) Decrypt(cryptotext string) (plaintext []byte, err error) {

// Encrypt uses AWS KMS API to encrypt plaintext.
func (c *KMS) Encrypt(plaintext []byte) (cryptotext string, err error) {
return c.Encrypt64(b64, plaintext)
}

// Encrypt64 uses AWS KMS API to encrypt plaintext.
func (c *KMS) Encrypt64(codec *base64.Encoding, plaintext []byte) (cryptotext string, err error) {
input := &kms.EncryptInput{
KeyId: aws.String(c.key),
Plaintext: plaintext,
Expand All @@ -69,5 +81,5 @@ func (c *KMS) Encrypt(plaintext []byte) (cryptotext string, err error) {
return
}

return b64.EncodeToString(result.CiphertextBlob), nil
return codec.EncodeToString(result.CiphertextBlob), nil
}
5 changes: 3 additions & 2 deletions env.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package cryptex

import (
"encoding/base64"
"os"

"github.com/fogfish/cryptex/cipher"
Expand All @@ -19,7 +20,7 @@ import (
Setenv sets the value of environment variable
*/
func Setenv(key, value string) error {
text, err := cipher.Default.Encrypt([]byte(value))
text, err := cipher.Default.Encrypt64(base64.StdEncoding, []byte(value))
if err != nil {
return err
}
Expand Down Expand Up @@ -54,7 +55,7 @@ func LookupEnv(key string) (string, bool) {
return "", false
}

text, err := cipher.Default.Decrypt(cryptotext)
text, err := cipher.Default.Decrypt64(base64.StdEncoding, cryptotext)
if err != nil {
return "", false
}
Expand Down