Added Ed448-Goldilocks support
This commit is contained in:
parent
b7d12b957b
commit
a04b56d2a3
102
Crypto/PubKey/Ed448.hs
Normal file
102
Crypto/PubKey/Ed448.hs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
-- |
|
||||||
|
-- Module : Crypto.PubKey.Ed448
|
||||||
|
-- License : BSD-style
|
||||||
|
-- Maintainer : John Galt <jgalt@centromere.net>
|
||||||
|
-- Stability : experimental
|
||||||
|
-- Portability : unknown
|
||||||
|
--
|
||||||
|
-- Ed448 support
|
||||||
|
--
|
||||||
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
|
{-# LANGUAGE MagicHash #-}
|
||||||
|
module Crypto.PubKey.Ed448
|
||||||
|
( SecretKey
|
||||||
|
, PublicKey
|
||||||
|
, DhSecret
|
||||||
|
-- * Smart constructors
|
||||||
|
, dhSecret
|
||||||
|
, publicKey
|
||||||
|
, secretKey
|
||||||
|
-- * methods
|
||||||
|
, dh
|
||||||
|
, toPublic
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.Word
|
||||||
|
import Foreign.Ptr
|
||||||
|
import GHC.Ptr
|
||||||
|
|
||||||
|
import Crypto.Error
|
||||||
|
import Crypto.Internal.Compat
|
||||||
|
import Crypto.Internal.Imports
|
||||||
|
import Crypto.Internal.ByteArray (ByteArrayAccess, ScrubbedBytes, Bytes, withByteArray)
|
||||||
|
import qualified Crypto.Internal.ByteArray as B
|
||||||
|
|
||||||
|
-- | A Ed448 Secret key
|
||||||
|
newtype SecretKey = SecretKey ScrubbedBytes
|
||||||
|
deriving (Show,Eq,ByteArrayAccess,NFData)
|
||||||
|
|
||||||
|
-- | A Ed448 public key
|
||||||
|
newtype PublicKey = PublicKey Bytes
|
||||||
|
deriving (Show,Eq,ByteArrayAccess,NFData)
|
||||||
|
|
||||||
|
-- | A Ed448 Diffie Hellman secret related to a
|
||||||
|
-- public key and a secret key.
|
||||||
|
newtype DhSecret = DhSecret ScrubbedBytes
|
||||||
|
deriving (Show,Eq,ByteArrayAccess,NFData)
|
||||||
|
|
||||||
|
-- | Try to build a public key from a bytearray
|
||||||
|
publicKey :: ByteArrayAccess bs => bs -> CryptoFailable PublicKey
|
||||||
|
publicKey bs
|
||||||
|
| B.length bs == x448_bytes = CryptoPassed $ PublicKey $ B.copyAndFreeze bs (\_ -> return ())
|
||||||
|
| otherwise = CryptoFailed CryptoError_PublicKeySizeInvalid
|
||||||
|
|
||||||
|
-- | Try to build a secret key from a bytearray
|
||||||
|
secretKey :: ByteArrayAccess bs => bs -> CryptoFailable SecretKey
|
||||||
|
secretKey bs
|
||||||
|
| B.length bs == x448_bytes = unsafeDoIO $
|
||||||
|
withByteArray bs $ \inp -> do
|
||||||
|
valid <- isValidPtr inp
|
||||||
|
if valid
|
||||||
|
then (CryptoPassed . SecretKey) <$> B.copy bs (\_ -> return ())
|
||||||
|
else return $ CryptoFailed CryptoError_SecretKeyStructureInvalid
|
||||||
|
| otherwise = CryptoFailed CryptoError_SecretKeySizeInvalid
|
||||||
|
where
|
||||||
|
isValidPtr :: Ptr Word8 -> IO Bool
|
||||||
|
isValidPtr _ =
|
||||||
|
return True
|
||||||
|
{-# NOINLINE secretKey #-}
|
||||||
|
|
||||||
|
-- | Create a DhSecret from a bytearray object
|
||||||
|
dhSecret :: ByteArrayAccess b => b -> CryptoFailable DhSecret
|
||||||
|
dhSecret bs
|
||||||
|
| B.length bs == x448_bytes = CryptoPassed $ DhSecret $ B.copyAndFreeze bs (\_ -> return ())
|
||||||
|
| otherwise = CryptoFailed CryptoError_SharedSecretSizeInvalid
|
||||||
|
|
||||||
|
-- | Compute the Diffie Hellman secret from a public key and a secret key
|
||||||
|
dh :: PublicKey -> SecretKey -> DhSecret
|
||||||
|
dh (PublicKey pub) (SecretKey sec) = DhSecret <$>
|
||||||
|
B.allocAndFreeze x448_bytes $ \result ->
|
||||||
|
withByteArray sec $ \psec ->
|
||||||
|
withByteArray pub $ \ppub ->
|
||||||
|
ccryptonite_ed448 result psec ppub
|
||||||
|
{-# NOINLINE dh #-}
|
||||||
|
|
||||||
|
-- | Create a public key from a secret key
|
||||||
|
toPublic :: SecretKey -> PublicKey
|
||||||
|
toPublic (SecretKey sec) = PublicKey <$>
|
||||||
|
B.allocAndFreeze x448_bytes $ \result ->
|
||||||
|
withByteArray sec $ \psec ->
|
||||||
|
ccryptonite_ed448 result psec basePoint
|
||||||
|
where
|
||||||
|
basePoint = Ptr "\x05\x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00"#
|
||||||
|
{-# NOINLINE toPublic #-}
|
||||||
|
|
||||||
|
x448_bytes :: Int
|
||||||
|
x448_bytes = 448 `quot` 8
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_x448"
|
||||||
|
ccryptonite_ed448 :: Ptr Word8 -- ^ public
|
||||||
|
-> Ptr Word8 -- ^ secret
|
||||||
|
-> Ptr Word8 -- ^ basepoint
|
||||||
|
-> IO ()
|
||||||
306
cbits/ed448/x448.c
Normal file
306
cbits/ed448/x448.c
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
/* Copyright (c) 2015 Cryptography Research, Inc.
|
||||||
|
* Released under the MIT License. See LICENSE.txt for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file decaf.c
|
||||||
|
* @author Mike Hamburg
|
||||||
|
* @brief Decaf high-level functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "x448.h"
|
||||||
|
|
||||||
|
#define WBITS 64 /* TODO */
|
||||||
|
#define LBITS (WBITS * 7 / 8)
|
||||||
|
#define X448_LIMBS (448/LBITS)
|
||||||
|
|
||||||
|
#if WBITS == 64
|
||||||
|
typedef uint64_t decaf_word_t;
|
||||||
|
typedef int64_t decaf_sword_t;
|
||||||
|
typedef __uint128_t decaf_dword_t;
|
||||||
|
typedef __int128_t decaf_sdword_t;
|
||||||
|
#elif WBITS == 32
|
||||||
|
typedef uint32_t decaf_word_t;
|
||||||
|
typedef int32_t decaf_sword_t;
|
||||||
|
typedef uint64_t decaf_dword_t;
|
||||||
|
typedef int64_t decaf_sdword_t;
|
||||||
|
#else
|
||||||
|
#error "WBITS must be 32 or 64"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct { decaf_word_t limb[X448_LIMBS]; } gf_s, gf[1];
|
||||||
|
|
||||||
|
const unsigned char X448_BASE_POINT[X448_BYTES] = {5};
|
||||||
|
|
||||||
|
static const gf ZERO = {{{0}}}, ONE = {{{1}}};
|
||||||
|
|
||||||
|
#define LMASK ((((decaf_word_t)1)<<LBITS)-1)
|
||||||
|
#if WBITS == 64
|
||||||
|
static const gf P = {{{ LMASK, LMASK, LMASK, LMASK, LMASK-1, LMASK, LMASK, LMASK }}};
|
||||||
|
#else
|
||||||
|
static const gf P = {{{ LMASK, LMASK, LMASK, LMASK, LMASK, LMASK, LMASK, LMASK,
|
||||||
|
LMASK-1, LMASK, LMASK, LMASK, LMASK, LMASK, LMASK, LMASK }}};
|
||||||
|
#endif
|
||||||
|
static const int EDWARDS_D = -39081;
|
||||||
|
|
||||||
|
#if (defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__)) || defined(DECAF_FORCE_UNROLL)
|
||||||
|
#if X448_LIMBS==8
|
||||||
|
#define FOR_LIMB_U(i,op) { unsigned int i=0; \
|
||||||
|
op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; \
|
||||||
|
}
|
||||||
|
#elif X448_LIMBS==16
|
||||||
|
#define FOR_LIMB_U(i,op) { unsigned int i=0; \
|
||||||
|
op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; \
|
||||||
|
op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define FOR_LIMB_U(i,op) { unsigned int i=0; for (i=0; i<X448_LIMBS; i++) { op; }}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define FOR_LIMB_U(i,op) { unsigned int i=0; for (i=0; i<X448_LIMBS; i++) { op; }}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FOR_LIMB(i,op) { unsigned int i=0; for (i=0; i<X448_LIMBS; i++) { op; }}
|
||||||
|
|
||||||
|
/** Copy x = y */
|
||||||
|
static void gf_cpy(gf x, const gf y) {
|
||||||
|
FOR_LIMB_U(i, x->limb[i] = y->limb[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Mostly-unoptimized multiply (PERF), but at least it's unrolled. */
|
||||||
|
static void
|
||||||
|
gf_mul (gf c, const gf a, const gf b) {
|
||||||
|
gf aa;
|
||||||
|
gf_cpy(aa,a);
|
||||||
|
|
||||||
|
decaf_dword_t accum[X448_LIMBS] = {0};
|
||||||
|
FOR_LIMB_U(i, {
|
||||||
|
FOR_LIMB_U(j,{ accum[(i+j)%X448_LIMBS] += (decaf_dword_t)b->limb[i] * aa->limb[j]; });
|
||||||
|
aa->limb[(X448_LIMBS-1-i)^(X448_LIMBS/2)] += aa->limb[X448_LIMBS-1-i];
|
||||||
|
});
|
||||||
|
|
||||||
|
accum[X448_LIMBS-1] += accum[X448_LIMBS-2] >> LBITS;
|
||||||
|
accum[X448_LIMBS-2] &= LMASK;
|
||||||
|
accum[X448_LIMBS/2] += accum[X448_LIMBS-1] >> LBITS;
|
||||||
|
FOR_LIMB_U(j,{
|
||||||
|
accum[j] += accum[(j-1)%X448_LIMBS] >> LBITS;
|
||||||
|
accum[(j-1)%X448_LIMBS] &= LMASK;
|
||||||
|
});
|
||||||
|
FOR_LIMB_U(j, c->limb[j] = accum[j] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** No dedicated square (PERF) */
|
||||||
|
#define gf_sqr(c,a) gf_mul(c,a,a)
|
||||||
|
|
||||||
|
/** Inverse square root using addition chain. */
|
||||||
|
static void
|
||||||
|
gf_isqrt(gf y, const gf x) {
|
||||||
|
int i;
|
||||||
|
#define STEP(s,m,n) gf_mul(s,m,c); gf_cpy(c,s); for (i=0;i<n;i++) gf_sqr(c,c);
|
||||||
|
gf a, b, c;
|
||||||
|
gf_sqr ( c, x );
|
||||||
|
STEP(b,x,1);
|
||||||
|
STEP(b,x,3);
|
||||||
|
STEP(a,b,3);
|
||||||
|
STEP(a,b,9);
|
||||||
|
STEP(b,a,1);
|
||||||
|
STEP(a,x,18);
|
||||||
|
STEP(a,b,37);
|
||||||
|
STEP(b,a,37);
|
||||||
|
STEP(b,a,111);
|
||||||
|
STEP(a,b,1);
|
||||||
|
STEP(b,x,223);
|
||||||
|
gf_mul(y,a,c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gf_inv(gf y, const gf x) {
|
||||||
|
gf z,w;
|
||||||
|
gf_sqr(z,x); /* x^2 */
|
||||||
|
gf_isqrt(w,z); /* +- 1/sqrt(x^2) = +- 1/x */
|
||||||
|
gf_sqr(z,w); /* 1/x^2 */
|
||||||
|
gf_mul(w,x,z); /* 1/x */
|
||||||
|
gf_cpy(y,w);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Weak reduce mod p. */
|
||||||
|
static void
|
||||||
|
gf_reduce(gf x) {
|
||||||
|
x->limb[X448_LIMBS/2] += x->limb[X448_LIMBS-1] >> LBITS;
|
||||||
|
FOR_LIMB_U(j,{
|
||||||
|
x->limb[j] += x->limb[(j-1)%X448_LIMBS] >> LBITS;
|
||||||
|
x->limb[(j-1)%X448_LIMBS] &= LMASK;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add mod p. Conservatively always weak-reduce. (PERF) */
|
||||||
|
static void
|
||||||
|
gf_add ( gf x, const gf y, const gf z ) {
|
||||||
|
FOR_LIMB_U(i, x->limb[i] = y->limb[i] + z->limb[i] );
|
||||||
|
gf_reduce(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Subtract mod p. Conservatively always weak-reduce. (PERF) */
|
||||||
|
static void
|
||||||
|
gf_sub ( gf x, const gf y, const gf z ) {
|
||||||
|
FOR_LIMB_U(i, x->limb[i] = y->limb[i] - z->limb[i] + 2*P->limb[i] );
|
||||||
|
gf_reduce(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Constant time, if (swap) (x,y) = (y,x); */
|
||||||
|
static void
|
||||||
|
cond_swap(gf x, gf_s *__restrict__ y, decaf_word_t swap) {
|
||||||
|
FOR_LIMB_U(i, {
|
||||||
|
decaf_word_t s = (x->limb[i] ^ y->limb[i]) & swap;
|
||||||
|
x->limb[i] ^= s;
|
||||||
|
y->limb[i] ^= s;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mul by signed int. Not constant-time WRT the sign of that int.
|
||||||
|
* Just uses a full mul (PERF)
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
gf_mlw(gf a, const gf b, int w) {
|
||||||
|
if (w>0) {
|
||||||
|
gf ww = {{{w}}};
|
||||||
|
gf_mul(a,b,ww);
|
||||||
|
} else {
|
||||||
|
gf ww = {{{-w}}};
|
||||||
|
gf_mul(a,b,ww);
|
||||||
|
gf_sub(a,ZERO,a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Canonicalize */
|
||||||
|
static void gf_canon ( gf a ) {
|
||||||
|
gf_reduce(a);
|
||||||
|
|
||||||
|
/* subtract p with borrow */
|
||||||
|
decaf_sdword_t carry = 0;
|
||||||
|
FOR_LIMB(i, {
|
||||||
|
carry = carry + a->limb[i] - P->limb[i];
|
||||||
|
a->limb[i] = carry & LMASK;
|
||||||
|
carry >>= LBITS;
|
||||||
|
});
|
||||||
|
|
||||||
|
decaf_word_t addback = carry;
|
||||||
|
carry = 0;
|
||||||
|
|
||||||
|
/* add it back */
|
||||||
|
FOR_LIMB(i, {
|
||||||
|
carry = carry + a->limb[i] + (P->limb[i] & addback);
|
||||||
|
a->limb[i] = carry & LMASK;
|
||||||
|
carry >>= LBITS;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deserialize */
|
||||||
|
static decaf_word_t
|
||||||
|
gf_deser(gf s, const unsigned char ser[X448_BYTES]) {
|
||||||
|
unsigned int i, k=0, bits=0;
|
||||||
|
decaf_dword_t buf=0;
|
||||||
|
for (i=0; i<X448_BYTES; i++) {
|
||||||
|
buf |= (decaf_dword_t)ser[i]<<bits;
|
||||||
|
for (bits += 8; (bits>=LBITS || i==X448_BYTES-1) && k<X448_LIMBS; bits-=LBITS, buf>>=LBITS) {
|
||||||
|
s->limb[k++] = buf & LMASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decaf_sdword_t accum = 0;
|
||||||
|
FOR_LIMB(i, accum = (accum + s->limb[i] - P->limb[i]) >> WBITS );
|
||||||
|
return accum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Serialize */
|
||||||
|
static void
|
||||||
|
gf_ser(uint8_t ser[X448_BYTES], gf a) {
|
||||||
|
gf_canon(a);
|
||||||
|
int k=0, bits=0;
|
||||||
|
decaf_dword_t buf=0;
|
||||||
|
FOR_LIMB(i, {
|
||||||
|
buf |= (decaf_dword_t)a->limb[i]<<bits;
|
||||||
|
for (bits += LBITS; (bits>=8 || i==X448_LIMBS-1) && k<X448_BYTES; bits-=8, buf>>=8) {
|
||||||
|
ser[k++]=buf;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int __attribute__((visibility("default"))) cryptonite_x448 (
|
||||||
|
unsigned char out[X448_BYTES],
|
||||||
|
const unsigned char scalar[X448_BYTES],
|
||||||
|
const unsigned char base[X448_BYTES]
|
||||||
|
) {
|
||||||
|
gf x1, x2, z2, x3, z3, t1, t2;
|
||||||
|
gf_deser(x1,base);
|
||||||
|
gf_cpy(x2,ONE);
|
||||||
|
gf_cpy(z2,ZERO);
|
||||||
|
gf_cpy(x3,x1);
|
||||||
|
gf_cpy(z3,ONE);
|
||||||
|
|
||||||
|
int t;
|
||||||
|
decaf_word_t swap = 0;
|
||||||
|
|
||||||
|
for (t = 448-1; t>=0; t--) {
|
||||||
|
uint8_t sb = scalar[t/8];
|
||||||
|
|
||||||
|
/* Scalar conditioning */
|
||||||
|
if (t/8==0) sb &= 0xFC;
|
||||||
|
else if (t/8 == X448_BYTES-1) sb |= 0x80;
|
||||||
|
|
||||||
|
decaf_word_t k_t = (sb>>(t%8)) & 1;
|
||||||
|
k_t = -k_t; /* set to all 0s or all 1s */
|
||||||
|
|
||||||
|
swap ^= k_t;
|
||||||
|
cond_swap(x2,x3,swap);
|
||||||
|
cond_swap(z2,z3,swap);
|
||||||
|
swap = k_t;
|
||||||
|
|
||||||
|
gf_add(t1,x2,z2); /* A = x2 + z2 */
|
||||||
|
gf_sub(t2,x2,z2); /* B = x2 - z2 */
|
||||||
|
gf_sub(z2,x3,z3); /* D = x3 - z3 */
|
||||||
|
gf_mul(x2,t1,z2); /* DA */
|
||||||
|
gf_add(z2,z3,x3); /* C = x3 + z3 */
|
||||||
|
gf_mul(x3,t2,z2); /* CB */
|
||||||
|
gf_sub(z3,x2,x3); /* DA-CB */
|
||||||
|
gf_sqr(z2,z3); /* (DA-CB)^2 */
|
||||||
|
gf_mul(z3,x1,z2); /* z3 = x1(DA-CB)^2 */
|
||||||
|
gf_add(z2,x2,x3); /* (DA+CB) */
|
||||||
|
gf_sqr(x3,z2); /* x3 = (DA+CB)^2 */
|
||||||
|
|
||||||
|
gf_sqr(z2,t1); /* AA = A^2 */
|
||||||
|
gf_sqr(t1,t2); /* BB = B^2 */
|
||||||
|
gf_mul(x2,z2,t1); /* x2 = AA*BB */
|
||||||
|
gf_sub(t2,z2,t1); /* E = AA-BB */
|
||||||
|
|
||||||
|
gf_mlw(t1,t2,-EDWARDS_D); /* E*-d = a24*E */
|
||||||
|
gf_add(t1,t1,z2); /* AA + a24*E */
|
||||||
|
gf_mul(z2,t2,t1); /* z2 = E(AA+a24*E) */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finish */
|
||||||
|
cond_swap(x2,x3,swap);
|
||||||
|
cond_swap(z2,z3,swap);
|
||||||
|
gf_inv(z2,z2);
|
||||||
|
gf_mul(x1,x2,z2);
|
||||||
|
gf_ser(out,x1);
|
||||||
|
|
||||||
|
decaf_sword_t nz = 0;
|
||||||
|
for (t=0; t<X448_BYTES; t++) {
|
||||||
|
nz |= out[t];
|
||||||
|
}
|
||||||
|
nz = (nz-1)>>8; /* 0 = succ, -1 = fail */
|
||||||
|
|
||||||
|
/* return value: 0 = succ, -1 = fail */
|
||||||
|
return nz;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __attribute__((visibility("default")))
|
||||||
|
cryptonite_x448_base (
|
||||||
|
unsigned char out[X448_BYTES],
|
||||||
|
const unsigned char scalar[X448_BYTES]
|
||||||
|
) {
|
||||||
|
return cryptonite_x448(out,scalar,X448_BASE_POINT);
|
||||||
|
}
|
||||||
25
cbits/ed448/x448.h
Normal file
25
cbits/ed448/x448.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
#define X448_BYTES (448/8)
|
||||||
|
|
||||||
|
/* The base point (5) */
|
||||||
|
extern const unsigned char X448_BASE_POINT[X448_BYTES];
|
||||||
|
|
||||||
|
/* Returns 0 on success, -1 on failure */
|
||||||
|
int __attribute__((visibility("default")))
|
||||||
|
cryptonite_x448 (
|
||||||
|
unsigned char out[X448_BYTES],
|
||||||
|
const unsigned char scalar[X448_BYTES],
|
||||||
|
const unsigned char base[X448_BYTES]
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Returns 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* Same as x448(out,scalar,X448_BASE_POINT), except that
|
||||||
|
* an implementation may optimize it.
|
||||||
|
*/
|
||||||
|
int __attribute__((visibility("default")))
|
||||||
|
cryptonite_x448_base (
|
||||||
|
unsigned char out[X448_BYTES],
|
||||||
|
const unsigned char scalar[X448_BYTES]
|
||||||
|
);
|
||||||
|
|
||||||
@ -38,6 +38,7 @@ extra-doc-files: README.md CHANGELOG.md
|
|||||||
extra-source-files: cbits/*.h
|
extra-source-files: cbits/*.h
|
||||||
cbits/aes/*.h
|
cbits/aes/*.h
|
||||||
cbits/ed25519/*.h
|
cbits/ed25519/*.h
|
||||||
|
cbits/ed448/*.h
|
||||||
cbits/p256/*.h
|
cbits/p256/*.h
|
||||||
cbits/blake2/ref/*.h
|
cbits/blake2/ref/*.h
|
||||||
cbits/blake2/ref/*.c
|
cbits/blake2/ref/*.c
|
||||||
@ -121,6 +122,7 @@ Library
|
|||||||
Crypto.PubKey.ECC.P256
|
Crypto.PubKey.ECC.P256
|
||||||
Crypto.PubKey.ECC.Types
|
Crypto.PubKey.ECC.Types
|
||||||
Crypto.PubKey.Ed25519
|
Crypto.PubKey.Ed25519
|
||||||
|
Crypto.PubKey.Ed448
|
||||||
Crypto.PubKey.RSA
|
Crypto.PubKey.RSA
|
||||||
Crypto.PubKey.RSA.PKCS15
|
Crypto.PubKey.RSA.PKCS15
|
||||||
Crypto.PubKey.RSA.Prim
|
Crypto.PubKey.RSA.Prim
|
||||||
@ -193,6 +195,7 @@ Library
|
|||||||
, cbits/cryptonite_cpu.c
|
, cbits/cryptonite_cpu.c
|
||||||
, cbits/curve25519/curve25519-donna.c
|
, cbits/curve25519/curve25519-donna.c
|
||||||
, cbits/ed25519/ed25519.c
|
, cbits/ed25519/ed25519.c
|
||||||
|
, cbits/ed448/x448.c
|
||||||
, cbits/p256/p256.c
|
, cbits/p256/p256.c
|
||||||
, cbits/p256/p256_ec.c
|
, cbits/p256/p256_ec.c
|
||||||
, cbits/cryptonite_blake2s.c
|
, cbits/cryptonite_blake2s.c
|
||||||
|
|||||||
23
tests/KAT_Ed448.hs
Normal file
23
tests/KAT_Ed448.hs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
module KAT_Ed448 ( tests ) where
|
||||||
|
|
||||||
|
import Crypto.Error
|
||||||
|
import qualified Crypto.PubKey.Ed448 as Ed448
|
||||||
|
import Data.ByteArray as B
|
||||||
|
import Imports
|
||||||
|
|
||||||
|
alicePrivate = throwCryptoError $ Ed448.secretKey ("\x9a\x8f\x49\x25\xd1\x51\x9f\x57\x75\xcf\x46\xb0\x4b\x58\x00\xd4\xee\x9e\xe8\xba\xe8\xbc\x55\x65\xd4\x98\xc2\x8d\xd9\xc9\xba\xf5\x74\xa9\x41\x97\x44\x89\x73\x91\x00\x63\x82\xa6\xf1\x27\xab\x1d\x9a\xc2\xd8\xc0\xa5\x98\x72\x6b" :: ByteString)
|
||||||
|
alicePublic = throwCryptoError $ Ed448.publicKey ("\x9b\x08\xf7\xcc\x31\xb7\xe3\xe6\x7d\x22\xd5\xae\xa1\x21\x07\x4a\x27\x3b\xd2\xb8\x3d\xe0\x9c\x63\xfa\xa7\x3d\x2c\x22\xc5\xd9\xbb\xc8\x36\x64\x72\x41\xd9\x53\xd4\x0c\x5b\x12\xda\x88\x12\x0d\x53\x17\x7f\x80\xe5\x32\xc4\x1f\xa0" :: ByteString)
|
||||||
|
bobPrivate = throwCryptoError $ Ed448.secretKey ("\x1c\x30\x6a\x7a\xc2\xa0\xe2\xe0\x99\x0b\x29\x44\x70\xcb\xa3\x39\xe6\x45\x37\x72\xb0\x75\x81\x1d\x8f\xad\x0d\x1d\x69\x27\xc1\x20\xbb\x5e\xe8\x97\x2b\x0d\x3e\x21\x37\x4c\x9c\x92\x1b\x09\xd1\xb0\x36\x6f\x10\xb6\x51\x73\x99\x2d" :: ByteString)
|
||||||
|
bobPublic = throwCryptoError $ Ed448.publicKey ("\x3e\xb7\xa8\x29\xb0\xcd\x20\xf5\xbc\xfc\x0b\x59\x9b\x6f\xec\xcf\x6d\xa4\x62\x71\x07\xbd\xb0\xd4\xf3\x45\xb4\x30\x27\xd8\xb9\x72\xfc\x3e\x34\xfb\x42\x32\xa1\x3c\xa7\x06\xdc\xb5\x7a\xec\x3d\xae\x07\xbd\xc1\xc6\x7b\xf3\x36\x09" :: ByteString)
|
||||||
|
aliceMultBob = "\x07\xff\xf4\x18\x1a\xc6\xcc\x95\xec\x1c\x16\xa9\x4a\x0f\x74\xd1\x2d\xa2\x32\xce\x40\xa7\x75\x52\x28\x1d\x28\x2b\xb6\x0c\x0b\x56\xfd\x24\x64\xc3\x35\x54\x39\x36\x52\x1c\x24\x40\x30\x85\xd5\x9a\x44\x9a\x50\x37\x51\x4a\x87\x9d" :: ByteString
|
||||||
|
|
||||||
|
katTests :: [TestTree]
|
||||||
|
katTests =
|
||||||
|
[ testCase "0" (aliceMultBob @=? B.convert (Ed448.dh alicePublic bobPrivate))
|
||||||
|
, testCase "1" (aliceMultBob @=? B.convert (Ed448.dh bobPublic alicePrivate))
|
||||||
|
]
|
||||||
|
|
||||||
|
tests = testGroup "Ed448"
|
||||||
|
[ testGroup "KATs" katTests
|
||||||
|
]
|
||||||
@ -14,6 +14,7 @@ import qualified KAT_HMAC
|
|||||||
import qualified KAT_HKDF
|
import qualified KAT_HKDF
|
||||||
import qualified KAT_PBKDF2
|
import qualified KAT_PBKDF2
|
||||||
import qualified KAT_Curve25519
|
import qualified KAT_Curve25519
|
||||||
|
import qualified KAT_Ed448
|
||||||
import qualified KAT_Ed25519
|
import qualified KAT_Ed25519
|
||||||
import qualified KAT_PubKey
|
import qualified KAT_PubKey
|
||||||
import qualified KAT_Scrypt
|
import qualified KAT_Scrypt
|
||||||
@ -37,6 +38,7 @@ tests = testGroup "cryptonite"
|
|||||||
, KAT_HMAC.tests
|
, KAT_HMAC.tests
|
||||||
]
|
]
|
||||||
, KAT_Curve25519.tests
|
, KAT_Curve25519.tests
|
||||||
|
, KAT_Ed448.tests
|
||||||
, KAT_Ed25519.tests
|
, KAT_Ed25519.tests
|
||||||
, KAT_PubKey.tests
|
, KAT_PubKey.tests
|
||||||
, testGroup "KDF"
|
, testGroup "KDF"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user