Giter Club home page Giter Club logo

secret's Introduction

Secret

Build Status Codacy Badge Codacy Badge Sonatype Nexus (Releases) Scala Steward badge Mergify Status GitHub license

A Scala 3, functional, type-safe and memory-safe library to handle secret values

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

Please, drop a ⭐️ if you are interested in this project and you want to support it.

Note

Scala 3 only, Scala 2 is not supported.

libraryDependencies += "com.github.geirolz" %% "secret" % "0.0.11"

Usage

import com.geirolz.secret.*
 import scala.util.Try

 val reusableSecret: Secret[String]  = Secret("password") // reusable secret
// reusableSecret: Secret[String] = ** SECRET **
 val oneShotSecret: Secret.OneShot[String] = Secret.oneShot("password") // one shot secret
// oneShotSecret: OneShotSecret[String] = ** SECRET **
 val deferredSecret: Secret.Deferred[Try, String] = Secret.deferred(Try("password")) // deferred secret
// deferredSecret: DeferredSecret[[T >: Nothing <: Any] => Try[T], String] = com.geirolz.secret.DeferredSecret$$anon$1@2ed6f149

Obfuscation

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

The obfuscated value is de-obfuscated using the implicit SecretStrategy instance every time use, and derived method, are invoked which returns the original value converting the bytes back to T re-applying the xor formula.

API and Type safety

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

Example

import com.geirolz.secret.*
import scala.util.Try

case class Database(password: String)

val secretString: Secret[String]  = Secret("password")
// secretString: Secret[String] = ** SECRET **
val database: Either[SecretDestroyed, Database] = secretString.euseAndDestroy(password => Database(password))
// database: Either[SecretDestroyed, Database] = Right(
//   value = Database(password = "password")
// )

// if you try to access the secret value once used, you'll get an error
secretString.euse(println(_))
// res2: Either[SecretDestroyed, Unit] = Left(
//   value = SecretDestroyed(destructionLocation = README.md:50:113)
// )

Integrations

These integrations aim to enhance the functionality and capabilities of Secret type making it easier to use in different contexts.

Cats Effect

libraryDependencies += "com.github.geirolz" %% "secret-effect" % "0.0.11"
import com.geirolz.secret.*
import cats.effect.{IO, Resource}

val s: Secret[String] = Secret("password")

// !!!! this will not destroy the secret because it uses a duplicated one !!!
val res: Resource[IO, String] = s.resource[IO]

// this will destroy the secret because it uses the original one
val res2: Resource[IO, String] = s.resourceDestroy[IO]

// this will destroy the secret because it uses the original one
val res3: Resource[IO, String] = Secret.resource[IO, String]("password")

Pureconfig

libraryDependencies += "com.github.geirolz" %% "secret-pureconfig" % "0.0.11"

Just provides the ConfigReader instance for Secret[T] type. There must be an ConfigReader[T] and a SecretStrategy[T] instances implicitly in the scope.

import com.geirolz.secret.pureconfig.given

Typesafe Config

libraryDependencies += "com.github.geirolz" %% "secret-typesafe-config" % "0.0.11"
import com.geirolz.secret.typesafe.config.given

Ciris

libraryDependencies += "com.github.geirolz" %% "secret-ciris" % "0.0.11"
import com.geirolz.secret.ciris.given

Circe

Provides the json Decoder instance for Secret[T] and OneShotSecret[T] type.

libraryDependencies += "com.github.geirolz" %% "secret-circe" % "0.0.11"
import com.geirolz.secret.circe.given

Cats-xml

Provides the xml Decoder instance for Secret[T] and OneShotSecret[T] type.

libraryDependencies += "com.github.geirolz" %% "secret-cats-xml" % "0.0.11"
import com.geirolz.secret.catsxml.given

Adopters

If you are using Secret in your company, please let me know and I'll add it to the list! It means a lot to me.

Custom Obfuscation Strategy for a specific type

If you want to use a custom obfuscation strategy for a specific type you can implement a custom SecretStrategy and provide an implicit instance of it during the secret creation. If you think that your strategy can be useful for other people, please consider to contribute to the project and add it to the library.

import com.geirolz.secret.strategy.SecretStrategy
import com.geirolz.secret.strategy.SecretStrategy.{DeObfuscator, Obfuscator}
import com.geirolz.secret.util.KeyValueBuffer
import com.geirolz.secret.Secret

given SecretStrategy[String] = SecretStrategy[String](
  Obfuscator.of[String](_ => KeyValueBuffer.directEmpty(0)),
  DeObfuscator.of[String](_ => "CUSTOM"),
)

Secret("my_password").euse(secret => secret)
// res10: Either[SecretDestroyed, String] = Right(value = "CUSTOM")

Custom Obfuscation Strategy algebra

If you want to use a custom obfuscation strategy algebra you can implement a custom SecretStrategyAlgebra and provide an implicit SecretStrategyFactory instance built on it during the secret creation. If you think that your strategy can be useful for other people, please consider to contribute to the project and add it to the library.

import com.geirolz.secret.strategy.SecretStrategy.{DeObfuscator, Obfuscator}
import com.geirolz.secret.strategy.{SecretStrategy, SecretStrategyAlgebra}
import com.geirolz.secret.util.KeyValueBuffer
import com.geirolz.secret.{PlainValueBuffer, Secret}

import java.nio.ByteBuffer

// build the custom algebra
val myCustomAlgebra = new SecretStrategyAlgebra:
    final def obfuscator[P](f: P => PlainValueBuffer): Obfuscator[P] =
      Obfuscator.of { (plain: P) => KeyValueBuffer(ByteBuffer.allocateDirect(0), f(plain)) }
    
    final def deObfuscator[P](f: PlainValueBuffer => P): DeObfuscator[P] =
      DeObfuscator.of { bufferTuple => f(bufferTuple.roObfuscatedBuffer) }
// myCustomAlgebra: SecretStrategyAlgebra = repl.MdocSession$MdocApp11$$anon$12@6512f34b

// build factory based on the algebra
val myCustomStrategyFactory = myCustomAlgebra.newFactory
// myCustomStrategyFactory: SecretStrategyFactory = com.geirolz.secret.strategy.SecretStrategyFactory@5be15840

// ----------------------------- USAGE -----------------------------
// implicitly in the scope

import myCustomStrategyFactory.given

Secret("my_password").euse(secret => secret)
// res12: Either[SecretDestroyed, String] = Right(value = "my_password")

// or restricted to a specific scope
myCustomStrategyFactory {
  Secret("my_password").euse(secret => secret)
}
// res13: Either[SecretDestroyed, String] = Right(value = "my_password")

Contributing

We welcome contributions from the open-source community to make Secret even better. If you have any bug reports, feature requests, or suggestions, please submit them via GitHub issues. Pull requests are also welcome.

Before contributing, please read our Contribution Guidelines to understand the development process and coding conventions.

Please remember te following:

  • Run sbt scalafmtAll before submitting a PR.
  • Run sbt gen-doc to update the documentation.

License

Secret is released under the Apache License 2.0. Feel free to use it in your open-source or commercial projects.

Acknowledgements

secret's People

Contributors

geirolz avatar scala-steward-geirolz[bot] avatar

Stargazers

Miguel Marcelino avatar Taketoday avatar Tammo avatar Uwe Sommerlatt avatar spamegg avatar DzejDzej avatar  avatar Romain Reuillon avatar Erik Torres Serrano avatar Isaka Traore avatar Matt Gilbert avatar Tae-kyeom, Kim avatar Choucri FAHED avatar Martin Mauch avatar Francesco Nolano avatar Alberto Coletta avatar Siyavash Habashi avatar Velichko Anton avatar  avatar Jakub Pravda avatar Alexandru Stana avatar Niklas Klein avatar Timofey Tsymlov avatar shrynx avatar Loránd Szakács avatar Andrea Tomasello avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

codacy-badger

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.