Add pointMulByCofactor and pointHasPrimeOrder
This commit is contained in:
parent
9cd77ed3e2
commit
3217038a1a
@ -37,6 +37,10 @@
|
|||||||
--
|
--
|
||||||
-- - or cofactor must be cleared by multiplying points by 8
|
-- - or cofactor must be cleared by multiplying points by 8
|
||||||
--
|
--
|
||||||
|
-- Utility functions are provided to implement this. Testing
|
||||||
|
-- subgroup membership with 'pointHasPrimeOrder' is 50-time slower
|
||||||
|
-- than call 'pointMulByCofactor'.
|
||||||
|
--
|
||||||
-- 2. Scalar arithmetic is always reduced modulo L, allowing fixed
|
-- 2. Scalar arithmetic is always reduced modulo L, allowing fixed
|
||||||
-- length and constant execution time, but this reduction is valid
|
-- length and constant execution time, but this reduction is valid
|
||||||
-- only when points are in the prime-order subgroup.
|
-- only when points are in the prime-order subgroup.
|
||||||
@ -56,6 +60,7 @@ module Crypto.ECC.Edwards25519
|
|||||||
-- * Points
|
-- * Points
|
||||||
, pointDecode
|
, pointDecode
|
||||||
, pointEncode
|
, pointEncode
|
||||||
|
, pointHasPrimeOrder
|
||||||
-- * Arithmetic functions
|
-- * Arithmetic functions
|
||||||
, toPoint
|
, toPoint
|
||||||
, scalarAdd
|
, scalarAdd
|
||||||
@ -64,6 +69,7 @@ module Crypto.ECC.Edwards25519
|
|||||||
, pointAdd
|
, pointAdd
|
||||||
, pointDouble
|
, pointDouble
|
||||||
, pointMul
|
, pointMul
|
||||||
|
, pointMulByCofactor
|
||||||
, pointsMulVarTime
|
, pointsMulVarTime
|
||||||
) where
|
) where
|
||||||
|
|
||||||
@ -203,6 +209,19 @@ pointDecode bs
|
|||||||
else return $ CryptoPassed (Point p)
|
else return $ CryptoPassed (Point p)
|
||||||
{-# NOINLINE pointDecode #-}
|
{-# NOINLINE pointDecode #-}
|
||||||
|
|
||||||
|
-- | Test whether a point belongs to the prime-order subgroup
|
||||||
|
-- generated by the base point. Result is 'True' for the identity
|
||||||
|
-- point.
|
||||||
|
--
|
||||||
|
-- @
|
||||||
|
-- pointHasPrimeOrder p = 'pointNegate' p == 'pointMul' l_minus_one p
|
||||||
|
-- @
|
||||||
|
pointHasPrimeOrder :: Point -> Bool
|
||||||
|
pointHasPrimeOrder (Point p) = unsafeDoIO $
|
||||||
|
withByteArray p $ \pp ->
|
||||||
|
fmap (/= 0) (ed25519_point_has_prime_order pp)
|
||||||
|
{-# NOINLINE pointHasPrimeOrder #-}
|
||||||
|
|
||||||
-- | Negate a point.
|
-- | Negate a point.
|
||||||
pointNegate :: Point -> Point
|
pointNegate :: Point -> Point
|
||||||
pointNegate (Point a) =
|
pointNegate (Point a) =
|
||||||
@ -229,6 +248,17 @@ pointDouble (Point a) =
|
|||||||
withByteArray a $ \pa ->
|
withByteArray a $ \pa ->
|
||||||
ed25519_point_double out pa
|
ed25519_point_double out pa
|
||||||
|
|
||||||
|
-- | Multiply a point by h = 8.
|
||||||
|
--
|
||||||
|
-- @
|
||||||
|
-- pointMulByCofactor p = 'pointMul' scalar_8 p
|
||||||
|
-- @
|
||||||
|
pointMulByCofactor :: Point -> Point
|
||||||
|
pointMulByCofactor (Point a) =
|
||||||
|
Point $ B.allocAndFreeze pointArraySize $ \out ->
|
||||||
|
withByteArray a $ \pa ->
|
||||||
|
ed25519_point_mul_by_cofactor out pa
|
||||||
|
|
||||||
-- | Scalar multiplication over curve edwards25519.
|
-- | Scalar multiplication over curve edwards25519.
|
||||||
--
|
--
|
||||||
-- Note: when the scalar had reduction modulo L and the input point
|
-- Note: when the scalar had reduction modulo L and the input point
|
||||||
@ -299,6 +329,10 @@ foreign import ccall "cryptonite_ed25519_point_eq"
|
|||||||
-> Ptr Point
|
-> Ptr Point
|
||||||
-> IO CInt
|
-> IO CInt
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_ed25519_point_has_prime_order"
|
||||||
|
ed25519_point_has_prime_order :: Ptr Point
|
||||||
|
-> IO CInt
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_point_negate"
|
foreign import ccall "cryptonite_ed25519_point_negate"
|
||||||
ed25519_point_negate :: Ptr Point -- minus_a
|
ed25519_point_negate :: Ptr Point -- minus_a
|
||||||
-> Ptr Point -- a
|
-> Ptr Point -- a
|
||||||
@ -315,6 +349,11 @@ foreign import ccall "cryptonite_ed25519_point_double"
|
|||||||
-> Ptr Point -- a
|
-> Ptr Point -- a
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_ed25519_point_mul_by_cofactor"
|
||||||
|
ed25519_point_mul_by_cofactor :: Ptr Point -- eight_a
|
||||||
|
-> Ptr Point -- a
|
||||||
|
-> IO ()
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_point_base_scalarmul"
|
foreign import ccall "cryptonite_ed25519_point_base_scalarmul"
|
||||||
ed25519_point_base_scalarmul :: Ptr Point -- scaled
|
ed25519_point_base_scalarmul :: Ptr Point -- scaled
|
||||||
-> Ptr Scalar -- scalar
|
-> Ptr Scalar -- scalar
|
||||||
|
|||||||
@ -87,6 +87,25 @@ ED25519_FN(ed25519_point_eq) (const ge25519 *p, const ge25519 *q) {
|
|||||||
return eq;
|
return eq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ED25519_FN(ed25519_point_is_identity) (const ge25519 *p) {
|
||||||
|
static const unsigned char zero[32] = {0};
|
||||||
|
unsigned char check[32];
|
||||||
|
bignum25519 d;
|
||||||
|
int eq;
|
||||||
|
|
||||||
|
// pX = 0
|
||||||
|
curve25519_contract(check, p->x);
|
||||||
|
eq = ed25519_verify(check, zero, 32);
|
||||||
|
|
||||||
|
// pY - pZ = 0
|
||||||
|
curve25519_sub_reduce(d, p->y, p->z);
|
||||||
|
curve25519_contract(check, d);
|
||||||
|
eq &= ed25519_verify(check, zero, 32);
|
||||||
|
|
||||||
|
return eq;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ED25519_FN(ed25519_point_negate) (ge25519 *r, const ge25519 *p) {
|
ED25519_FN(ed25519_point_negate) (ge25519 *r, const ge25519 *p) {
|
||||||
curve25519_neg(r->x, p->x);
|
curve25519_neg(r->x, p->x);
|
||||||
@ -105,6 +124,13 @@ ED25519_FN(ed25519_point_double) (ge25519 *r, const ge25519 *p) {
|
|||||||
ge25519_double(r, p);
|
ge25519_double(r, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ED25519_FN(ed25519_point_mul_by_cofactor) (ge25519 *r, const ge25519 *p) {
|
||||||
|
ge25519_double_partial(r, p);
|
||||||
|
ge25519_double_partial(r, r);
|
||||||
|
ge25519_double(r, r);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ED25519_FN(ed25519_point_base_scalarmul) (ge25519 *r, const bignum256modm s) {
|
ED25519_FN(ed25519_point_base_scalarmul) (ge25519 *r, const bignum256modm s) {
|
||||||
ge25519_scalarmult_base_niels(r, ge25519_niels_base_multiples, s);
|
ge25519_scalarmult_base_niels(r, ge25519_niels_base_multiples, s);
|
||||||
@ -207,3 +233,14 @@ ED25519_FN(ed25519_base_double_scalarmul_vartime) (ge25519 *r, const bignum256mo
|
|||||||
// computes [s1]basepoint + [s2]p2
|
// computes [s1]basepoint + [s2]p2
|
||||||
ge25519_double_scalarmult_vartime(r, p2, s2, s1);
|
ge25519_double_scalarmult_vartime(r, p2, s2, s1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ED25519_FN(ed25519_point_has_prime_order) (const ge25519 *p) {
|
||||||
|
static const bignum256modm sc_zero = {0};
|
||||||
|
ge25519 q;
|
||||||
|
|
||||||
|
// computes Q = m.P, vartime allowed because m is not secret
|
||||||
|
ED25519_FN(ed25519_base_double_scalarmul_vartime) (&q, sc_zero, p, modm_m);
|
||||||
|
|
||||||
|
return ED25519_FN(ed25519_point_is_identity) (&q);
|
||||||
|
}
|
||||||
|
|||||||
@ -93,6 +93,10 @@ tests = testGroup "ECC.Edwards25519"
|
|||||||
p0 `propertyEq` pointAdd p (pointNegate p)
|
p0 `propertyEq` pointAdd p (pointNegate p)
|
||||||
, testProperty "doubling" $ \p ->
|
, testProperty "doubling" $ \p ->
|
||||||
pointAdd p p `propertyEq` pointDouble p
|
pointAdd p p `propertyEq` pointDouble p
|
||||||
|
, testProperty "multiplication by cofactor" $ \p ->
|
||||||
|
pointMul s8 p `propertyEq` pointMulByCofactor p
|
||||||
|
, testProperty "prime order" $ \(PrimeOrder p) ->
|
||||||
|
True `propertyEq` pointHasPrimeOrder p
|
||||||
, testCase "8-torsion point" $ do
|
, testCase "8-torsion point" $ do
|
||||||
assertBool "mul by 4" $ p0 /= pointMul s4 torsion8
|
assertBool "mul by 4" $ p0 /= pointMul s4 torsion8
|
||||||
assertBool "mul by 8" $ p0 == pointMul s8 torsion8
|
assertBool "mul by 8" $ p0 == pointMul s8 torsion8
|
||||||
@ -102,8 +106,8 @@ tests = testGroup "ECC.Edwards25519"
|
|||||||
p `propertyEq` pointMul s1 p
|
p `propertyEq` pointMul s1 p
|
||||||
, testProperty "scalarmult with two" $ \p ->
|
, testProperty "scalarmult with two" $ \p ->
|
||||||
pointDouble p `propertyEq` pointMul s2 p
|
pointDouble p `propertyEq` pointMul s2 p
|
||||||
, testProperty "scalarmult with curve order - 1" $ \(PrimeOrder p) ->
|
, testProperty "scalarmult with curve order - 1" $ \p ->
|
||||||
pointNegate p `propertyEq` pointMul sI p
|
pointHasPrimeOrder p === (pointNegate p == pointMul sI p)
|
||||||
, testProperty "scalarmult commutative" $ \a b ->
|
, testProperty "scalarmult commutative" $ \a b ->
|
||||||
pointMul a (toPoint b) === pointMul b (toPoint a)
|
pointMul a (toPoint b) === pointMul b (toPoint a)
|
||||||
, testProperty "scalarmult distributive" $ \x y (PrimeOrder p) ->
|
, testProperty "scalarmult distributive" $ \x y (PrimeOrder p) ->
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user