Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 201 additions & 10 deletions Lyra2.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ int LYRA2(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *
}
//Places the pointers in the correct positions
uint64_t *ptrWord = wholeMatrix;
for (i = 0; i < (int64_t)nRows; i++) {
for (i = 0; i < nRows; i++) {
memMatrix[i] = ptrWord;
ptrWord += ROW_LEN_INT64;
}
Expand Down Expand Up @@ -133,7 +133,7 @@ int LYRA2(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *
//================================ Setup Phase =============================//
//Absorbing salt, password and basil: this is the only place in which the block length is hard-coded to 512 bits
ptrWord = wholeMatrix;
for (i = 0; i < (int64_t)nBlocksInput; i++) {
for (i = 0; i < nBlocksInput; i++) {
absorbBlockBlake2Safe(state, ptrWord); //absorbs each block of pad(pwd || salt || basil)
ptrWord += BLOCK_LEN_BLAKE2_SAFE_INT64; //goes to next block of pad(pwd || salt || basil)
}
Expand Down Expand Up @@ -161,14 +161,14 @@ int LYRA2(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *
gap = -gap; //inverts the modifier to the step
}

} while (row < (int64_t)nRows);
} while (row < nRows);
//==========================================================================/

//============================ Wandering Phase =============================//
row = 0; //Resets the visitation to the first row of the memory matrix
for (tau = 1; tau <= (int64_t)timeCost; tau++) {
for (tau = 1; tau <= timeCost; tau++) {
//Step is approximately half the number of all rows of the memory matrix for an odd tau; otherwise, it is -1
step = (tau % 2 == 0) ? -1 : (int64_t)(nRows / 2 - 1);
step = (tau % 2 == 0) ? -1 : nRows / 2 - 1;
do {
//Selects a pseudorandom index row*
//------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -246,7 +246,7 @@ int LYRA2_old(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const vo
}
//Places the pointers in the correct positions
uint64_t *ptrWord = wholeMatrix;
for (i = 0; i < (int64_t)nRows; i++) {
for (i = 0; i < nRows; i++) {
memMatrix[i] = ptrWord;
ptrWord += ROW_LEN_INT64;
}
Expand Down Expand Up @@ -302,7 +302,7 @@ int LYRA2_old(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const vo
//================================ Setup Phase =============================//
//Absorbing salt, password and basil: this is the only place in which the block length is hard-coded to 512 bits
ptrWord = wholeMatrix;
for (i = 0; i < (int64_t)nBlocksInput; i++) {
for (i = 0; i < nBlocksInput; i++) {
absorbBlockBlake2Safe(state, ptrWord); //absorbs each block of pad(pwd || salt || basil)
ptrWord += BLOCK_LEN_BLAKE2_SAFE_BYTES; //goes to next block of pad(pwd || salt || basil)
}
Expand Down Expand Up @@ -330,14 +330,14 @@ int LYRA2_old(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const vo
gap = -gap; //inverts the modifier to the step
}

} while (row < (int64_t)nRows);
} while (row < nRows);
//==========================================================================/

//============================ Wandering Phase =============================//
row = 0; //Resets the visitation to the first row of the memory matrix
for (tau = 1; tau <= (int64_t)timeCost; tau++) {
for (tau = 1; tau <= timeCost; tau++) {
//Step is approximately half the number of all rows of the memory matrix for an odd tau; otherwise, it is -1
step = (tau % 2 == 0) ? -1 : (int64_t)(nRows / 2 - 1);
step = (tau % 2 == 0) ? -1 : nRows / 2 - 1;
do {
//Selects a pseudorandom index row*
//------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -380,3 +380,194 @@ int LYRA2_old(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const vo

return 0;
}

/**
* Executes Lyra2 based on the G function from Blake2b. This version supports salts and passwords
* whose combined length is smaller than the size of the memory matrix, (i.e., (nRows x nCols x b) bits,
* where "b" is the underlying sponge's bitrate). In this implementation, the "basil" is composed by all
* integer parameters (treated as type "unsigned int") in the order they are provided, plus the value
* of nCols, (i.e., basil = kLen || pwdlen || saltlen || timeCost || nRows || nCols).
*
* @param K The derived key to be output by the algorithm
* @param kLen Desired key length
* @param pwd User password
* @param pwdlen Password length
* @param salt Salt
* @param saltlen Salt length
* @param timeCost Parameter to determine the processing time (T)
* @param nRows Number or rows of the memory matrix (R)
* @param nCols Number of columns of the memory matrix (C)
*
* @return 0 if the key is generated correctly; -1 if there is an error (usually due to lack of memory for allocation)
*/
int LYRA2_3(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols) {

//============================= Basic variables ============================//
int64_t row = 2; //index of row to be processed
int64_t prev = 1; //index of prev (last row ever computed/modified)
int64_t rowa = 0; //index of row* (a previous row, deterministically picked during Setup and randomly picked while Wandering)
int64_t tau; //Time Loop iterator
int64_t step = 1; //Visitation step (used during Setup and Wandering phases)
int64_t window = 2; //Visitation window (used to define which rows can be revisited during Setup)
int64_t gap = 1; //Modifier to the step, assuming the values 1 or -1
int64_t i; //auxiliary iteration counter
//==========================================================================/

//========== Initializing the Memory Matrix and pointers to it =============//
//Tries to allocate enough space for the whole memory matrix


const int64_t ROW_LEN_INT64 = BLOCK_LEN_INT64 * nCols;
const int64_t ROW_LEN_BYTES = ROW_LEN_INT64 * 8;

i = (int64_t) ((int64_t) nRows * (int64_t) ROW_LEN_BYTES);
uint64_t *wholeMatrix = malloc(i);
if (wholeMatrix == NULL) {
return -1;
}
memset(wholeMatrix, 0, i);

//Allocates pointers to each row of the matrix
uint64_t **memMatrix = malloc(nRows * sizeof (uint64_t*));
if (memMatrix == NULL) {
return -1;
}
//Places the pointers in the correct positions
uint64_t *ptrWord = wholeMatrix;
for (i = 0; i < nRows; i++) {
memMatrix[i] = ptrWord;
ptrWord += ROW_LEN_INT64;
}
//==========================================================================/

//============= Getting the password + salt + basil padded with 10*1 ===============//
//OBS.:The memory matrix will temporarily hold the password: not for saving memory,
//but this ensures that the password copied locally will be overwritten as soon as possible

//First, we clean enough blocks for the password, salt, basil and padding
uint64_t nBlocksInput = ((saltlen + pwdlen + 6 * sizeof (uint64_t)) / BLOCK_LEN_BLAKE2_SAFE_BYTES) + 1;
byte *ptrByte = (byte*) wholeMatrix;
memset(ptrByte, 0, nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES);

//Prepends the password
memcpy(ptrByte, pwd, pwdlen);
ptrByte += pwdlen;

//Concatenates the salt
memcpy(ptrByte, salt, saltlen);
ptrByte += saltlen;

//Concatenates the basil: every integer passed as parameter, in the order they are provided by the interface
memcpy(ptrByte, &kLen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &pwdlen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &saltlen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &timeCost, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &nRows, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &nCols, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);

//Now comes the padding
*ptrByte = 0x80; //first byte of padding: right after the password
ptrByte = (byte*) wholeMatrix; //resets the pointer to the start of the memory matrix
ptrByte += nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - 1; //sets the pointer to the correct position: end of incomplete block
*ptrByte ^= 0x01; //last byte of padding: at the end of the last incomplete block
//==========================================================================/

//======================= Initializing the Sponge State ====================//
//Sponge state: 16 uint64_t, BLOCK_LEN_INT64 words of them for the bitrate (b) and the remainder for the capacity (c)
uint64_t *state = malloc(16 * sizeof (uint64_t));
if (state == NULL) {
return -1;
}
initState(state);
//==========================================================================/

//================================ Setup Phase =============================//
//Absorbing salt, password and basil: this is the only place in which the block length is hard-coded to 512 bits
ptrWord = wholeMatrix;
for (i = 0; i < nBlocksInput; i++) {
absorbBlockBlake2Safe(state, ptrWord); //absorbs each block of pad(pwd || salt || basil)
ptrWord += BLOCK_LEN_BLAKE2_SAFE_INT64; //goes to next block of pad(pwd || salt || basil)
}

//Initializes M[0] and M[1]
reducedSqueezeRow0(state, memMatrix[0], nCols); //The locally copied password is most likely overwritten here
reducedDuplexRow1(state, memMatrix[0], memMatrix[1], nCols);

do {
//M[row] = rand; //M[row*] = M[row*] XOR rotW(rand)
reducedDuplexRowSetup(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);


//updates the value of row* (deterministically picked during Setup))
rowa = (rowa + step) & (window - 1);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
row++;

//Checks if all rows in the window where visited.
if (rowa == 0) {
step = window + gap; //changes the step: approximately doubles its value
window *= 2; //doubles the size of the re-visitation window
gap = -gap; //inverts the modifier to the step
}

} while (row < nRows);
//==========================================================================/

//============================ Wandering Phase =============================//

uint64_t index = 0;
row = 0; //Resets the visitation to the first row of the memory matrix
for (tau = 1; tau <= timeCost; tau++) {
//Step is approximately half the number of all rows of the memory matrix for an odd tau; otherwise, it is -1
step = (tau % 2 == 0) ? -1 : nRows / 2 - 1;
do {
//Selects a pseudorandom index row*
//------------------------------------------hg7------------------------------------------------
//rowa = ((unsigned int)state[0]) & (nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
index = state[index % 16];
rowa = ((uint64_t) (state[index % 16])) % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------

//Performs a reduced-round duplexing operation over M[row*] XOR M[prev], updating both M[row*] and M[row]
reducedDuplexRow(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);

//update prev: it now points to the last row ever computed
prev = row;

//updates row: goes to the next row to be computed
//------------------------------------------------------------------------------------------
//row = (row + step) & (nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
row = (row + step) % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------

} while (row != 0);
}
//==========================================================================/

//============================ Wrap-up Phase ===============================//
//Absorbs the last block of the memory matrix
absorbBlock(state, memMatrix[rowa]);

//Squeezes the key
squeeze(state, K, kLen);
//==========================================================================/

//========================= Freeing the memory =============================//
free(memMatrix);
free(wholeMatrix);

//Wiping out the sponge's internal state before freeing it
memset(state, 0, 16 * sizeof (uint64_t));
free(state);
//==========================================================================/

return 0;
}
2 changes: 2 additions & 0 deletions Lyra2.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ typedef unsigned char byte;

int LYRA2(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols);

int LYRA2_3(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols);

int LYRA2_old(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols);

#endif /* LYRA2_H_ */
27 changes: 27 additions & 0 deletions Lyra2RE.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,30 @@ void lyra2re2_hash(const char* input, char* output)

memcpy(output, hashA, 32);
}

void lyra2re3_hash(const char* input, char* output)
{
sph_blake256_context ctx_blake;
sph_cubehash256_context ctx_cubehash;
sph_bmw256_context ctx_bmw;

uint32_t hashA[8], hashB[8];

sph_blake256_init(&ctx_blake);
sph_blake256(&ctx_blake, input, 80);
sph_blake256_close (&ctx_blake, hashA);

LYRA2_3(hashB, 32, hashA, 32, hashA, 32, 1, 4, 4);

sph_cubehash256_init(&ctx_cubehash);
sph_cubehash256(&ctx_cubehash, hashB, 32);
sph_cubehash256_close(&ctx_cubehash, hashA);

LYRA2_3(hashB, 32, hashA, 32, hashA, 32, 1, 4, 4);

sph_bmw256_init(&ctx_bmw);
sph_bmw256(&ctx_bmw, hashB, 32);
sph_bmw256_close(&ctx_bmw, hashA);

memcpy(output, hashA, 32);
}
1 change: 1 addition & 0 deletions Lyra2RE.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extern "C" {

void lyra2re_hash(const char* input, char* output);
void lyra2re2_hash(const char* input, char* output);
void lyra2re3_hash(const char* input, char* output);

#ifdef __cplusplus
}
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ orehash is a Node.js native module for Galactrum proof of work functions. It pro

var buf = Buffer.from('700000005d385ba114d079971b29a9418fd0549e7d68a95c7f168621a314201000000000578586d149fd07b22f3a8a347c516de7052f034d2b76ff68e0d6ecff9b77a45489e3fd511732011df0731000', 'hex');

console.log(orehash.SumLyra2REv3(buf));
console.log(orehash.SumLyra2REv2(buf));
console.log(orehash.SumLyra2RE(buf));
console.log(orehash.SumScryptN(buf));
Expand Down
2 changes: 1 addition & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"sha3/blake.c", "sha3/bmw.c",
"sha3/cubehash.c", "sha3/groestl.c",
"sha3/keccak.c", "sha3/skein.c", "scryptn.c",
"orehash.cc"],
"galactrum-hash.cc"],
"include_dirs" : [
"<!(node -e \"require('nan')\")"
]
Expand Down
24 changes: 24 additions & 0 deletions orehash.cc → galactrum-hash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,28 @@ void SumLyra2REv2(const Nan::FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(Nan::NewBuffer(output, 32).ToLocalChecked());
}

void SumLyra2REv3(const Nan::FunctionCallbackInfo<Value>& args) {

if(args.Length() < 1) {
Nan::ThrowTypeError("1 argument expected");
return;
}

Local<Object> target = args[0]->ToObject();

if(!node::Buffer::HasInstance(target)) {
Nan::ThrowTypeError("Function expects buffer as input");
return;
}

char* input = node::Buffer::Data(target);
char* output = new char[32];

lyra2re3_hash(input, output);

args.GetReturnValue().Set(Nan::NewBuffer(output, 32).ToLocalChecked());
}

void SumLyra2RE(const Nan::FunctionCallbackInfo<Value>& args) {

if(args.Length() < 1) {
Expand Down Expand Up @@ -78,6 +100,8 @@ void SumScryptN(const Nan::FunctionCallbackInfo<Value>& args) {
}

void Init(v8::Local<v8::Object> exports) {
exports->Set(Nan::New("SumLyra2REv3").ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(SumLyra2REv3)->GetFunction());
exports->Set(Nan::New("SumLyra2REv2").ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(SumLyra2REv2)->GetFunction());
exports->Set(Nan::New("SumLyra2RE").ToLocalChecked(),
Expand Down
Loading