summaryrefslogtreecommitdiff
path: root/Crypto/XEd25519/FieldElement.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/XEd25519/FieldElement.hs')
-rw-r--r--Crypto/XEd25519/FieldElement.hs49
1 files changed, 49 insertions, 0 deletions
diff --git a/Crypto/XEd25519/FieldElement.hs b/Crypto/XEd25519/FieldElement.hs
new file mode 100644
index 0000000..7a91610
--- /dev/null
+++ b/Crypto/XEd25519/FieldElement.hs
@@ -0,0 +1,49 @@
1{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE TypeOperators #-}
3module Crypto.XEd25519.FieldElement where
4
5import Crypto.Error
6import qualified Crypto.PubKey.Curve25519 as X25519
7import qualified Crypto.PubKey.Ed25519 as Ed25519
8import Data.ByteArray as BA (pack,unpack,Bytes)
9import Data.Modular
10import Data.Word
11
12-- 2^255 - 19
13type P25519 = 57896044618658097711785492504343953926634992332820282019728792003956564819949
14
15newtype FieldElement = FE (ℤ / P25519)
16
17
18fe_frombytes :: X25519.PublicKey -> FieldElement
19fe_frombytes pub = FE $ toMod $ decodeLittleEndian $ BA.unpack pub
20
21fe_tobytes :: FieldElement -> Ed25519.PublicKey
22fe_tobytes (FE x) = throwCryptoError $ Ed25519.publicKey (b :: Bytes)
23 where
24 b = BA.pack $ take 32 $ (encodeLittleEndian $ unMod x) ++ repeat 0
25
26fe_1 :: FieldElement
27fe_1 = FE $ toMod 1
28
29fe_sub :: FieldElement -> FieldElement -> FieldElement
30fe_sub (FE x) (FE y) = FE $ x - y
31
32fe_add :: FieldElement -> FieldElement -> FieldElement
33fe_add (FE x) (FE y) = FE $ x + y
34
35fe_invert :: FieldElement -> FieldElement
36fe_invert (FE x) = FE $ inv x
37
38fe_mul :: FieldElement -> FieldElement -> FieldElement
39fe_mul (FE x) (FE y) = FE (x * y)
40
41decodeLittleEndian :: [Word8] -> Integer
42decodeLittleEndian [] = 0
43decodeLittleEndian (x:xs) = fromIntegral x + 256 * decodeLittleEndian xs
44
45encodeLittleEndian :: Integer -> [Word8]
46encodeLittleEndian 0 = []
47encodeLittleEndian x = let (bs,b) = divMod x 256
48 in fromIntegral b : encodeLittleEndian bs
49