|
| 1 | +module Bulletproofs.Curve where |
| 2 | + |
| 3 | +import Protolude hiding (hash) |
| 4 | + |
| 5 | +import Crypto.Hash |
| 6 | +import qualified Crypto.PubKey.ECC.Generate as Crypto |
| 7 | +import qualified Crypto.PubKey.ECC.Prim as Crypto |
| 8 | +import qualified Crypto.PubKey.ECC.Types as Crypto |
| 9 | + |
| 10 | +import qualified Data.ByteArray as BA |
| 11 | +import Crypto.Number.Serialize (os2ip) |
| 12 | +import Math.NumberTheory.Moduli.Sqrt (sqrtModP) |
| 13 | + |
| 14 | +-- TEST |
| 15 | +import Numeric |
| 16 | +import qualified Data.List as L |
| 17 | + |
| 18 | +curveName :: Crypto.CurveName |
| 19 | +curveName = Crypto.SEC_p256k1 |
| 20 | + |
| 21 | +curve :: Crypto.Curve |
| 22 | +curve = Crypto.getCurveByName curveName |
| 23 | + |
| 24 | +-- | Order of the curve |
| 25 | +q :: Integer |
| 26 | +q = Crypto.ecc_n . Crypto.common_curve $ curve |
| 27 | + |
| 28 | +-- | Generator of the curve |
| 29 | +g :: Crypto.Point |
| 30 | +g = Crypto.ecc_g $ Crypto.common_curve curve |
| 31 | + |
| 32 | +-- | H = aG where a is not known |
| 33 | +h :: Crypto.Point |
| 34 | +h = generateH g "" |
| 35 | + |
| 36 | +-- | Generate vector of generators in a deterministic way from the curve generator g |
| 37 | +-- by applying H(encode(g) || i) where H is a secure hash function |
| 38 | +gs :: [Crypto.Point] |
| 39 | +gs = Crypto.pointBaseMul curve . oracle . (<> pointToBS g) . show <$> [1..] |
| 40 | + |
| 41 | +-- | Generate vector of generators in a deterministic way from the curve generator h |
| 42 | +-- by applying H(encode(h) || i) where H is a secure hash function |
| 43 | +hs :: [Crypto.Point] |
| 44 | +hs = Crypto.pointBaseMul curve . oracle . (<> pointToBS h) . show <$> [1..] |
| 45 | + |
| 46 | +-- | A random oracle. In the Fiat-Shamir heuristic, its input |
| 47 | +-- is specifically the transcript of the interaction up to that point. |
| 48 | +oracle :: ByteString -> Integer |
| 49 | +oracle x = os2ip (sha256 x) |
| 50 | + |
| 51 | +sha256 :: ByteString -> ByteString |
| 52 | +sha256 bs = BA.convert (hash bs :: Digest SHA3_256) |
| 53 | + |
| 54 | +pointToBS :: Crypto.Point -> ByteString |
| 55 | +pointToBS Crypto.PointO = "" |
| 56 | +pointToBS (Crypto.Point x y) = show x <> show y |
| 57 | + |
| 58 | +-- | Characteristic of the underlying finite field of the elliptic curve |
| 59 | +p :: Integer |
| 60 | +p = Crypto.ecc_p cp |
| 61 | + where |
| 62 | + cp = case curve of |
| 63 | + Crypto.CurveFP c -> c |
| 64 | + Crypto.CurveF2m _ -> panic "Not a FP curve" |
| 65 | + |
| 66 | +-- | Iterative algorithm to generate H. |
| 67 | +-- The important thing about the H value is that nobody gets |
| 68 | +-- to know its discrete logarithm "k" such that H = kG |
| 69 | +generateH :: Crypto.Point -> [Char] -> Crypto.Point |
| 70 | +generateH basePoint extra = |
| 71 | + case yM of |
| 72 | + Nothing -> generateH basePoint (toS $ '1':extra) |
| 73 | + Just y -> if Crypto.isPointValid curve (Crypto.Point x y) |
| 74 | + then Crypto.Point x y |
| 75 | + else generateH basePoint (toS $ '1':extra) |
| 76 | + where |
| 77 | + x = oracle (pointToBS basePoint <> toS extra) `mod` p |
| 78 | + yM = sqrtModP (x ^ 3 + 7) p |
| 79 | + |
0 commit comments