From f580ca2b976773c19d4ff3e041157fe2c61ff780 Mon Sep 17 00:00:00 2001 From: avtc Date: Sun, 14 Jan 2018 23:05:46 +0200 Subject: [PATCH] attempt to add support for sld --- src/crypto/slow-hash.c | 73 ++++++++++++++++++++++++++++++++++++++++++ src/main.cc | 31 ++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index 72f5eba3..9775fd12 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -17,6 +17,7 @@ static void (*const extra_hashes[4])(const void *, size_t, char *) = { #define MEMORY (1 << 21) /* 2 MiB */ #define ITER (1 << 20) +#define ITER_SLD (1 << 16) #define AES_BLOCK_SIZE 16 #define AES_KEY_SIZE 32 /*16*/ #define INIT_SIZE_BLK 8 @@ -150,3 +151,75 @@ void cn_slow_hash(const void *data, size_t length, char *hash) { oaes_free(&aes_ctx); free(long_state); } + +void cn_slow_hash_sld(const void *data, size_t length, char *hash) { + uint8_t* long_state = malloc(MEMORY); + union cn_slow_hash_state state; + uint8_t text[INIT_SIZE_BYTE]; + uint8_t a[AES_BLOCK_SIZE]; + uint8_t b[AES_BLOCK_SIZE]; + uint8_t c[AES_BLOCK_SIZE]; + uint8_t d[AES_BLOCK_SIZE]; + size_t i, j; + uint8_t aes_key[AES_KEY_SIZE]; + OAES_CTX* aes_ctx; + + hash_process(&state.hs, data, length); + memcpy(text, state.init, INIT_SIZE_BYTE); + memcpy(aes_key, state.hs.b, AES_KEY_SIZE); + aes_ctx = oaes_alloc(); + + oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE); + for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { + for (j = 0; j < INIT_SIZE_BLK; j++) { + oaes_pseudo_encrypt_ecb(aes_ctx, &text[AES_BLOCK_SIZE * j]); + } + memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); + } + + for (i = 0; i < 16; i++) { + a[i] = state.k[ i] ^ state.k[32 + i]; + b[i] = state.k[16 + i] ^ state.k[48 + i]; + } + + for (i = 0; i < ITER_SLD / 2; i++) { + /* Dependency chain: address -> read value ------+ + * written value <-+ hard function (AES or MUL) <+ + * next address <-+ + */ + /* Iteration 1 */ + j = e2i(a, MEMORY / AES_BLOCK_SIZE); + copy_block(c, &long_state[j * AES_BLOCK_SIZE]); + oaes_encryption_round(a, c); + xor_blocks(b, c); + swap_blocks(b, c); + copy_block(&long_state[j * AES_BLOCK_SIZE], c); + assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); + swap_blocks(a, b); + /* Iteration 2 */ + j = e2i(a, MEMORY / AES_BLOCK_SIZE); + copy_block(c, &long_state[j * AES_BLOCK_SIZE]); + mul(a, c, d); + sum_half_blocks(b, d); + swap_blocks(b, c); + xor_blocks(b, c); + copy_block(&long_state[j * AES_BLOCK_SIZE], c); + assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); + swap_blocks(a, b); + } + + memcpy(text, state.init, INIT_SIZE_BYTE); + oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE); + for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { + for (j = 0; j < INIT_SIZE_BLK; j++) { + xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]); + oaes_pseudo_encrypt_ecb(aes_ctx, &text[j * AES_BLOCK_SIZE]); + } + } + memcpy(state.init, text, INIT_SIZE_BYTE); + hash_permutation(&state.hs); + /*memcpy(hash, &state, 32);*/ + extra_hashes[state.hs.b[0] & 3](&state, 200, hash); + oaes_free(&aes_ctx); + free(long_state); +} diff --git a/src/main.cc b/src/main.cc index bb9b7020..8a3011dd 100644 --- a/src/main.cc +++ b/src/main.cc @@ -279,6 +279,36 @@ NAN_METHOD(cryptonight) { info.GetReturnValue().Set(Nan::NewBuffer(output, 32).ToLocalChecked()); } +NAN_METHOD(cryptonight_sld) { + bool fast = false; + + if (info.Length() < 1) + return THROW_ERROR_EXCEPTION("You must provide one argument."); + + if (info.Length() >= 2) { + if (!info[1]->IsBoolean()) + return THROW_ERROR_EXCEPTION("Argument 2 should be a boolean"); + fast = info[1]->ToBoolean()->BooleanValue(); + } + + Local target = Nan::To(info[0]).ToLocalChecked(); + + if (!Buffer::HasInstance(target)) + return THROW_ERROR_EXCEPTION("Argument should be a buffer object."); + + char * input = Buffer::Data(target); + char *output = (char*)malloc(sizeof(char) * 32); + + uint32_t input_len = Buffer::Length(target); + + if (fast) + crypto::cn_fast_hash_sld((const void *)input, input_len, output); + else + crypto::cn_slow_hash_sld((const void *)input, input_len, output); + + info.GetReturnValue().Set(Nan::NewBuffer(output, 32).ToLocalChecked()); +} + NAN_MODULE_INIT(init) { Nan::Set(target, Nan::New("construct_block_blob").ToLocalChecked(), Nan::GetFunction(Nan::New(construct_block_blob)).ToLocalChecked()); Nan::Set(target, Nan::New("get_block_id").ToLocalChecked(), Nan::GetFunction(Nan::New(get_block_id)).ToLocalChecked()); @@ -286,6 +316,7 @@ NAN_MODULE_INIT(init) { Nan::Set(target, Nan::New("convert_blob_bb").ToLocalChecked(), Nan::GetFunction(Nan::New(convert_blob_bb)).ToLocalChecked()); Nan::Set(target, Nan::New("address_decode").ToLocalChecked(), Nan::GetFunction(Nan::New(address_decode)).ToLocalChecked()); Nan::Set(target, Nan::New("cryptonight").ToLocalChecked(), Nan::GetFunction(Nan::New(cryptonight)).ToLocalChecked()); + Nan::Set(target, Nan::New("cryptonight_sld").ToLocalChecked(), Nan::GetFunction(Nan::New(cryptonight_sld)).ToLocalChecked()); } NODE_MODULE(cryptonote, init)