-
Notifications
You must be signed in to change notification settings - Fork 29
/
ScalarMult.hs
117 lines (106 loc) · 4.27 KB
/
ScalarMult.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
-- |
-- 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
-- (<http://nacl.cr.yp.to/valid.html>). 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, <http://cr.yp.to/papers.html#curve25519>.
--
-- 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 = if S.length v == Bytes.mult
then Just (GE v)
else Nothing
{-# INLINE decode #-}
encode (GE v) = v
{-# INLINE encode #-}
instance IsEncoding Scalar where
decode v = if S.length v == Bytes.multScalar
then Just (Sc v)
else 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