Skip to content

Overview

secret: a Rune-style type for sensitive values in Python

secret-type provides a convenient type (secret) to indicate that a value is considered sensitive, similar to the secret type in Google's Rune Lang.

>>> from secret_type import secret
>>> password = secret("a very secret value") # (1)!

>>> print(password) # (2)!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "secret_type/containers/secret.py", line 91, in __str__
    raise SecretException()
secret_type.exceptions.SecretException: Secrets cannot be examined

>>> better_password = password + "!" # (3)!
>>> >>> type(better_password)
<class 'secret_type.sequence.SecretStr'>

>>> better_password.dangerous_apply(print) # (4)!
a very secret value!
  1. Secrets can be any primitive value
  2. Runtime exceptions prevent logging
  3. Operations derive new secrets
  4. Use dangerous_apply or dangerous_map to access the underlying value

Docs

For complete docs, see the Quickstart, or check out the API Reference.

Features

  • When marked as secret, values cannot be printed or logged; attempting to do so will raise an exception.
  • Secrets are "viral"; any operation on a secret will also return a secret.
  • Comparison operations with a secret are guaranteed to be constant-time. This helps avoid timing attacks.
  • A bool derived from a secret cannot be used for control flow.
  • Secrets cannot be used as indexes or keys for containers.
  • Internally, the underlying value is stored encrypted in memory, and is only decrypted when deriving a new value.
  • As soon as secrets are out of scope, the Garbage Collector is encouraged to immediately collect them.

Comparison to Rune

Rune makes the following guarantees about a secret:

  • All operations on secrets occur in constant time, minimizing timing side-channel leakage.
  • Secrets cannot be used in conditional branches or memory addressing.
  • Even speculative branching and indexing on secrets are caught at compile-time to avoid Specter/Meltdown.
  • Secrecy is sticky: any value in part derived from a secret is considered secret until "revealed".
  • Secrets are automatically zeroed when no longer used

This projects attempts to do something similar, but with the runtime constraints of Python.