module Crypto.Spake2.Groups.IntegerGroup
( IntegerGroup(..)
, makeIntegerGroup
, i1024
) where
import Protolude hiding (group, length)
import Crypto.Error (CryptoFailable(..), CryptoError(..))
import Crypto.Number.Basic (numBits)
import Crypto.Number.Generate (generateMax)
import Crypto.Number.ModArithmetic (expSafe)
import Crypto.Spake2.Group
( AbelianGroup(..)
, Group(..)
, KeyPair(..)
, elementSizeBytes
)
import Crypto.Spake2.Util
( expandArbitraryElementSeed
, bytesToNumber
, unsafeNumberToBytes
)
data IntegerGroup
= IntegerGroup
{ order :: !Integer
, subgroupOrder :: !Integer
, generator :: !Integer
} deriving (Eq, Show)
makeIntegerGroup :: Integer -> Integer -> Integer -> Maybe IntegerGroup
makeIntegerGroup _ _ 1 = Nothing
makeIntegerGroup order subgroupOrder generator = Just (IntegerGroup order subgroupOrder generator)
instance Group IntegerGroup where
type Element IntegerGroup = Integer
elementAdd group x y = (x * y) `mod` order group
elementNegate group x = expSafe x (subgroupOrder group 1) (order group)
groupIdentity _ = 1
encodeElement group = unsafeNumberToBytes (elementSizeBytes group)
decodeElement group bytes =
case bytesToNumber bytes of
x
| x <= 0 || x >= order group -> CryptoFailed CryptoError_PointSizeInvalid
| expSafe x (subgroupOrder group) (order group) /= groupIdentity group -> CryptoFailed CryptoError_PointCoordinatesInvalid
| otherwise -> CryptoPassed x
elementSizeBits group = numBits (order group)
arbitraryElement group seed =
let processedSeed = expandArbitraryElementSeed seed (elementSizeBytes group) :: ByteString
p = order group
q = subgroupOrder group
r = (p 1) `div` q
h = bytesToNumber processedSeed `mod` p
in expSafe h r p
instance AbelianGroup IntegerGroup where
type Scalar IntegerGroup = Integer
scalarMultiply group n x = expSafe x (n `mod` subgroupOrder group) (order group)
integerToScalar group x = x `mod` subgroupOrder group
scalarToInteger _ n = n
generateElement group = do
scalar <- generateMax (subgroupOrder group)
let element = scalarMultiply group scalar (generator group)
pure (KeyPair element scalar)
scalarSizeBits group = numBits (subgroupOrder group)
i1024 :: IntegerGroup
i1024 =
IntegerGroup
{ order = 0xE0A67598CD1B763BC98C8ABB333E5DDA0CD3AA0E5E1FB5BA8A7B4EABC10BA338FAE06DD4B90FDA70D7CF0CB0C638BE3341BEC0AF8A7330A3307DED2299A0EE606DF035177A239C34A912C202AA5F83B9C4A7CF0235B5316BFC6EFB9A248411258B30B839AF172440F32563056CB67A861158DDD90E6A894C72A5BBEF9E286C6B
, subgroupOrder = 0xE950511EAB424B9A19A2AEB4E159B7844C589C4F
, generator = 0xD29D5121B0423C2769AB21843E5A3240FF19CACC792264E3BB6BE4F78EDD1B15C4DFF7F1D905431F0AB16790E1F773B5CE01C804E509066A9919F5195F4ABC58189FD9FF987389CB5BEDF21B4DAB4F8B76A055FFE2770988FE2EC2DE11AD92219F0B351869AC24DA3D7BA87011A701CE8EE7BFE49486ED4527B7186CA4610A75
}