packages feed

cachix-0.2.1: src/Cachix/Client/Secrets.hs

-- A facade for working with secrets and their representations, without delving
-- into cryptography libraries.
module Cachix.Client.Secrets (

  -- * NAR signing
  SigningKey(..)
  , parseSigningKeyLenient
  , exportSigningKey

  -- TODO: * Auth token

) where

import           Crypto.Sign.Ed25519
import qualified Data.ByteString.Base64        as B64
import qualified Data.ByteString.Char8         as BC
import           Data.Char                      ( isSpace )
import           Protolude

-- | A secret key for signing nars.
newtype SigningKey = SigningKey { signingSecretKey :: SecretKey }

parseSigningKeyLenientBS
  :: ByteString -- ^ ASCII (Base64)
  -> Either Text SigningKey -- ^ Error message or signing key
parseSigningKeyLenientBS raw =
  let bcDropWhileEnd f = BC.reverse . BC.dropWhile f . BC.reverse
      bcDropAround f = bcDropWhileEnd f . BC.dropWhile f
      stripped = bcDropAround isSpace raw
      nonNull = if BC.null stripped then Left "A signing key must not be empty" else pure stripped
  in SigningKey . SecretKey . B64.decodeLenient <$> nonNull

parseSigningKeyLenient
  :: Text -- ^ Base64
  -> Either Text SigningKey -- ^ Error message or signing key
parseSigningKeyLenient = parseSigningKeyLenientBS . toSL

exportSigningKeyBS
  :: SigningKey
  -> ByteString -- ^ ASCII (Base64)
exportSigningKeyBS (SigningKey (SecretKey bs)) = B64.encode bs

exportSigningKey :: SigningKey -> Text
exportSigningKey = toS . exportSigningKeyBS