// test Ed25519 key generation and signature // // input is four 256-bit hex lines followed by the binary message data: // // sk (secret key) // pub (public key) // s1 (signature R value) // s2 (signature S value) // ... binary message data ... // // see data/ files and keytest.sh // #include #include #include #include #include "impl.h" #define SIZE 66 // 256-bit hex strings have length 64 + '\n' + '\0' #define BUFSIZE 4096 // for message data and hash input int main( void) { int test_decode = 1; // non-zero to make Point_encode() test Point_decode() char skstr[SIZE], pubstr[SIZE], s1str[SIZE], s2str[SIZE]; E sk, priv, pub, s1, s2, prefix; EE h; D w; printf( "CONSTANT_TIME = %i\n", CONSTANT_TIME); // read secret key, public key, signature R and S values // if( !fgets( skstr, SIZE, stdin) || !fgets( pubstr, SIZE, stdin) || !fgets( s1str, SIZE, stdin) || !fgets( s2str, SIZE, stdin) ) { fprintf( stderr, "key: insufficient input\n"); return 1; } convert_E( sk, skstr); SHA512( sk, M, h); print_E( "SHA512(sk)", h, MM); // private key comes from first M (32) bytes of the hash // for( int i = 0; i < M; ++i) priv[i] = h[i]; priv[0] &= 0xF8; // clear lowest 3 bits priv[M-1] &= 0x7F; // clear highest bit priv[M-1] |= 0x40; // set second highest bit print_E( "priv", priv, M); // can reduce the private key mod L // EtoC( w, priv); for( int i = N; i < NN; ++i) w[i] = 0; mod_L( priv, w); print_E( "priv", priv, M); // prefix is the last M bytes of the hash // for( int i = 0; i < M; ++i) prefix[i] = h[i+M]; print_E( "prefix", prefix, M); // public value, A = priv*G // Point A; Point_mul( &A, priv, &G); print( "A.x", A.x, N); print( "A.y", A.y, N); // print( "A.z", A.z, N); print( "A.t", A.t, N); print_P( "A", &A); E Ae; Point_encode( Ae, &A, test_decode); print_E( " Ae", Ae, M); convert_E( pub, pubstr); print_E( "pub", pub, M); printf( "pub key "); if( memcmp( Ae, pub, sizeof(Ae)) == 0) printf( "pass\n"); else printf( "fail\n"); // read message data and compute signature // UC msg[BUFSIZE], buf[BUFSIZE]; int msglen, len; msglen = fread( msg, 1, BUFSIZE, stdin); printf( "msglen = %i\n", msglen); // r = SHA512( prefix || msg) // memcpy( buf, prefix, M); memcpy( buf+M, msg, msglen); len = M + msglen; SHA512( buf, len, h); print_E( "SHA512(prefix||msg)", h, MM); // convert hash to D value and do mod L // E r; EEtoD( w, h); print( "w", w, NN); mod_L( r, w); print_E( "r", r, M); // R = r*G // Point R; Point_mul( &R, r, &G); print( "R.x", R.x, N); print( "R.y", R.y, N); E Re; Point_encode( Re, &R, test_decode); print_E( "Re", Re, M); convert_E( s1, s1str); print_E( "s1", s1, M); printf( "s1 "); if( memcmp( Re, s1, sizeof(Re)) == 0) printf( "pass\n"); else printf( "fail\n"); // k = SHA512( R || A || msg) // memcpy( buf, Re, M); memcpy( buf+M, Ae, M); memcpy( buf+2*M, msg, msglen); len = 2*M + msglen; SHA512( buf, len, h); print_E( "SHA512(R||A||msg)", h, MM); // convert hash to D value and do mod L // E k; EEtoD( w, h); print( "w", w, NN); mod_L( k, w); print_E( "k", k, M); // sign // E s; sign( s, r, k, priv); print_E( " s", s, M); convert_E( s2, s2str); print_E( "s2", s2, M); printf( "s2 "); if( memcmp( s, s2, sizeof(s)) == 0) printf( "pass\n"); else printf( "fail\n"); // verify // int v = verify( s, &G, &R, k, &A); printf( "verify "); if( v) printf( "pass\n"); else printf( "fail\n"); return 0; }