summaryrefslogtreecommitdiff
path: root/Crypto/XEd25519/FieldElement.hs
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