add Ed25519 ECC signature algorithm

The Ed25519 sources were taken from the crypto_sign/ed25519/ref
subdirectory of the SUPERCOP benchmarking tool.
The Ed25519 software is in the public domain.

Contributors (in alphabetical order)
    Daniel J. Bernstein, University of Illinois at Chicago
    Niels Duif, Technische Universiteit Eindhoven
    Tanja Lange, Technische Universiteit Eindhoven
    Peter Schwabe, National Taiwan University
    Bo-Yin Yang, Academia Sinica
This commit is contained in:
ac-stef
2016-08-26 14:28:53 +02:00
parent b080d634fc
commit 806e0f4f7e
4 changed files with 2020 additions and 35 deletions
+102 -21
View File
@@ -227,6 +227,7 @@ void sha512(uchar *hash, const uchar *msg, int msglen)
#undef SHA512ROUND
#ifndef STANDALONE
#ifdef _DEBUG
COMMANDF(sha512, "s", (char *msg) // SHA512 debug command
{
uchar hash[SHA512SIZE];
@@ -245,7 +246,7 @@ COMMANDF(tiger, "s", (char *msg) // tiger debug command
conoutf("%s", erg);
});
#endif
#endif
////////////////////////// crypto rand (Mersenne twister) ////////////////////////////////////////
@@ -357,7 +358,7 @@ void entropy_add_block(const uchar *s, int len)
for( ; len > 0; s += 128, len -= 128)
{
int bl = min(len, 128);
xor_block(entpool + rnd(ENTPOOLSIZE / 8 - 16) * 8, s, bl);
xor_block(entpool + rnd(ENTPOOLSIZE / 8 - 16) * 8, s, bl); // use pseudorandom to mix entropy into the pool in a hard to predict fashion
mix_block(entpool + rnd(ENTPOOLSIZE - bl), s, bl);
}
}
@@ -377,7 +378,7 @@ void entropy_get(uchar *buf, int len)
#ifndef STANDALONE
/////////////////////////////////////////////// key derivation function ////////////////////////////////////////////////////////////////////////
// * basically a hash function that delivers keylen bytes calculated from pass and salt
// * but uses a lot of memory and a quite complex algorithm, to make brute-force offline-attacks on short passwords as hard as possible
// * but uses a lot of memory and a quite complex algorithm, to make brute-force offline-attacks on short passwords as hard as possible (even if someone uses fpgas)
// * last line of defense against "evil little brothers"
void passphrase2key(const char *pass, const uchar *salt, int saltlen, uchar *key, int keylen, int *iterations, int maxtime, int memusage)
@@ -436,25 +437,106 @@ conoutf("passphrase2key: %d ms, %d rounds, %d bytes used", watch.elapsed(), roun
}
#endif
#ifndef STANDALONE
COMMANDF(passkey, "ssiii", (const char *pass, const char *salt, int *keylen, int *rounds, int *memusage)
{
uchar buf[*keylen];
passphrase2key(pass, (const uchar *)salt, strlen(salt), buf, *keylen, rounds, 1000, *memusage);
defformatstring(erg)("passkey (%d rounds): ", *rounds);
loopi(*keylen) concatformatstring(erg, "%02x", buf[i]);
conoutf("%s", erg);
});
/////////////////////////////////////////////// Ed25519: high-speed high-security signatures //////////////////////////////////////////////////////
COMMANDF(entropy, "", ()
#include "crypto_tools.h"
void ed25519_pubkey_from_private(uchar *pubkey, const uchar *privkey)
{
uchar buf[32];
entropy_get(buf, 32);
defformatstring(erg)("entropy: ");
loopi(32) concatformatstring(erg, "%02x", buf[i]);
conoutf("%s", erg);
});
#endif
unsigned char az[64];
sc25519 scsk;
ge25519 gepk;
sha512(az, privkey, 32);
az[0] &= 248;
az[31] &= 127;
az[31] |= 64;
sc25519_from32bytes(&scsk,az);
ge25519_scalarmult_base(&gepk, &scsk);
ge25519_pack(pubkey, &gepk);
}
void privkey_from_prepriv(unsigned char *privkey, const unsigned char *prepriv, int preprivlen, unsigned char *privpriv = NULL) // derive private key from even more secret bulk of entropy
{
uchar temp[SHA512SIZE], pub[32], testpriv[32];
sha512(temp, prepriv, preprivlen);
int esc, minesc = 32, minescpos = 0;
loopi(33)
{ // find privte key with the public key with the least getint() escape codes (yes, that decreases the keyrange. sue me.)
ed25519_pubkey_from_private(testpriv, temp + i);
ed25519_pubkey_from_private(pub, testpriv);
esc = 0;
loopj(32) if((pub[j] & 0xfe) == 0x80) esc++;
if(esc < minesc) { minesc = esc; minescpos = i; }
if(esc == 0) break;
}
ed25519_pubkey_from_private(privkey, temp + minescpos); // (the resulting private key is actually itself a public key of a private derived from prepriv)
if(privpriv) memcpy(privpriv, temp + minescpos, 32);
}
void ed25519_sign(uchar *sm, int *smlen, const uchar *m, int mlen, const uchar *sk)
{ // sk: 32-byte private key + 32-byte public key
uchar pk[32], az[64], nonce[64], hram[64];
sc25519 sck, scs, scsk;
ge25519 ger;
memmove(pk, sk + 32, 32); // pk: 32-byte public key A
sha512(az, sk, 32);
az[0] &= 248;
az[31] &= 127;
az[31] |= 64; // az: 32-byte scalar a, 32-byte randomizer z
if(smlen) *smlen = mlen + 64;
memmove(sm + 64, m, mlen); // need memmove here: m and sm may overlap
memmove(sm + 32, az + 32, 32); // sm: 32-byte uninit, 32-byte z, mlen-byte m
sha512(nonce, sm + 32, mlen + 32); // nonce: 64-byte H(z,m)
sc25519_from64bytes(&sck, nonce);
ge25519_scalarmult_base(&ger, &sck);
ge25519_pack(sm, &ger); // sm: 32-byte R, 32-byte z, mlen-byte m
memmove(sm + 32, pk, 32); // sm: 32-byte R, 32-byte A, mlen-byte m
sha512(hram, sm, mlen + 64); // hram: 64-byte H(R,A,m)
sc25519_from64bytes(&scs, hram);
sc25519_from32bytes(&scsk, az);
sc25519_mul(&scs, &scs, &scsk);
sc25519_add(&scs, &scs, &sck); // scs: S = nonce + H(R,A,m)a
sc25519_to32bytes(sm + 32, &scs); // sm: 32-byte R, 32-byte S, mlen-byte m
}
uchar *ed25519_sign_check(uchar *sm, int smlen, const uchar *pk)
{
uchar scopy[32], hram[64], rcheck[32];
ge25519 get1, get2;
sc25519 schram, scs;
if(smlen < 64 || (sm[63] & 224) || ge25519_unpackneg_vartime(&get1, pk)) return NULL; // frame error
memmove(scopy, sm + 32, 32);
sc25519_from32bytes(&scs, sm + 32);
memmove(sm + 32, pk, 32);
sha512(hram, sm, smlen);
sc25519_from64bytes(&schram, hram);
ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs);
ge25519_pack(rcheck, &get2);
memmove(sm + 32, scopy, 32); // restore sm
return memcmp(rcheck, sm, 32) ? NULL : sm + 64;
}
/////////////////// misc helper functions ////////////////////////////////////////////////////////////////
@@ -487,4 +569,3 @@ const char *genpwdhash(const char *name, const char *pwd, int salt)