void DataHash::Init(HASH_TYPE Type,uint MaxThreads) { HashType=Type; if (Type==HASH_RAR14) CurCRC32=0; if (Type==HASH_CRC32) CurCRC32=0xffffffff; // Initial CRC32 value. if (Type==HASH_BLAKE2) blake2sp_init( &blake2ctx ); #ifdef RAR_SMP DataHash::MaxThreads=Min(MaxThreads,MaxHashThreads); #endif }
int blake2sp_stream( FILE *stream, void *resstream ) { int ret = -1; size_t sum, n; blake2sp_state S[1]; static const size_t buffer_length = 16 * ( 1UL << 20 ); uint8_t *buffer = ( uint8_t * )malloc( buffer_length ); if( !buffer ) return -1; blake2sp_init( S, BLAKE2S_OUTBYTES ); while( 1 ) { sum = 0; while( 1 ) { n = fread( buffer + sum, 1, buffer_length - sum, stream ); sum += n; if( buffer_length == sum ) break; if( 0 == n ) { if( ferror( stream ) ) goto cleanup_buffer; goto final_process; } if( feof( stream ) ) goto final_process; } blake2sp_update( S, buffer, buffer_length ); } final_process:; if( sum > 0 ) blake2sp_update( S, buffer, sum ); blake2sp_final( S, resstream, BLAKE2S_OUTBYTES ); ret = 0; cleanup_buffer: free( buffer ); return ret; }
static NAN_METHOD(New) { if(!info.IsConstructCall()) { return Nan::ThrowError("Constructor must be called with new"); } Hash *obj = new Hash(); obj->Wrap(info.This()); if(info.Length() < 1 || !info[0]->IsString()) { return Nan::ThrowError(v8::Exception::TypeError(Nan::New<v8::String>("First argument must be a string with algorithm name").ToLocalChecked())); } std::string algo = std::string(*v8::String::Utf8Value(info[0]->ToString())); const char *key_data = nullptr; size_t key_length; if(algo != "bypass" && info.Length() >= 2) { if(!node::Buffer::HasInstance(info[1])) { return Nan::ThrowError(v8::Exception::TypeError(Nan::New<v8::String>("If key argument is given, it must be a Buffer").ToLocalChecked())); } key_data = node::Buffer::Data(info[1]); key_length = node::Buffer::Length(info[1]); } if(algo == "bypass") { // Initialize nothing - .copy() will set up all the state } else if(algo == "blake2b") { if(!key_data) { if(blake2b_init(reinterpret_cast<blake2b_state*>(&obj->state), BLAKE2B_OUTBYTES) != 0) { return Nan::ThrowError("blake2b_init failure"); } } else { if(key_length > BLAKE2B_KEYBYTES) { return Nan::ThrowError("Key must be 64 bytes or smaller"); } if(blake2b_init_key(reinterpret_cast<blake2b_state*>(&obj->state), BLAKE2B_OUTBYTES, key_data, key_length) != 0) { return Nan::ThrowError("blake2b_init_key failure"); } } obj->outbytes = 512 / 8; obj->any_blake2_update = BLAKE_FN_CAST(blake2b_update); obj->any_blake2_final = BLAKE_FN_CAST(blake2b_final); obj->initialized_ = true; } else if(algo == "blake2bp") { if(!key_data) { if(blake2bp_init(reinterpret_cast<blake2bp_state*>(&obj->state), BLAKE2B_OUTBYTES) != 0) { return Nan::ThrowError("blake2bp_init failure"); } } else { if(key_length > BLAKE2B_KEYBYTES) { return Nan::ThrowError("Key must be 64 bytes or smaller"); } if(blake2bp_init_key(reinterpret_cast<blake2bp_state*>(&obj->state), BLAKE2B_OUTBYTES, key_data, key_length) != 0) { return Nan::ThrowError("blake2bp_init_key failure"); } } obj->outbytes = 512 / 8; obj->any_blake2_update = BLAKE_FN_CAST(blake2bp_update); obj->any_blake2_final = BLAKE_FN_CAST(blake2bp_final); obj->initialized_ = true; } else if(algo == "blake2s") { if(!key_data) { if(blake2s_init(reinterpret_cast<blake2s_state*>(&obj->state), BLAKE2S_OUTBYTES) != 0) { return Nan::ThrowError("blake2bs_init failure"); } } else { if(key_length > BLAKE2S_KEYBYTES) { return Nan::ThrowError("Key must be 32 bytes or smaller"); } if(blake2s_init_key(reinterpret_cast<blake2s_state*>(&obj->state), BLAKE2S_OUTBYTES, key_data, key_length) != 0) { return Nan::ThrowError("blake2s_init_key failure"); } } obj->outbytes = 256 / 8; obj->any_blake2_update = BLAKE_FN_CAST(blake2s_update); obj->any_blake2_final = BLAKE_FN_CAST(blake2s_final); obj->initialized_ = true; } else if(algo == "blake2sp") { if(!key_data) { if(blake2sp_init(reinterpret_cast<blake2sp_state*>(&obj->state), BLAKE2S_OUTBYTES) != 0) { return Nan::ThrowError("blake2sp_init failure"); } } else { if(key_length > BLAKE2S_KEYBYTES) { return Nan::ThrowError("Key must be 32 bytes or smaller"); } if(blake2sp_init_key(reinterpret_cast<blake2sp_state*>(&obj->state), BLAKE2S_OUTBYTES, key_data, key_length) != 0) { return Nan::ThrowError("blake2sp_init_key failure"); } } obj->outbytes = 256 / 8; obj->any_blake2_update = BLAKE_FN_CAST(blake2sp_update); obj->any_blake2_final = BLAKE_FN_CAST(blake2sp_final); obj->initialized_ = true; } else { return Nan::ThrowError("Algorithm must be blake2b, blake2s, blake2bp, or blake2sp"); } info.GetReturnValue().Set(info.This()); }