Initial Commit

master
Harald Wolff 2021-04-08 22:36:08 +02:00
commit 75a6883d18
15 changed files with 1046 additions and 0 deletions

8
.gitignore vendored 100644
View File

@ -0,0 +1,8 @@
*.o
*.so
*.a
*.dylib
*.dll
*.exe
curvecli
.vscode

18
Makefile 100644
View File

@ -0,0 +1,18 @@
SOURCES=curve.c curves.c sha256.c lsag.c utils.c mpztools.c rand.c
OBJECTS=$(SOURCES:%.c=src/%.o)
CFLAGS=-Iinclude -Lgmp -fPIC -ggdb
all:
clean:
rm -f *.so *.a src/*.o
curvecli: libcurve.a
gcc -o curvecli -L. src/curvecli.c $(CFLAGS) -lgmp libcurve.a
libcurve.so: $(OBJECTS)
gcc -o libcurve.so -shared $(OBJECTS)
libcurve.a: $(OBJECTS)
ar cm libcurve.a $(OBJECTS)

71
include/curve.h 100644
View File

@ -0,0 +1,71 @@
#pragma once
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <gmp.h>
#define assert_zero(__c__) { if ((__c__)!=0) { printf("assert_zero: " __FILE__ "\n"); return -1; }; }
//#define assert_zero(__c__) __c__
#define DUMP_MPZ(__prefix__, __mpz__) { char t[128]; mpz_get_str(t, 16, __mpz__); printf(__prefix__ ": %s\n", t); };
struct ec_point
{
mpz_t x, y;
};
typedef struct ec_point ec_point_t[1];
/***
* Define a curve of type y*y = x*x*x + a*x + b
***/
struct curve
{
mpz_t p;
mpz_t a, b;
mpz_t n;
int32_t h;
ec_point_t G;
int bitwidth;
};
typedef struct curve curve_t[1];
int named_curves_count;
int32_t curve_create_from_name(char *curve_name, curve_t curve);
int32_t curve_create(curve_t curve, mpz_t p, mpz_t a, mpz_t b, mpz_t n, int32_t h, mpz_t xg, mpz_t yg);
int32_t curve_destroy(curve_t curve);
int32_t curve_point_init(ec_point_t point);
int32_t curve_point_init_set(ec_point_t point, ec_point_t src);
int32_t curve_point_init_set_xy(ec_point_t point, mpz_t x, mpz_t y);
int32_t curve_point_clear(ec_point_t point);
int32_t curve_point_is_valid(ec_point_t point, curve_t curve);
int32_t curve_point_is_infinity(ec_point_t point);
int32_t curve_point_add(ec_point_t dst, ec_point_t p1, ec_point_t p2, curve_t curve);
int32_t curve_point_mul(ec_point_t dst, ec_point_t p1, mpz_t i, curve_t curve);
int32_t curve_map_to_curve( ec_point_t dst, mpz_t u, curve_t curve);
int32_t curve_hash_to_point( ec_point_t dst, char *message, int len, curve_t curve);
int32_t curve_get_generator( ec_point_t dst, curve_t curve );
static inline void curve_point_set(ec_point_t dst, ec_point_t src) {
mpz_set( dst->x, src->x );
mpz_set( dst->y, src->y );
};
static inline int32_t curve_point_equals(ec_point_t p1, ec_point_t p2) { return (mpz_cmp(p1->x, p2->x) == 0) && (mpz_cmp(p1->y, p2->y) == 0); }
void sha256(char *message, int len, char *hash);
void sha256_curve_points(ec_point_t* points, int points_length, curve_t curve, char *hash);
static inline void __tools_ec_point_cleanup(ec_point_t *p) { curve_point_clear( *p ); }
#define ec_point_t_cleanup(name) ec_point_t name __attribute__ (( __cleanup__(__tools_ec_point_cleanup))); curve_point_init( name );

13
include/lsag.h 100644
View File

@ -0,0 +1,13 @@
#pragma once
#include <curve.h>
#include <mpztools.h>
int32_t lsag_sign (char *message, int mlen, mpz_t signKey, ec_point_t* public_keys, int public_keys_len, curve_t curve, mpz_t out_C0, ec_point_t out_Y, mpz_t* out_s);
int32_t lsag_verify (char *message, int mlen, ec_point_t* public_keys, int public_keys_len, curve_t curve, mpz_t C0, ec_point_t Y, mpz_t* s);
int32_t lsag_hash_one(char *pkHash, ec_point_t y, char *msgHash, ec_point_t a, ec_point_t b, curve_t curve, mpz_t out_H1);
char *print_hex(char *p, int len);

36
include/mpztools.h 100644
View File

@ -0,0 +1,36 @@
#pragma once
#include <gmp.h>
struct mpz_field
{
int length;
mpz_t values[0];
};
typedef struct mpz_field mpz_field_t;
#define mpz_field_value(f, i) (f->values[i])
static inline void __tools_mpz_cleanup(mpz_t *mpz){
// printf("__tools_mpz_clenaup(%x)\n", mpz);
mpz_clear(*mpz);
}
void mpz_random_mod( mpz_t rop, mpz_t p);
char* mpz_to_string(mpz_t i, int base);
#define mpz_cleanup(name) mpz_t name __attribute__ (( __cleanup__(__tools_mpz_cleanup))); mpz_init( name );
#define mpz_t_cleanup_set(name, value) mpz_t name __attribute__ (( __cleanup__(__tools_mpz_cleanup))); mpz_init_set( name, value );
mpz_t* mpz_field_init(int length);
void mpz_field_clear(mpz_t *field);
static inline void __tools_mpz_field_cleanup(mpz_t **f){
mpz_field_clear(*f);
}
#define mpz_field_cleanup(name, length) mpz_t* name __attribute__ (( __cleanup__(__tools_mpz_field_cleanup))) = mpz_field_init( length );

10
include/rand.h 100644
View File

@ -0,0 +1,10 @@
#pragma once
void rand_init_auto();
void rand_init_seeded(long seed);
void rand_get_bytes(char *dst, int length);
void sha256(char *message, int len, char *hash);

35
include/sha256.h 100644
View File

@ -0,0 +1,35 @@
/*********************************************************************
* Filename: sha256.h
* Author: Brad Conte (brad AT bradconte.com) https://github.com/B-Con/crypto-algorithms.git
* Copyright:
* Disclaimer: This code is presented "as is" without any guarantees.
* Details: Defines the API for the corresponding SHA1 implementation.
*********************************************************************/
#ifndef SHA256_H
#define SHA256_H
/*************************** HEADER FILES ***************************/
#include <stddef.h>
#include <stdint.h>
/****************************** MACROS ******************************/
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
/**************************** DATA TYPES ****************************/
typedef uint8_t BYTE; // 8-bit byte
typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines
typedef struct {
BYTE data[64];
WORD datalen;
unsigned long long bitlen;
WORD state[8];
} SHA256_CTX;
/*********************** FUNCTION DECLARATIONS **********************/
void sha256_init(SHA256_CTX *ctx);
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len);
void sha256_final(SHA256_CTX *ctx, BYTE hash[]);
#endif // SHA256_H

229
src/curve.c 100644
View File

@ -0,0 +1,229 @@
#include <curve.h>
#include <sha256.h>
#include <mpztools.h>
int __ec_point_size = sizeof(struct ec_point);
int32_t curve_create(curve_t curve, mpz_t p, mpz_t a, mpz_t b, mpz_t n, int32_t h, mpz_t xg, mpz_t yg)
{
mpz_init_set( curve->p, p);
mpz_init_set( curve->a, a);
mpz_init_set( curve->b, b);
mpz_init_set( curve->n, n);
curve->h = h;
curve->bitwidth = (mpz_sizeinbase( p , 2 ) + 7) & 0xFFFFFFF8;
curve_point_init_set_xy(curve->G, xg, yg);
if (curve->G)
return 0;
mpz_clear( curve->n );
mpz_clear( curve->b );
mpz_clear( curve->a );
mpz_clear( curve->p );
return -1;
};
int32_t curve_destroy(curve_t curve)
{
if (curve)
{
if (!curve_point_clear( curve->G ))
{
mpz_clear( curve->n );
mpz_clear( curve->b );
mpz_clear( curve->a );
mpz_clear( curve->p );
return 0;
}
}
return -1;
}
int32_t curve_get_generator( ec_point_t dst, curve_t curve )
{
mpz_set( dst->x, curve->G->x );
mpz_set( dst->y, curve->G->y );
}
int32_t curve_point_init(ec_point_t point)
{
mpz_init(point->x);
mpz_init(point->y);
return 0;
}
int32_t curve_point_init_set(ec_point_t point, ec_point_t src)
{
mpz_init_set(point->x, src->x);
mpz_init_set(point->y, src->y);
return 0;
}
int32_t curve_point_init_set_xy(ec_point_t point, mpz_t x, mpz_t y)
{
mpz_init_set(point->x, x);
mpz_init_set(point->y, y);
return 0;
}
int32_t curve_point_clear(ec_point_t point)
{
mpz_clear(point->x);
mpz_clear(point->y);
return 0;
}
int32_t curve_point_is_valid(ec_point_t point, curve_t curve)
{
mpz_t yy, yy2;
mpz_inits( yy, yy2, NULL );
mpz_powm_ui( yy, point->x, 3, curve->p );
mpz_addmul( yy, curve->a, point->x );
mpz_add( yy, yy, curve->b );
mpz_mod( yy, yy, curve->p );
mpz_powm_ui( yy2, point->y, 2, curve->p );
int result = mpz_cmp( yy, yy2 ) == 0;
mpz_clears( yy, yy2, NULL );
return result;
}
int32_t curve_point_is_infinity(ec_point_t point)
{
return (mpz_cmp_ui(point->x, 0) == 0) && (mpz_cmp_ui(point->y, 0) == 0);
}
int32_t curve_point_add(ec_point_t dst, ec_point_t p1, ec_point_t p2, curve_t curve)
{
int xeq, yeq;
xeq = mpz_cmp(p1->x, p2->x) == 0;
yeq = mpz_cmp(p1->y, p2->y) == 0;
if (xeq && !yeq)
{
mpz_set_ui( dst->x, 0);
mpz_set_ui( dst->y, 0);
return 0;
} else {
int result = -1;
mpz_t lambda;
mpz_t divlambda;
ec_point_t _p1;
ec_point_t _p2;
curve_point_init_set( _p1, p1 );
curve_point_init_set( _p2, p2 );
mpz_inits( lambda, divlambda, NULL );
if (xeq)
{
mpz_powm_ui(lambda, _p1->x, 2, curve->p);
mpz_mul_ui(lambda, lambda, 3);
mpz_add(lambda, lambda, curve->a);
mpz_mul_ui(divlambda, _p1->y, 2);
} else {
mpz_sub( lambda, _p2->y, _p1->y);
mpz_sub( divlambda, _p2->x, _p1->x);
}
mpz_mod( lambda, lambda, curve->p );
mpz_mod( divlambda, divlambda, curve->p );
if (mpz_invert( divlambda, divlambda, curve->p )==0)
{
printf("%s: no inverse found\n", __func__);
} else {
mpz_mul( lambda, lambda, divlambda );
mpz_mod( lambda, lambda, curve->p );
mpz_powm_ui( dst->x, lambda, 2, curve->p );
mpz_sub( dst->x, dst->x, _p1->x );
mpz_sub( dst->x, dst->x, _p2->x );
mpz_mod( dst->x, dst->x, curve->p );
mpz_sub( dst->y, _p1->x, dst->x );
mpz_mul( dst->y, dst->y, lambda );
mpz_sub( dst->y, dst->y, _p1->y );
mpz_mod( dst->y, dst->y, curve->p );
result = 0;
}
mpz_clears( lambda, divlambda, NULL );
curve_point_clear(_p1);
curve_point_clear(_p2);
return result;
}
return -1;
}
int32_t curve_point_mul(ec_point_t dst, ec_point_t p1, mpz_t i, curve_t curve)
{
if (curve_point_is_infinity(p1) || (mpz_cmp_ui(p1->y, 0)==0))
{
mpz_set_ui( dst->x, 0);
mpz_set_ui( dst->y, 0);
return 0;
}
int firstOne = mpz_scan1( i, 0 );
int size = (mpz_size( i ) * sizeof(mp_limb_t)) << 3;
ec_point_t p;
curve_point_init_set(p, p1);
int n=0;
for (;n<firstOne;n++)
curve_point_add( p, p, p, curve );
n++;
curve_point_set( dst, p );
for (;n<size;n++)
{
curve_point_add( p, p, p, curve );
if (mpz_tstbit(i, n))
curve_point_add( dst, dst, p, curve );
}
curve_point_clear(p);
return 0;
}
int32_t curve_map_to_curve( ec_point_t dst, mpz_t u, curve_t curve)
{
mpz_t_cleanup_set(u2, u);
mpz_mod( u2, u2, curve->n );
curve_point_mul( dst, curve->G, u2, curve );
return 0;
}
int32_t curve_hash_to_point( ec_point_t dst, char *message, int len, curve_t curve)
{
char hash[32];
SHA256_CTX sha256;
sha256_init(&sha256);
sha256_update(&sha256, message, len );
sha256_final(&sha256, hash);
mpz_cleanup(k);
mpz_import(k, 32, -1, 1, -1, 0, hash);
mpz_mul_ui( k, k, 0xdeadbeef );
mpz_mod( k, k, curve->n);
return curve_map_to_curve( dst, k, curve );
}

81
src/curvecli.c 100644
View File

@ -0,0 +1,81 @@
#include <stdio.h>
#include <curve.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <rand.h>
#include <lsag.h>
#include <mpztools.h>
char curvename[32];
void test_lsag(int ringsize)
{
curve_t secp256k1;
curve_create_from_name("secp256k1", secp256k1);
mpz_t privKeys[ringsize];
ec_point_t pubKeys[ringsize];
for (int i=0; i<ringsize; i++)
{
mpz_init( privKeys[i] );
mpz_random_mod( privKeys[i], secp256k1->n );
curve_point_init( pubKeys[i] );
curve_point_mul( pubKeys[i], secp256k1->G, privKeys[i], secp256k1 );
}
printf("LSAG: created ring of %i keys:\n", ringsize);
for (int i=0; i<ringsize; i++)
{
printf("#%06d ", i);
printf("%s -> ", mpz_to_string(privKeys[i], 16));
printf("%s / ", mpz_to_string(pubKeys[i]->x, 16));
printf("%s\n", mpz_to_string(pubKeys[i]->y, 16));
}
char *message = "Hallo Welt!";
int msglen = strlen(message);
mpz_cleanup( C0 );
ec_point_t_cleanup( Y );
mpz_field_cleanup( S, ringsize );
printf("LSAG: signing ring of %i keys:\n", ringsize);
for (int i=0; i<ringsize; i++)
{
printf("signing #%i\n",i );
lsag_sign(message, msglen, privKeys[i], pubKeys, ringsize, secp256k1, C0, Y, S);
printf("verifying #%i\n", i );
int verified = lsag_verify( message, msglen, pubKeys, ringsize, secp256k1, C0, Y, S);
printf("verfication: %i\n", verified);
}
for (int i=0; i<ringsize; i++)
{
mpz_clear( privKeys[i] );
curve_point_clear( pubKeys[i] );
}
curve_destroy( secp256k1 );
}
int main(int argc, char *argv[])
{
test_lsag(10);
test_lsag(100);
test_lsag(1000);
}

52
src/curves.c 100644
View File

@ -0,0 +1,52 @@
#include <curve.h>
#include <string.h>
#include <stdio.h>
struct named_curve
{
char *name;
char *p;
char *a,*b,*n;
int h;
char *gx,*gy;
};
struct named_curve named_curves[] = {
{
"secp256k1",
"00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
"00",
"07",
"00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
1,
"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"
},
};
int named_curves_count = sizeof(named_curves) / sizeof(struct named_curve);
int32_t curve_create_from_name(char *curve_name, curve_t curve)
{
for (int i=0; i<named_curves_count; i++)
{
if (!strcmp(curve_name, named_curves[i].name))
{
mpz_t p,a,b,n,gx,gy;
mpz_init_set_str(p, named_curves[i].p, 16);
mpz_init_set_str(a, named_curves[i].a, 16);
mpz_init_set_str(b, named_curves[i].b, 16);
mpz_init_set_str(n, named_curves[i].n, 16);
mpz_init_set_str(gx, named_curves[i].gx, 16);
mpz_init_set_str(gy, named_curves[i].gy, 16);
int success = curve_create(curve, p, a, b, n, named_curves[i].h, gx, gy);
mpz_clears(p, a, b, n, gx, gy, NULL);
return success;
}
}
return -1;
}

173
src/lsag.c 100644
View File

@ -0,0 +1,173 @@
#include <lsag.h>
#include <mpztools.h>
#include <sha256.h>
int32_t lsag_sign (char *message, int mlen, mpz_t signKey, ec_point_t* public_keys, int public_keys_len, curve_t curve, mpz_t out_C0, ec_point_t out_Y, mpz_t* out_s)
{
ec_point_t signPubKey;
int signKeyIndex = -1;
curve_point_init( signPubKey );
curve_point_mul( signPubKey, curve->G, signKey, curve );
for (int n=0; n<public_keys_len; n++)
{
if (curve_point_equals(signPubKey, public_keys[n]))
{
signKeyIndex = n;
break;
}
}
if (signKeyIndex < 0)
{
printf("SignKey not found!\n");
return -1;
}
// printf("signing key is %i\n", signKeyIndex);
mpz_field_cleanup( c, public_keys_len );
mpz_cleanup( u );
char pkHash[32];
char msgHash[32];
sha256( message, mlen, msgHash );
sha256_curve_points( public_keys, public_keys_len, curve, pkHash );
// printf("msgHash: %s\n", print_hex(msgHash, 32));
// printf("pkHash: %s\n", print_hex(pkHash, 32));
ec_point_t_cleanup(H);
curve_hash_to_point( H, pkHash, 32, curve );
curve_point_mul( out_Y, H, signKey, curve );
mpz_random_mod( u, curve->n );
ec_point_t_cleanup(a);
ec_point_t_cleanup(b);
ec_point_t_cleanup(t);
curve_point_mul( a, curve->G, u, curve );
curve_point_mul( b, H, u, curve );
lsag_hash_one(pkHash, out_Y, msgHash, a, b, curve, c[ (signKeyIndex+1) % public_keys_len ] );
for (int i=(signKeyIndex+1) % public_keys_len ; i != signKeyIndex ; i = (i+1)%public_keys_len )
{
mpz_random_mod( out_s[i], curve->n );
curve_point_mul( a, curve->G, out_s[i], curve );
curve_point_mul( t, public_keys[i], c[i], curve );
curve_point_add( a, a, t, curve );
curve_point_mul( b, H, out_s[i], curve );
curve_point_mul( t, out_Y, c[i], curve );
curve_point_add( b, b, t, curve );
lsag_hash_one(pkHash, out_Y, msgHash, a, b, curve, c[ (i+1) % public_keys_len ] );
// printf("sign: c[%i] = %s\n", i, mpz_to_string(c[i], 16));
// printf("sign: s[%i] = %s\n", i, mpz_to_string(out_s[i], 16));
}
mpz_set( out_s[signKeyIndex], u );
mpz_submul( out_s[signKeyIndex], signKey, c[signKeyIndex] );
mpz_mod( out_s[signKeyIndex], out_s[signKeyIndex], curve->n );
// printf("sign: c[%i] = %s\n", signKeyIndex, mpz_to_string(c[signKeyIndex], 16));
// printf("sign: s[%i] = %s\n", signKeyIndex, mpz_to_string(out_s[signKeyIndex], 16));
mpz_set( out_C0, c[0] );
return 0;
}
int32_t lsag_verify (char *message, int mlen, ec_point_t* public_keys, int public_keys_len, curve_t curve, mpz_t C0, ec_point_t Y, mpz_t* s)
{
// printf(" --- lsag_verify(): start --- \n");
char msgHash[32];
char pkHash[32];
sha256( message, mlen, msgHash );
sha256_curve_points( public_keys, public_keys_len, curve, pkHash );
// printf("msgHash: %s\n", print_hex(msgHash, 32));
// printf("pkHash: %s\n", print_hex(pkHash, 32));
mpz_field_cleanup( c, public_keys_len + 1 );
mpz_set( c[0], C0 );
// printf(" --- lsag_verify(): mark I --- \n");
ec_point_t_cleanup(H);
// printf(" --- lsag_verify(): mark Ib --- \n");
curve_hash_to_point( H, pkHash, 32, curve );
ec_point_t_cleanup(a);
ec_point_t_cleanup(b);
ec_point_t_cleanup(t);
// printf(" --- lsag_verify(): mark II --- \n");
for (int i=0 ; i < public_keys_len ; i++ )
{
// printf("sign: c[%i] = %s\n", i, mpz_to_string(c[i], 16));
// printf("sign: s[%i] = %s\n", i, mpz_to_string(s[i], 16));
curve_point_mul( a, curve->G, s[i], curve );
curve_point_mul( t, public_keys[i], c[i], curve );
curve_point_add( a, a, t, curve );
curve_point_mul( b, H, s[i], curve );
curve_point_mul( t, Y, c[i], curve );
curve_point_add( b, b, t, curve );
lsag_hash_one(pkHash, Y, msgHash, a, b, curve, c[ i+1 ] );
}
return mpz_cmp(c[0], c[public_keys_len]) == 0;
}
int32_t lsag_hash_one(char *pkHash, ec_point_t y, char *msgHash, ec_point_t a, ec_point_t b, curve_t curve, mpz_t out_H1)
{
char h1[32];
int keysize = curve->bitwidth >> 3;
char tv[keysize];
SHA256_CTX sha;
sha256_init( &sha );
sha256_update( &sha, pkHash, 32 );
sha256_update( &sha, msgHash, 32 );
memset( tv, 0x00, keysize );
mpz_export( tv, NULL, -1, 1, -1, 0, y->x );
sha256_update( &sha, tv, keysize);
memset( tv, 0x00, keysize );
mpz_export( tv, NULL, -1, 1, -1, 0, y->y );
sha256_update( &sha, tv, keysize);
memset( tv, 0x00, keysize );
mpz_export( tv, NULL, -1, 1, -1, 0, a->x );
sha256_update( &sha, tv, keysize);
memset( tv, 0x00, keysize );
mpz_export( tv, NULL, -1, 1, -1, 0, a->y );
sha256_update( &sha, tv, keysize);
memset( tv, 0x00, keysize );
mpz_export( tv, NULL, -1, 1, -1, 0, b->x );
sha256_update( &sha, tv, keysize);
memset( tv, 0x00, keysize );
mpz_export( tv, NULL, -1, 1, -1, 0, b->y );
sha256_update( &sha, tv, keysize);
sha256_final( &sha, h1 );
mpz_import( out_H1, 32, -1, 1, -1, 0, h1 );
mpz_mul_ui( out_H1, out_H1, 0xdeadbeef );
mpz_mod( out_H1, out_H1, curve->p );
return 0;
}

50
src/mpztools.c 100644
View File

@ -0,0 +1,50 @@
#include <mpztools.h>
#include <stdlib.h>
#include <stdio.h>
#include <rand.h>
#include <gmp.h>
mpz_t* mpz_field_init(int length)
{
int *l = malloc( sizeof(int) + (sizeof(mpz_t) * length));
*l = length;
mpz_t *f = (mpz_t*) (++l);
for (int n=0;n<length;n++)
mpz_init(f[n]);
return f;
}
void mpz_field_clear(mpz_t *f)
{
int *l = ((int*)f)-1;
for (int n=0;n<*l;n++)
mpz_clear(f[n]);
free(l);
}
void mpz_random_mod( mpz_t rop, mpz_t p)
{
int bytesize = (mpz_sizeinbase( p, 2 )+7) >> 3;
char b[ bytesize * 2 ];
rand_get_bytes( b, bytesize * 2 );
mpz_import( rop, bytesize * 2, -1, 1, -1, 0, b );
mpz_mod( rop, rop, p );
}
char* mpz_to_string(mpz_t i, int base)
{
static char *s = NULL;
static int slen = 0;
int neededsize = mpz_sizeinbase(i, base) + 2;
if (slen < neededsize)
{
if (s)
free(s);
s = malloc(neededsize);
slen = neededsize;
}
mpz_get_str(s, base, i );
return s;
}

52
src/rand.c 100644
View File

@ -0,0 +1,52 @@
#include <rand.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sha256.h>
char __rand_state[32];
int __rand_seeded = 0;
void rand_init_auto()
{
int f = open("/dev/random", O_RDONLY);
read( f, __rand_state, 32 );
close(f);
__rand_seeded = 1;
}
void rand_init_seeded(long seed)
{
memset( __rand_state, 0x00, 32 );
memcpy(__rand_state, &seed, 8 );
sha256(__rand_state, 32, __rand_state);
sha256(__rand_state, 32, __rand_state);
sha256(__rand_state, 32, __rand_state);
sha256(__rand_state, 32, __rand_state);
__rand_seeded = 1;
}
void rand_get_bytes(char *dst, int length)
{
if (!__rand_seeded)
rand_init_auto();
while (length > 0)
{
int l = length > 32 ? 32 : length;
sha256(__rand_state, 32, __rand_state);
memcpy( dst, __rand_state, l);
length -= l;
dst += l;
}
sha256(__rand_state, 32, __rand_state);
}

158
src/sha256.c 100644
View File

@ -0,0 +1,158 @@
/*********************************************************************
* Filename: sha256.c
* Author: Brad Conte (brad AT bradconte.com) https://github.com/B-Con/crypto-algorithms.git
* Copyright:
* Disclaimer: This code is presented "as is" without any guarantees.
* Details: Implementation of the SHA-256 hashing algorithm.
SHA-256 is one of the three algorithms in the SHA2
specification. The others, SHA-384 and SHA-512, are not
offered in this implementation.
Algorithm specification can be found here:
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
This implementation uses little endian byte order.
*********************************************************************/
/*************************** HEADER FILES ***************************/
#include <stdlib.h>
#include <memory.h>
#include "sha256.h"
/****************************** MACROS ******************************/
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
/**************************** VARIABLES *****************************/
static const WORD k[64] = {
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};
/*********************** FUNCTION DEFINITIONS ***********************/
void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
{
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
for ( ; i < 64; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->state[7];
for (i = 0; i < 64; ++i) {
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
t2 = EP0(a) + MAJ(a,b,c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}
void sha256_init(SHA256_CTX *ctx)
{
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
{
WORD i;
for (i = 0; i < len; ++i) {
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
sha256_transform(ctx, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
void sha256_final(SHA256_CTX *ctx, BYTE hash[])
{
WORD i;
i = ctx->datalen;
// Pad whatever data is left in the buffer.
if (ctx->datalen < 56) {
ctx->data[i++] = 0x80;
while (i < 56)
ctx->data[i++] = 0x00;
}
else {
ctx->data[i++] = 0x80;
while (i < 64)
ctx->data[i++] = 0x00;
sha256_transform(ctx, ctx->data);
memset(ctx->data, 0, 56);
}
// Append to the padding the total message's length in bits and transform.
ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = ctx->bitlen;
ctx->data[62] = ctx->bitlen >> 8;
ctx->data[61] = ctx->bitlen >> 16;
ctx->data[60] = ctx->bitlen >> 24;
ctx->data[59] = ctx->bitlen >> 32;
ctx->data[58] = ctx->bitlen >> 40;
ctx->data[57] = ctx->bitlen >> 48;
ctx->data[56] = ctx->bitlen >> 56;
sha256_transform(ctx, ctx->data);
// Since this implementation uses little endian byte ordering and SHA uses big endian,
// reverse all the bytes when copying the final state to the output hash.
for (i = 0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
}
}

60
src/utils.c 100644
View File

@ -0,0 +1,60 @@
#include <curve.h>
#include <sha256.h>
char hexdigits[] = "0123456789ABCDEF";
void sha256(char *message, int len, char *hash)
{
SHA256_CTX sha;
sha256_init( &sha );
sha256_update( &sha, message, len );
sha256_final( &sha, hash );
}
void sha256_curve_points(ec_point_t* points, int points_length, curve_t curve, char *hash)
{
SHA256_CTX sha;
int blen = curve->bitwidth >> 3;
char b[blen];
sha256_init( &sha );
for (int i=0;i<points_length;i++)
{
memset( b, 0x00, blen );
mpz_export( b, NULL, -1, 1, -1, 0, points[i]->x );
sha256_update( &sha, b, blen );
memset( b, 0x00, blen );
mpz_export( b, NULL, -1, 1, -1, 0, points[i]->y );
sha256_update( &sha, b, blen );
}
sha256_final( &sha, hash);
}
char *print_hex(char *p, int len)
{
static char *s = NULL;
static int slen = 0;
int minsize = (len<<1)+1;
if (slen < minsize)
{
if (s)
free(s);
s = malloc(minsize);
slen = minsize;
}
for (int i=0; i<len; i++)
{
s[ (i<<1) ] = hexdigits[ (p[i]>>4) & 0x0f ];
s[ (i<<1) +1 ]= hexdigits[ (p[i]) & 0x0f ];
}
s[minsize-1] = 0x00;
return s;
}