secrecy

package module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 18, 2025 License: MIT Imports: 5 Imported by: 1

README ΒΆ

🀫 secrecy - A simple secret-keeping library for Go.

PkgGoDev Go Report Card Go version

secrecy is a simple library which provides wrapper type for secret management in Go. It is inspired from the excellent secrecy Rust crate.

It provides a Secret[T] type for wrapping another value in a secret cell which attempts to limit exposure (only available via the special ExposeSecret() function).

Each secret has a finalizer attached that recusively zeroize secret memory when garbage collected. You must not share memory contained within a secret and share the secret itself.

This helps to ensure secrets aren't accidentally copied, logged, or otherwise exposed (as much as possible), and also ensures secrets are securely wiped from memory when garbage collected.

Getting started

Here is a simple example for storing an API key.

package main

import (
	"github.com/negrel/secrecy"
)

func main() {
	// Load secret on startup.
	secretApi := secrecy.NewSecretString(retrieveApiKey())

	// Then use it like this.
	apiCall(secretApi)
}

func apiCall(secret secrecy.SecretString) {
	apiKey := secret.ExposeSecret()
	// Use your API key but don't store it.
}

func retrieveSecret() []byte {
	// Securely retrieve your api key.
}

If you accidentally leak your secret using fmt.Println, json.Marshal or another method, the output will contains <!SECRET_LEAKED!> marker string. You can customize this value by setting the package variable secrecy.SecretLeakedMarker. This way, you can easily check for secret leaks in your logs using tool such as grep.

Disable zeroize

Sometime, you must pass your secret to a library global variable such as stripe global Key variable.

To do so, you must disable memory zeroize as it will corrupt the exposed string when the secret will be garbage collected.

package main

import (
	"github.com/negrel/secrecy"
	"github.com/stripe/stripe-go/v80"
)

func main() {
	// Load secret on startup.
	stripeSecret := secrecy.NewSecretString(retrieveApiKey())
	stripeSecret.DisableZeroize()

	stripe.Key = stripeSecret.ExposeSecret()
}

func retrieveStripeSecret() []byte {
	// Securely retrieve your api key.
}

Contributing

If you want to contribute to secrecy to add a feature or improve the code contact me at alexandre@negrel.dev, open an issue or make a pull request.

🌠 Show your support

Please give a ⭐ if this project helped you!

buy me a coffee

πŸ“œ License

MIT Β© Alexandre Negrel

Documentation ΒΆ

Overview ΒΆ

secrecy is a simple, safe library which provides wrapper type for secret management in Go.

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

View Source
var SecretLeakedMarker = "<!SECRET_LEAKED!>"

SecretLeakedMarker is a marker string returned by Secret[T] when accidentally leaking the secret. This value is returned when you try to fmt.Println(secret) or serialize it to JSON/XML. This enable you to easily monitor your logs for secret leak.

Functions ΒΆ

func UnsafeBytesToString ΒΆ added in v0.2.0

func UnsafeBytesToString(bytes []byte) string

UnsafeStringToBytes converts given string into a bytes slice using unsafe. This function doesn't perform any copy so mutating the byte slice will mutate the returned string.

func UnsafeStringToBytes ΒΆ added in v0.2.0

func UnsafeStringToBytes(str string) []byte

UnsafeStringToBytes converts given string into a bytes slice using unsafe. This function doesn't perform any copy so mutating the byte slice will mutate the string.

func Zeroize ΒΆ

func Zeroize(v any)

Zeroize recursively changes to zeros memory pointed by the given value. Panics if data is or contains a struct with non ignored unexported fields and doesn't implements Zeroizer.

This function zeroize all mutable memory, be sure to not share that memory as it may lead to unexpected behavior. All pointers (map, slice, pointers) type are emptied before being replaced by nil.

Go strings are immutable and can't be zeroized (without using unsafe), if you want your secret to be fully zeroized, store them as []byte.

Types ΒΆ

type Secret ΒΆ

type Secret[T any] struct {
	// contains filtered or unexported fields
}

Secret is a wrapper type for values that contains secrets, which attempts to limit accidental exposure and ensure secrets are wiped from memory when garbage collected. (e.g. passwords, cryptographic keys, access tokens or other credentials)

Prefer SecretString over Secret[string] as go string are immutable and can't be wiped from memory.

func NewSecret ΒΆ

func NewSecret[T any](value T) *Secret[T]

NewSecret wraps given secret and returns *Secret[T]. Wrapped value and inner values will be entirely wiped from memory when garbage collected, this includes maps, slices pointers, etc. Returned secret owns wrapped value and inner value, you must not share underlying data.

func (*Secret[T]) DisableZeroize ΒΆ

func (s *Secret[T]) DisableZeroize()

Disable zeroize on garbage collection for this secret.

func (*Secret[T]) EnableZeroize ΒΆ

func (s *Secret[T]) EnableZeroize()

Enable zeroize on garbage collection for this secret. By default zeroize is enabled, you don't need to call this function if didn't call DisableZeroize before.

func (*Secret[T]) ExposeSecret ΒΆ

func (s *Secret[T]) ExposeSecret() T

ExposeSecret returns a copy of inner secret. Don't store returned value and prefer passing Secret itself if needed.

func (Secret[T]) GoString ΒΆ added in v0.5.0

func (s Secret[T]) GoString() string

Format implements fmt.GoStringer. This function return the SecretLeakedMarker marker string and appends "Secret[T](******)" as a suffix.

func (Secret[T]) MarshalText ΒΆ added in v0.5.0

func (s Secret[T]) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler This function returns the SecretLeakedMarker marker byte slice so it can be easily searched.

func (Secret[T]) String ΒΆ

func (s Secret[T]) String() string

String implements fmt.Stringer. This function returns the SecretLeakedMarker marker string so it can be easily searched.

func (*Secret[T]) UnmarshalJSON ΒΆ added in v0.7.0

func (s *Secret[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

func (Secret[T]) Zeroize ΒΆ

func (s Secret[T]) Zeroize()

Zeroize implements Zeroizer.

type SecretExposer ΒΆ

type SecretExposer[T any] interface {
	ExposeSecret() T
}

SecretExposer define any secret wrapper types that can expose it's underlying secret of type T. Don't store returned value and prefer passing SecretExposer itself if needed.

type SecretString ΒΆ

type SecretString struct {
	*Secret[[]byte]
}

SecretString is a wrapper around Secret[[]byte] that expose its secret as string.

func NewSecretString ΒΆ

func NewSecretString(secret []byte) SecretString

NewSecretString wraps given secret and returns SecretString. This function takes a byte slice as parameter so the secret can be wiped on garbage collection. Use UnsafeStringToBytes to convert your string to a byte slice if needed.

func (SecretString) ExposeSecret ΒΆ

func (ss SecretString) ExposeSecret() string

ExposeSecret exposes underlying secret as a string using unsafe. Don't store returned value and prefer passing SecretString itself if needed.

type SerializableSecret ΒΆ

type SerializableSecret[S any, T SecretExposer[S]] struct {
	// contains filtered or unexported fields
}

SerializableSecret is a serializable wrapper around a SecretExposer.

func NewSerializableSecret ΒΆ

func NewSerializableSecret[S any, T SecretExposer[S]](secret T) SerializableSecret[S, T]

NewSerializableSecret wraps secret and return a SerializableSecret that implements json.Marshaler interface.

func (SerializableSecret[S, T]) ExposeSecret ΒΆ

func (ss SerializableSecret[S, T]) ExposeSecret() S

ExposeSecret implements SecretExposer.

func (SerializableSecret[S, T]) MarshalJSON ΒΆ

func (ss SerializableSecret[S, T]) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*SerializableSecret[S, T]) UnmarshalJSON ΒΆ added in v0.7.0

func (ss *SerializableSecret[S, T]) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type Zeroizer ΒΆ

type Zeroizer interface {
	Zeroize()
}

Interface for securely erasing values from memory. You may want to implement it if you're struct contains unexported fields that can't be ignored using `Zeroizer:"ignore"` struct tag. This interface MUST be implemented using a struct receiver and not a pointer receiver.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL