packages feed

saltine-0.2.2.0: src/Crypto/Saltine/Core/OneTimeAuth.hs

-- |
-- Module      : Crypto.Saltine.Core.OneTimeAuth
-- Copyright   : (c) Joseph Abrahamson 2013
-- License     : MIT
--
-- Maintainer  : me@jspha.com
-- Stability   : experimental
-- Portability : non-portable
--
-- Secret-key single-message authentication:
-- "Crypto.Saltine.Core.OneTimeAuth"
--
-- The 'auth' function authenticates a message 'ByteString' using a
-- secret key The function returns an authenticator. The 'verify'
-- function checks if it's passed a correct authenticator of a message
-- under the given secret key.
--
-- The 'auth' function, viewed as a function of the message for a
-- uniform random key, is designed to meet the standard notion of
-- unforgeability after a single message. After the sender
-- authenticates one message, an attacker cannot find authenticators
-- for any other messages.
--
-- The sender must not use 'auth' to authenticate more than one
-- message under the same key. Authenticators for two messages under
-- the same key should be expected to reveal enough information to
-- allow forgeries of authenticators on other messages.
--
-- "Crypto.Saltine.Core.OneTimeAuth" is
-- @crypto_onetimeauth_poly1305@, an authenticator specified in
-- "Cryptography in NaCl" (<http://nacl.cr.yp.to/valid.html>), Section
-- 9. This authenticator is proven to meet the standard notion of
-- unforgeability after a single message.
--
-- This is version 2010.08.30 of the onetimeauth.html web page.
module Crypto.Saltine.Core.OneTimeAuth (
  Key, Authenticator,
  newKey,
  auth, verify
  ) where

import Crypto.Saltine.Internal.OneTimeAuth
            ( c_onetimeauth
            , c_onetimeauth_verify
            , Key(..)
            , Authenticator(..)
            )
import Crypto.Saltine.Internal.Util as U
import Data.ByteString              (ByteString)

import qualified Crypto.Saltine.Internal.OneTimeAuth as Bytes
import qualified Data.ByteString                   as S

-- | Creates a random key of the correct size for 'auth' and 'verify'.
newKey :: IO Key
newKey = Key <$> randomByteString Bytes.onetimeauth_keybytes

-- | Builds a keyed 'Authenticator' for a message. This
-- 'Authenticator' is /impossible/ to forge so long as the 'Key' is
-- never used twice.
auth :: Key
     -> ByteString
     -- ^ Message
     -> Authenticator
auth (Key key) msg =
  Au . snd . buildUnsafeByteString Bytes.onetimeauth_bytes $ \pa ->
    constByteStrings [key, msg] $ \[(pk, _), (pm, _)] ->
      c_onetimeauth pa pm (fromIntegral $ S.length msg) pk

-- | Verifies that an 'Authenticator' matches a given message and key.
verify :: Key
       -> Authenticator
       -> ByteString
       -- ^ Message
       -> Bool
       -- ^ Is this message authentic?
verify (Key key) (Au a) msg =
  unsafeDidSucceed $ constByteStrings [key, msg, a] $ \
    [(pk, _), (pm, _), (pa, _)] ->
      return $ c_onetimeauth_verify pa pm (fromIntegral $ S.length msg) pk