Skip to content

Commit

Permalink
Merge pull request #15 from adjoint-io/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
sdiehl authored Jul 12, 2019
2 parents 9c9eaf2 + 42f97df commit c2e69d8
Show file tree
Hide file tree
Showing 13 changed files with 289 additions and 221 deletions.
15 changes: 10 additions & 5 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# Change log for galois-field

## 0.2.1
* Add preliminary implementation of BinaryField.
* Add `frob` function for GaloisField.
* Add minor improvements to documentation.

## 0.2.0

* Add `deg` for GaloisField
* Add `order` for GaloisField
* Add `pow` for GaloisField
* Add `rnd` for GaloisField
* Add `deg` function for GaloisField.
* Add `order` function for GaloisField.
* Add `pow` function for GaloisField.
* Add `rnd` function for GaloisField.

## 0.1.1

* Add `Arbitrary` instances to PrimeField, PolynomialRing, and ExtensionField.
* Add `Bits` instances to PrimeField.
* Add `Pretty` instances to PrimeField, PolynomialRing, and ExtensionField.
* Minor optimisations to multiplication and inversion with `INLINE`.
* Add minor optimisations to multiplication and inversion with `INLINE`.

## 0.1.0

Expand Down
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<p align="center">
<a href="https://www.adjoint.io">
<img width="250" src="./.assets/adjoint.png" alt="Adjoint Logo" />
</a>
<a href="https://www.adjoint.io">
<img width="250" src="./.assets/adjoint.png" alt="Adjoint Logo" />
</a>
</p>


Expand All @@ -14,11 +14,11 @@ An efficient implementation of Galois fields used in cryptography research.

## Technical background

A **Galois field** GF(p<sup>q</sup>), for prime p and positive q, is a *field* (GF(p<sup>q</sup>), +, \*, 0, 1) of finite *order*. Explicitly,
- (GF(p<sup>q</sup>), +, 0) is an abelian group,
- (GF(p<sup>q</sup>) \\ \{0\}, \*, 1) is an abelian group,
A **Galois field** GF(p^q), for prime p and positive q, is a *field* (GF(p^q), +, \*, 0, 1) of finite *order*. Explicitly,
- (GF(p^q), +, 0) is an abelian group,
- (GF(p^q) \\ \{0\}, \*, 1) is an abelian group,
- \* is distributive over +, and
- \#GF(p<sup>q</sup>) is finite.
- \#GF(p^q) is finite.

### Prime fields

Expand All @@ -28,9 +28,9 @@ For example, GF(4) is a Galois field of characteristic 2 that is a two-dimension

### Extension fields

Any Galois field has order a prime power p<sup>q</sup> for prime p and positive q, and there is a Galois field GF(p<sup>q</sup>) of any prime power order p<sup>q</sup> that is *unique up to non-unique isomorphism*. Any Galois field GF(p<sup>q</sup>) can be constructed as an **extension field** over a smaller Galois subfield GF(p<sup>r</sup>), through the identification GF(p<sup>q</sup>) = GF(p<sup>r</sup>)[X] / \<f(X)\> for an *irreducible monic splitting polynomial* f(X) of degree q - r + 1 in the *polynomial ring* GF(p<sup>r</sup>)[X].
Any Galois field has order a prime power p^q for prime p and positive q, and there is a Galois field GF(p^q) of any prime power order p^q that is *unique up to non-unique isomorphism*. Any Galois field GF(p^q) can be constructed as an **extension field** over a smaller Galois subfield GF(p^r), through the identification GF(p^q) = GF(p^r)[X] / \<f(X)\> for an *irreducible monic splitting polynomial* f(X) of degree q - r + 1 in the *polynomial ring* GF(p^r)[X].

For example, GF(4) has order 2<sup>2</sup> and can be constructed as an extension field GF(2)[X] / \<f(X)\> where f(X) = X<sup>2</sup> + X + 1 is an irreducible monic splitting quadratic polynomial in GF(2)[X].
For example, GF(4) has order 2^2 and can be constructed as an extension field GF(2)[X] / \<f(X)\> where f(X) = X^2 + X + 1 is an irreducible monic splitting quadratic polynomial in GF(2)[X].

## Example usage

Expand Down
6 changes: 3 additions & 3 deletions benchmarks/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fq' = 10757805228921058098980668000791497318123219899766237205512608761387909753

data Pu
instance IrreducibleMonic Fq Pu where
split _ = x^2 + 1
split _ = x ^ (2 :: Int) + 1
type Fq2 = ExtensionField Fq Pu

fq2 :: Fq2
Expand All @@ -33,7 +33,7 @@ fq2' = fromList

data Pv
instance IrreducibleMonic Fq2 Pv where
split _ = x^3 - (9 + t x)
split _ = x ^ (3 :: Int) - (9 + t x)
type Fq6 = ExtensionField Fq2 Pv

fq6 :: Fq6
Expand Down Expand Up @@ -70,7 +70,7 @@ fq6' = fromList

data Pw
instance IrreducibleMonic Fq6 Pw where
split _ = x^2 - t x
split _ = x ^ (2 :: Int) - t x
type Fq12 = ExtensionField Fq6 Pw

fq12 :: Fq12
Expand Down
19 changes: 8 additions & 11 deletions package.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: galois-field
version: 0.2.0
version: 0.2.1
synopsis: Galois field library
description: Galois field library for cryptography research
description: An efficient implementation of Galois fields used in cryptography research
maintainer: Adjoint Inc ([email protected])
license: MIT
github: adjoint-io/galois-field
Expand Down Expand Up @@ -34,14 +34,16 @@ extra-source-files:
- README.md
- ChangeLog.md

ghc-options:
- -O2
- -Wall

library:
exposed-modules:
- BinaryField
- ExtensionField
- GaloisField
- PrimeField
- ExtensionField
ghc-options:
- -O2
- -Wall
other-modules:
- PolynomialRing
source-dirs:
Expand All @@ -52,9 +54,6 @@ tests:
main: Main
dependencies:
- tasty
- tasty-discover
ghc-options:
- -O2
source-dirs:
- tests
- src
Expand All @@ -64,8 +63,6 @@ benchmarks:
main: Main
dependencies:
- criterion
ghc-options:
- -O2
source-dirs:
- benchmarks
- src
108 changes: 108 additions & 0 deletions src/BinaryField.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
module BinaryField
( BinaryField
) where

import Protolude

import Control.Monad.Random (Random(..), getRandom)
import Test.Tasty.QuickCheck (Arbitrary(..), choose)
import Text.PrettyPrint.Leijen.Text (Pretty(..))

import GaloisField (GaloisField(..))

-- | Binary fields @GF(2^q)[X]/\<f(X)\>@ for @q@ positive and
-- @f(X)@ irreducible monic in @GF(2^q)[X]@ encoded as an integer.
newtype BinaryField (ib :: Nat) = BF Integer
deriving (Eq, Generic, NFData, Show)

-- Binary fields are arbitrary.
instance KnownNat ib => Arbitrary (BinaryField ib) where
arbitrary = BF <$> choose (0, 2 ^ natVal (witness :: BinaryField ib) - 1)

-- Binary fields are fields.
instance KnownNat ib => Fractional (BinaryField ib) where
recip y@(BF x) = case inv (natVal y) x of
Just z -> BF z
_ -> panic "no multiplicative inverse."
{-# INLINE recip #-}
fromRational (x:%y) = fromInteger x / fromInteger y
{-# INLINABLE fromRational #-}

-- Binary fields are Galois fields.
instance KnownNat ib => GaloisField (BinaryField ib) where
char = const 2
{-# INLINE char #-}
deg = bin . natVal
{-# INLINE deg #-}
frob = flip pow 2
{-# INLINE frob #-}
pow = (^)
{-# INLINE pow #-}
rnd = getRandom
{-# INLINE rnd #-}

-- Binary fields are fields.
instance KnownNat ib => Num (BinaryField ib) where
BF x + BF y = BF (xor x y)
{-# INLINE (+) #-}
BF x * BF y = fromInteger (mul x y)
{-# INLINE (*) #-}
BF x - BF y = BF (xor x y)
{-# INLINE (-) #-}
negate = identity
{-# INLINE negate #-}
fromInteger = BF . red (natVal (witness :: BinaryField ib))
{-# INLINABLE fromInteger #-}
abs = panic "not implemented."
signum = panic "not implemented."

-- Binary fields are pretty.
instance KnownNat ib => Pretty (BinaryField ib) where
pretty (BF x) = pretty x

-- Binary fields are random.
instance KnownNat ib => Random (BinaryField ib) where
random = first BF . randomR (0, 2 ^ natVal (witness :: BinaryField ib) - 1)
randomR = panic "not implemented."

-- Binary logarithm.
bin :: Integer -> Int
bin = logP 2
where
logP :: Integer -> Integer -> Int
logP p x = let l = 2 * logP (p * p) x
in if x < p then 0 else log' l (quot x (p ^ l))
where
log' :: Int -> Integer -> Int
log' q y = if y < p then q else log' (q + 1) (quot y p)
{-# INLINE bin #-}

-- Binary multiplication.
mul :: Integer -> Integer -> Integer
mul x y = mul' (bin y) (if testBit y 0 then x else 0)
where
mul' :: Int -> Integer -> Integer
mul' 0 n = n
mul' l n = mul' (l - 1) (if testBit y l then xor n (shift x l) else n)
{-# INLINE mul #-}

-- Binary reduction.
red :: Integer -> Integer -> Integer
red f = red'
where
red' :: Integer -> Integer
red' x = let n = bin x - bin f
in if n < 0 then x else red' (xor x (shift f n))
{-# INLINE red #-}

-- Binary inversion.
inv :: Integer -> Integer -> Maybe Integer
inv f x = case inv' 1 x 0 f of
(y, 1) -> Just y
_ -> Nothing
where
inv' :: Integer -> Integer -> Integer -> Integer -> (Integer, Integer)
inv' t r _ 0 = (t, r)
inv' t r t' r' = let q = max 0 (bin r - bin r')
in inv' t' r' (xor t (shift t' q)) (xor r (shift r' q))
{-# INLINE inv #-}
Loading

0 comments on commit c2e69d8

Please sign in to comment.