Secret

com.geirolz.secret.Secret
See theSecret companion object
sealed abstract class Secret[T]

Memory-safe and type-safe secret value of type T.

Secret does the best to avoid leaking information in memory and in the code BUT an attack is possible and I don't give any certainties or guarantees about security using this class, you use it at your own risk. Code is open source, you can check the implementation and take your decision consciously. I'll do my best to improve the security and documentation of this class.

Obfuscation

The value is obfuscated when creating the Secret instance using the given SecretStrategy which, by default, transform the value into a xor-ed ByteBuffer witch store bytes outside the JVM using direct memory access.

The obfuscated value is de-obfuscated using the given SecretStrategy instance every time the method use is invoked which returns the original value converting bytes back to T re-apply the xor.

API and Type safety

While obfuscating the value prevents or at least makes it harder to read the value from memory, Secret class API are designed to avoid leaking information in other ways. Preventing developers to improperly use the secret value ( logging, etc...).

Example

 val secretString: Secret[String]  = Secret("my_password")
 val database: F[Database]         = secretString.use(password => initDb(password))

Attributes

Companion
object
Graph
Supertypes
trait AutoCloseable
class Object
trait Matchable
class Any

Members list

Value members

Abstract methods

def duplicate: Secret[T]

Duplicate the secret without destroying it.

Duplicate the secret without destroying it.

If this was destroyed the duplicated will also be destroyed.

Attributes

Concrete methods

final def asOneShot: OneShotSecret[T]

OneShotSecret version of this secret

OneShotSecret version of this secret

Attributes

inline def euse[U](f: T => U): Either[SecretDestroyed, U]

Alias for use with Either[Throwable, *]

Alias for use with Either[Throwable, *]

Attributes

final def evalUse[F[_] : MonadSecretError, U](f: T => F[U]): F[U]

Apply f with the de-obfuscated value WITHOUT destroying it.

Apply f with the de-obfuscated value WITHOUT destroying it.

If the secret is destroyed it will raise a NoLongerValidSecret exception.

Once the secret is destroyed it can't be used anymore. If you try to use it using use, useAndDestroy, evalUse, evalUseAndDestroy and other methods, it will raise a NoLongerValidSecret exception.

Attributes

final def flatMap[U : SecretStrategy](f: T => Secret[U])(implicit evidence$1: SecretStrategy[U], Hasher): Secret[U]

flat map the value using the specified function.

flat map the value using the specified function.

If the secret were destroyed it will raise a SecretDestroyed when you try to use the new secret.

This current secret will NOT be destroyed when the new secret is destroyed.

Example:

val secretString: Secret[String]
val secretInt: Secret[Int] = secretString.flatMap(s => Secret(s.toInt))
secretInt.destroy()
secretString.isDestroyed // false

Attributes

inline def isValueEquals(that: Secret[T])(using Eq[T]): Boolean

Safely compare this secret with the provided Secret.

Safely compare this secret with the provided Secret.

Attributes

Returns

true if the secrets are equal, false if they are not equal or if one of the secret is destroyed

final def map[U : SecretStrategy](f: T => U)(implicit evidence$1: SecretStrategy[U], Hasher): Secret[U]

map the value using the specified function.

map the value using the specified function.

If the secret were destroyed it will raise a SecretDestroyed when you try to use the new secret.

  • This current secret will NOT be destroyed when the new secret is destroyed.

Example:

val secretString: Secret[String]
val secretInt: Secret[Int] = secretString.map(_.toInt)
secretInt.destroy()
secretString.isDestroyed // false

Attributes

inline def use[F[_] : MonadSecretError, U](f: T => U): F[U]

Apply f with the de-obfuscated value WITHOUT destroying it.

Apply f with the de-obfuscated value WITHOUT destroying it.

If the secret is destroyed it will raise a SecretDestroyed exception.

Once the secret is destroyed it can't be used anymore. If you try to use it using use, useAndDestroy, evalUse, evalUseAndDestroy and other methods, it will raise a SecretDestroyed exception.

Attributes

Inherited methods

final inline override def close(): Unit

Alias for destroy

Alias for destroy

Attributes

Definition Classes
SecretApi -> AutoCloseable
Inherited from:
SecretApi (hidden)
final def destroy()(using Location): Unit

Destroy the secret value by filling the obfuscated value with '\0'.

Destroy the secret value by filling the obfuscated value with '\0'.

This method is idempotent.

Once the secret is destroyed it can't be used anymore. If you try to use it using use, useAndDestroy, evalUse, evalUseAndDestroy and other methods, it will raise a NoLongerValidSecret exception.

Attributes

Inherited from:
SecretApi (hidden)
final def destructionLocation: Option[Location]

Attributes

Returns

the location where the secret was destroyed if the collection is enabled.

Inherited from:
SecretApi (hidden)
final inline override def equals(obj: Any): Boolean

Always returns false to prevents leaking information.

Always returns false to prevents leaking information.

Use isHashedEquals or isValueEquals

Attributes

Definition Classes
SecretApi -> Any
Inherited from:
SecretApi (hidden)
final inline def euseAndDestroy[U](f: T => U)(using Location): Either[SecretDestroyed, U]

Alias for useAndDestroy with Either[Throwable, *]

Alias for useAndDestroy with Either[Throwable, *]

Attributes

Inherited from:
SecretApi (hidden)
final inline def evalUseAndDestroy[F[_] : MonadSecretError, U](f: T => F[U])(implicit evidence$1: MonadSecretError[F], Location): F[U]

Apply f with the de-obfuscated value and then destroy the secret value by invoking destroy method.

Apply f with the de-obfuscated value and then destroy the secret value by invoking destroy method.

Once the secret is destroyed it can't be used anymore. If you try to use it using use, useAndDestroy, evalUse, evalUseAndDestroy and other methods, it will raise a SecretDestroyed exception.

Attributes

Inherited from:
SecretApi (hidden)
final def flatMapAndDestroy[U : SecretStrategy](f: T => Secret[U])(implicit evidence$1: SecretStrategy[U], Location, Hasher): Secret[U]

flat map the value using the specified function and then destroy this.

flat map the value using the specified function and then destroy this.

If the secret were destroyed it will raise a SecretDestroyed when you try to use the new secret.

Attributes

Inherited from:
SecretApi (hidden)
final def hashed: String

Attributes

Returns

a hashed representation of the secret value

Inherited from:
SecretApi (hidden)
final def isDestroyed: Boolean

Check if the secret is destroyed

Check if the secret is destroyed

Attributes

Returns

true if the secret is destroyed, false otherwise

Inherited from:
SecretApi (hidden)
inline def isHashedEquals(that: Secret[T]): Boolean

Safely compare the hashed value of this secret with the provided Secret.

Safely compare the hashed value of this secret with the provided Secret.

Attributes

Inherited from:
SecretApi (hidden)
final def mapAndDestroy[U : SecretStrategy](f: T => U)(implicit evidence$1: SecretStrategy[U], Location, Hasher): Secret[U]

map the value using the specified function and then destroy this.

map the value using the specified function and then destroy this.

If the secret were destroyed it will raise a SecretDestroyed when you try to use the new secret.

Attributes

Inherited from:
SecretApi (hidden)
final inline def useAndDestroy[F[_] : MonadSecretError, U](f: T => U)(implicit evidence$1: MonadSecretError[F], Location): F[U]

Apply f with the de-obfuscated value and then destroy the secret value by invoking destroy method.

Apply f with the de-obfuscated value and then destroy the secret value by invoking destroy method.

Once the secret is destroyed it can't be used anymore. If you try to use it using use, useAndDestroy, evalUse, evalUseAndDestroy and other methods, it will raise a SecretDestroyed exception.

Attributes

Inherited from:
SecretApi (hidden)

Inherited fields

final override val toString: String

Attributes

Returns

always returns a static place holder string "** SECRET **" to avoid leaking information

Inherited from:
SecretApi (hidden)