-- | -- Module : Crypto.Saltine.Core.ScalarMult -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT -- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable -- -- Scalar multiplication: "Crypto.Saltine.Core.ScalarMult" -- -- The 'mult' function multiplies a group element by an integer of -- length 'Bytes.multScalar'. It returns the resulting group element -- of length 'Bytes.mult'. The 'multBase' function multiplies a -- standard group element by an integer of length -- 'Bytes.multScalar'. It returns the resulting group element of -- length 'Bytes.mult'. -- -- The correspondence between strings and group elements depends on -- the primitive implemented by 'mult'. The correspondence is not -- necessarily injective in either direction, but it is compatible -- with scalar multiplication in the group. The correspondence does -- not necessarily include all group elements, but it does include all -- strings; i.e., every string represents at least one group element. -- -- The correspondence between strings and integers also depends on the -- primitive implemented by 'mult'. Every string represents at least -- one integer. -- -- 'mult' is designed to be strong as a component of various -- well-known \"hashed Diffie–Hellman\" applications. In particular, -- it is designed to make the \"computational Diffie–Hellman\" problem -- (CDH) difficult with respect to the standard base. 'mult' is also -- designed to make CDH difficult with respect to other nontrivial -- bases. In particular, if a represented group element has small -- order, then it is annihilated by all represented scalars. This -- feature allows protocols to avoid validating membership in the -- subgroup generated by the standard base. -- -- NaCl does not make any promises regarding the \"decisional -- Diffie–Hellman\" problem (DDH), the \"static Diffie–Hellman\" -- problem (SDH), etc. Users are responsible for hashing group -- elements. -- -- 'mult' is the function @crypto_scalarmult_curve25519@ specified in -- \"Cryptography in NaCl\", Sections 2, 3, and 4 -- (). This function is conjectured -- to be strong. For background see Bernstein, \"Curve25519: new -- Diffie-Hellman speed records,\" Lecture Notes in Computer Science -- 3958 (2006), 207–228, . -- -- This is version 2010.08.30 of the scalarmult.html web page. module Crypto.Saltine.Core.ScalarMult ( Scalar, GroupElement, mult, multBase ) where import Crypto.Saltine.Class import Crypto.Saltine.Internal.Util import qualified Crypto.Saltine.Internal.ByteSizes as Bytes import Foreign.C import Foreign.Ptr import qualified Data.ByteString as S import Data.ByteString (ByteString) -- $types -- | A group element. newtype GroupElement = GE ByteString deriving (Eq) -- | A scalar integer. newtype Scalar = Sc ByteString deriving (Eq) instance IsEncoding GroupElement where decode v = case S.length v == Bytes.mult of True -> Just (GE v) False -> Nothing {-# INLINE decode #-} encode (GE v) = v {-# INLINE encode #-} instance IsEncoding Scalar where decode v = case S.length v == Bytes.multScalar of True -> Just (Sc v) False -> Nothing {-# INLINE decode #-} encode (Sc v) = v {-# INLINE encode #-} mult :: Scalar -> GroupElement -> GroupElement mult (Sc n) (GE p) = GE . snd . buildUnsafeCVector Bytes.mult $ \pq -> constVectors [n, p] $ \[(pn, _), (pp, _)] -> c_scalarmult pq pn pp multBase :: Scalar -> GroupElement multBase (Sc n) = GE . snd . buildUnsafeCVector Bytes.mult $ \pq -> constVectors [n] $ \[(pn, _)] -> c_scalarmult_base pq pn foreign import ccall "crypto_scalarmult" c_scalarmult :: Ptr CChar -- ^ Output group element buffer -> Ptr CChar -- ^ Input integer buffer -> Ptr CChar -- ^ Input group element buffer -> IO CInt -- ^ Always 0 foreign import ccall "crypto_scalarmult_base" c_scalarmult_base :: Ptr CChar -- ^ Output group element buffer -> Ptr CChar -- ^ Input integer buffer -> IO CInt -- ^ Always 0