blob: 7a916107f1cde8e3b99e42bff9d17cec1015768c (
plain)
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
|
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
module Crypto.XEd25519.FieldElement where
import Crypto.Error
import qualified Crypto.PubKey.Curve25519 as X25519
import qualified Crypto.PubKey.Ed25519 as Ed25519
import Data.ByteArray as BA (pack,unpack,Bytes)
import Data.Modular
import Data.Word
-- 2^255 - 19
type P25519 = 57896044618658097711785492504343953926634992332820282019728792003956564819949
newtype FieldElement = FE (ℤ / P25519)
fe_frombytes :: X25519.PublicKey -> FieldElement
fe_frombytes pub = FE $ toMod $ decodeLittleEndian $ BA.unpack pub
fe_tobytes :: FieldElement -> Ed25519.PublicKey
fe_tobytes (FE x) = throwCryptoError $ Ed25519.publicKey (b :: Bytes)
where
b = BA.pack $ take 32 $ (encodeLittleEndian $ unMod x) ++ repeat 0
fe_1 :: FieldElement
fe_1 = FE $ toMod 1
fe_sub :: FieldElement -> FieldElement -> FieldElement
fe_sub (FE x) (FE y) = FE $ x - y
fe_add :: FieldElement -> FieldElement -> FieldElement
fe_add (FE x) (FE y) = FE $ x + y
fe_invert :: FieldElement -> FieldElement
fe_invert (FE x) = FE $ inv x
fe_mul :: FieldElement -> FieldElement -> FieldElement
fe_mul (FE x) (FE y) = FE (x * y)
decodeLittleEndian :: [Word8] -> Integer
decodeLittleEndian [] = 0
decodeLittleEndian (x:xs) = fromIntegral x + 256 * decodeLittleEndian xs
encodeLittleEndian :: Integer -> [Word8]
encodeLittleEndian 0 = []
encodeLittleEndian x = let (bs,b) = divMod x 256
in fromIntegral b : encodeLittleEndian bs
|