We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Encrypted Logs

In rare cases, you may find that you absolutely, positively, must log some sensitive information.

In those cases, it's best to encrypt the data, ideally with PKI (public key infrastructure).

I've done this before using the package filippo.io/age. It does require some up-front work, and makes reading logs complicated, but it does provide good security.

First, you'd need to set up a public/private key pair for anyone on your team who may need to read secret logs. Public keys can be committed to your repository and shipped with your application.

var developerPublicKeys = age.Recipient{
	/* ... developer keys here ... */
}

// encryptSecretLog encrypts secret for safe logging.
func encryptSecretLog(secret string) string {
	dst := bytes.Buffer{}
	w, err := age.Encrypt(dst, developerPublicKeys...)
	if err != nil {
		panic(err)
	}
	if _, err := w.Write([]byte(secret)); err != nil {
		panic(err)
	}
	if err := w.Close(); err != nil {
		panic(err)
	}
	return dst.String()
}

Then you can safely log a secret in encrypted form:

req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "https://bank.example.com/account/details", nil)
resp, _ := client.Do(req)
body, _ := io.ReadAll(resp.Body)
logger.Debug("read API response from bank",
	"url", req.URL.String(),
	"body", encryptSecretLog(string(body)), // <--- now it's encrypted!
)

The resulting log will look something like this:

2024-01-15T10:30:45.123Z INFO msg="read API response from bank" url="https://bank.example.com/account/details" body="WW91IGZvdW5kIHRoZSBzZWNyZXQhISEK...

You'll need to build a decryption tool that accepts an encrypted log value and a private key to display the original text.

We won't be encrypting logs with Linko, but its useful to be aware of the tactic.