Ejemplo n.º 1
0
size_t Resource::Reader::readData(char *buffer, size_t size)
{
	if(!mCurrentBlock) return 0;	// EOF
	
	if(!mKey.empty() && !mCurrentBlock->hasDecryption())
	{
		BinaryString subsalt;
		subsalt.writeBinary(uint64_t(mCurrentBlockIndex));
		
		// Generate subkey
		BinaryString subkey;
		Sha256().pbkdf2_hmac(mKey, subsalt, subkey, 32, 100);
		
		// Generate iv
		BinaryString iv;
		Sha256().pbkdf2_hmac(mResource->salt(), subsalt, iv, 16, 100);
		
		// Initialize decryption process
		mCurrentBlock->setDecryption(subkey, iv);
	}
	
	size_t ret;
	if((ret = mCurrentBlock->readData(buffer, size)))
	{
		mReadPosition+= ret;
		return ret;
	}
	
	delete mCurrentBlock;
	++mCurrentBlockIndex;
	mCurrentBlock = mNextBlock;
	mNextBlock = createBlock(mCurrentBlockIndex + 1);
	return readData(buffer, size);
}
Ejemplo n.º 2
0
QByteArray Hmac(const QByteArray& key, const QByteArray& data, HashFunction method) {
  const int kBlockSize = 64; // bytes
  Q_ASSERT(key.length() <= kBlockSize);

  QByteArray inner_padding(kBlockSize, char(0x36));
  QByteArray outer_padding(kBlockSize, char(0x5c));

  for (int i=0 ; i<key.length() ; ++i) {
    inner_padding[i] = inner_padding[i] ^ key[i];
    outer_padding[i] = outer_padding[i] ^ key[i];
  }
  if (Md5_Algo == method) {
    return QCryptographicHash::hash(outer_padding +
                                    QCryptographicHash::hash(inner_padding + data,
                                                             QCryptographicHash::Md5),
                                    QCryptographicHash::Md5);
  } else if (Sha1_Algo == method) {
    return QCryptographicHash::hash(outer_padding +
                                    QCryptographicHash::hash(inner_padding + data,
                                                             QCryptographicHash::Sha1),
                                    QCryptographicHash::Sha1);
  } else { // Sha256_Algo, currently default
    return Sha256(outer_padding + Sha256(inner_padding + data));
  }
}
Ejemplo n.º 3
0
void calculateTransactionHash(Transaction * self) {
	assert(self != NULL);

	uint8_t tmpHashStore[32];
	uint8_t * data = getByteArrayData(getMessage(self)->bytes);

	Sha256(data, getMessage(self)->bytes->length, tmpHashStore);
	Sha256(tmpHashStore, 32, self->hash);
}
Ejemplo n.º 4
0
Block::Block(const String &filename, int64_t offset, int64_t size) :
	mCipher(NULL)
{
	mFile = new File(filename, File::Read);
	mOffset = offset;
	
	mFile->seekRead(mOffset);
	if(size >= 0) mSize = Sha256().compute(*mFile, size, mDigest);
	else mSize = Sha256().compute(*mFile, mDigest);
	
	mFile->seekRead(mOffset);
	notifyStore();
}
Ejemplo n.º 5
0
static void _Sha256HmacInit(Sha256HmacCtx *Ctx, BYTE *key, size_t klen)
{
	BYTE  IPad[64];
	unsigned int  i;

	memset(IPad, 0x36, sizeof(IPad));
	memset(Ctx->OPad, 0x5C, sizeof(Ctx->OPad));

	if ( klen > 64 )
	{
		BYTE *temp = (BYTE*)alloca(32);
		Sha256(key, klen, temp);
		klen = 32;
		key  = temp;
	}

	for (i = 0; i < klen; i++)
	{
		IPad[ i ]      ^= key[ i ];
		Ctx->OPad[ i ] ^= key[ i ];
	}

	Sha256Init(&Ctx->ShaCtx);
	Sha256Update(&Ctx->ShaCtx, IPad, sizeof(IPad));
}
Ejemplo n.º 6
0
String Cache::move(const String &filename)
{
	BinaryString digest;
	File file(filename);
	Sha256().compute(file, digest);
	file.close();
	
	String destination = path(digest);
	File::Rename(filename, destination);
	return destination;
}
Ejemplo n.º 7
0
bool Block::ProcessFile(File &file, BinaryString &digest)
{
	int64_t offset = file.tellRead();
	int64_t size = Sha256().compute(file, Size, digest);
	
	if(size)
	{
		Store::Instance->notifyBlock(digest, file.name(), offset, size);
		return true;
	}
	
	return false;
}
Ejemplo n.º 8
0
uint8_t initializeAddressFromRIPEMD160Hash(Address * self,uint8_t netVersionByte,uint8_t * hash,uint8_t cacheString,void (*onErrorReceived)(Error error,char *,...))
{
	/* Build address and then complete intitialization with VersionChecksumBytes*/
	uint8_t * addressData = malloc(25); /* 1 version byte, 20 hash bytes, 4 checksum bytes.*/
	if ( addressData==NULL) {
		onErrorReceived(ERROR_OUT_OF_MEMORY,"Cannot allocate 25 bytes of memory in initializeAddressFromRIPEMD160Hash\n");
		return FALSE;
	}
	/* Set version byte */
	addressData[0] = netVersionByte;
	/* Move hash */
	memmove(addressData+1, hash, 20);
	/* Make checksum and move it into address; check https://en.bitcoin.it/wiki/Technical_background_of_Bitcoin_addresses for step by step explanation */
	uint8_t checksum[32];
	uint8_t checksum2[32];
	Sha256(addressData,21,checksum);
	Sha256(checksum,32,checksum2);
	memmove(addressData+21, checksum2, 4);
	/* initialise VersionChecksumBytes*/
	if (! initializeVersionChecksumBytesFromBytes(getVersionChecksumBytes(self), addressData, 25,cacheString, onErrorReceived)) {
		return FALSE;
	}
	return TRUE;
}
Ejemplo n.º 9
0
Resource::Reader::Reader(Resource *resource, const String &secret, bool nocheck) :
	mResource(resource),
	mReadPosition(0),
	mCurrentBlock(NULL),
	mNextBlock(NULL)
{
	Assert(mResource);
	
	if(!secret.empty())
	{
		if(!nocheck && mResource->salt().empty())
			throw Exception("Expected encrypted resource");
		
		Sha256().pbkdf2_hmac(secret, mResource->salt(), mKey, 32, 100000); 
	}
	else {
		if(!nocheck && !mResource->salt().empty())
			throw Exception("Expected non-encrypted resource");
	}
	
	seekRead(0);	// Initialize positions
}
Ejemplo n.º 10
0
TransactionHashStatus getTransactionInputHashForVerification(void * txIn,
		ByteArray * prevOutSubScript, uint32_t input, SignatureType signType,
		uint8_t * hash) {
	assert(txIn != NULL);
	assert(prevOutSubScript != NULL);
	assert(input >= 0);
	assert(signType != NULL);
	assert(hash != NULL);

	Transaction * self = txIn;

	if (self->numOfTransactionInput < input + 1) {
		getMessage(self)->onErrorReceived(ERROR_TRANSACTION_FEW_INPUTS,
				"Receiving transaction hash to sign cannot be done for because the input index goes past the number of inputs.");
		return TX_HASH_BAD;
	}

	uint8_t last5Bits = (signType & 0x1f); /* For some reason this is what the C++ client does.*/
	uint32_t sizeOfData = 12 + prevOutSubScript->length; /*Version, lock time and the sign type make up 12 bytes.*/

	if (signType & SIGHASH_ANYONECANPAY) {
		sizeOfData += 41; /* Just this one input. 32 bytes for outPointHash, 4 for outPointIndex, 1 for VarLenInt, 4 for sequence*/
	} else {
		sizeOfData += getSizeOfVarLenInt(self->numOfTransactionInput)
				+ self->numOfTransactionInput * 40; /* All inputs*/
	}

	if (last5Bits == SIGHASH_NONE) {
		sizeOfData++; /* Just for the VarLenInt and no outputs.*/
	} else if ((signType & 0x1f) == SIGHASH_SINGLE) {
		if (self->numOfTransactionOutput < input + 1) {
			getMessage(self)->onErrorReceived(ERROR_TRANSACTION_FEW_OUTPUTS,
					"Receiving transaction hash to sign cannot be done for _SIGHASH_SINGLE because there are not enough outputs.");
			return TX_HASH_BAD;
		}
		sizeOfData += getSizeOfVarLenInt(input + 1) + input * 9; /* For outputs up to the input index*/
		/* The size for the output at the input index.*/
		uint32_t len = getByteArray(self->outputs[input]->scriptObject)->length;
		sizeOfData += 8 + getSizeOfVarLenInt(len) + len;
	} else { /* All outputs. Default to SIGHASH_ALL*/
		sizeOfData += getSizeOfVarLenInt(self->numOfTransactionOutput);
		uint32_t i;
		for (i = 0; i < self->numOfTransactionOutput; i++) {
			uint32_t len = getByteArray(self->outputs[i]->scriptObject)->length;
			sizeOfData += 8 + getSizeOfVarLenInt(len) + len;
		}
	}

	ByteArray * data = createNewByteArrayOfSize(sizeOfData,
			getMessage(self)->onErrorReceived);

	if (!data) {
		return TX_HASH_FAIL;
	}

	writeInt32AsLittleEndianIntoByteArray(data, 0, self->version);

	/* Copy input data. Scripts are not copied for the inputs.*/
	uint32_t cursor;

	if (signType & SIGHASH_ANYONECANPAY) {
		encodeVarLenInt(data, 4, createVarLenIntFromUInt64(1)); /* Only the input the signature is for.*/
		copyByteArrayToByteArray(data, 5, self->inputs[input]->prevOutput.hash);
		writeInt32AsLittleEndianIntoByteArray(data, 37,
				self->inputs[input]->prevOutput.index);
		/*Add prevOutSubScript*/
		copyByteArrayToByteArray(data, 41, prevOutSubScript);
		cursor = 41 + prevOutSubScript->length;
		writeInt32AsLittleEndianIntoByteArray(data, cursor,
				self->inputs[input]->sequence);
		cursor += 4;
	} else {
		VarLenInt inputNum = createVarLenIntFromUInt64(
				self->numOfTransactionInput);
		encodeVarLenInt(data, 4, inputNum);
		cursor = 4 + inputNum.storageSize;
		uint32_t i;
		for (i = 0; i < self->numOfTransactionInput; i++) {
			copyByteArrayToByteArray(data, cursor,
					self->inputs[i]->prevOutput.hash);
			cursor += 32;
			writeInt32AsLittleEndianIntoByteArray(data, cursor,
					self->inputs[i]->prevOutput.index);
			cursor += 4;
			/* Add prevOutSubScript if the input is for the signature.*/
			if (i == input) {
				copyByteArrayToByteArray(data, cursor, prevOutSubScript);
				cursor += prevOutSubScript->length;
			}
			if ((signType == SIGHASH_NONE || signType == SIGHASH_SINGLE)
					&& i != input)
				writeInt32AsLittleEndianIntoByteArray(data, cursor, 0);
			else
				/* SIGHASH_ALL or input index for signing sequence*/
				writeInt32AsLittleEndianIntoByteArray(data, cursor,
						self->inputs[i]->sequence);
			cursor += 4;
		}
	}
	/* Copy output data*/
	if (last5Bits == SIGHASH_NONE) {
		VarLenInt varInt = createVarLenIntFromUInt64(0);
		encodeVarLenInt(data, cursor, varInt);
		cursor++;
	} else if (last5Bits == SIGHASH_SINGLE) {
		VarLenInt varInt = createVarLenIntFromUInt64(input + 1);
		encodeVarLenInt(data, cursor, varInt);
		cursor += varInt.storageSize;

		uint32_t j;
		for (j = 0; j < input; j++) {
			writeInt64AsLittleEndianIntoByteArray(data, cursor,
					0xFFFFFFFFFFFFFFFF); /*_OUTPUT_VALUE_NUS_ONE = 0xFFFFFFFFFFFFFFFF*/
			cursor += 8;
			encodeVarLenInt(data, cursor, createVarLenIntFromUInt64(0));
			cursor++;
		}
		writeInt64AsLittleEndianIntoByteArray(data, cursor,
				self->outputs[input]->value);
		cursor += 8;
		varInt = createVarLenIntFromUInt64(
				getByteArray(self->outputs[input]->scriptObject)->length);
		encodeVarLenInt(data, cursor, varInt);
		cursor += varInt.storageSize;

		copyByteArrayToByteArray(data, cursor,
				getByteArray(self->outputs[input]->scriptObject));
		cursor += varInt.value;
	} else { /* SIGHASH_ALL*/
		VarLenInt varInt = createVarLenIntFromUInt64(
				self->numOfTransactionOutput);
		encodeVarLenInt(data, cursor, varInt);
		cursor += varInt.storageSize;
		uint32_t x;
		for (x = 0; x < self->numOfTransactionOutput; x++) {
			writeInt64AsLittleEndianIntoByteArray(data, cursor,
					self->outputs[x]->value);
			cursor += 8;
			varInt = createVarLenIntFromUInt64(
					getByteArray(self->outputs[x]->scriptObject)->length);
			encodeVarLenInt(data, cursor, varInt);
			cursor += varInt.storageSize;
			copyByteArrayToByteArray(data, cursor,
					getByteArray(self->outputs[x]->scriptObject));
			cursor += varInt.value;
		}
	}
	/* Set lockTime*/
	writeInt32AsLittleEndianIntoByteArray(data, cursor, self->lockTime);
	writeInt32AsLittleEndianIntoByteArray(data, cursor + 4, signType);

	assert(sizeOfData == cursor + 8); /* Must always be like this*/

	uint8_t firstHash[32];
	Sha256(getByteArrayData(data), sizeOfData, firstHash);
	Sha256(firstHash, 32, hash);

	return TX_HASH_GOOD;
}
Ejemplo n.º 11
0
		inline static HashSha256 Sha256(std::string s)
			{
			return Sha256(s.c_str(), s.size());
			}
Ejemplo n.º 12
0
void Resource::process(const String &filename, const String &name, const String &type, const String &secret)
{
	BinaryString salt;
	
	// If secret is not empty then this is an encrypted resource
	if(!secret.empty())
	{
		// Generate salt from plaintext
		// Because we need to be able to recognize data is identical even when encrypted
		BinaryString digest;
		File file(filename, File::Read);
		Sha256().compute(file, digest);
		Sha256().pbkdf2_hmac(digest, type, salt, 32, 100000);
		Assert(!salt.empty());
	}
	
	// Fill index record
	delete mIndexRecord;
	int64_t size = File::Size(filename);
	mIndexRecord = new Resource::IndexRecord;
	mIndexRecord->name = name;
	mIndexRecord->type = type;
	mIndexRecord->size = size;
	mIndexRecord->salt = salt;
	mIndexRecord->blockDigests.reserve(size/Block::Size);
	
	// Process blocks
	File file(filename, File::Read);
	BinaryString blockDigest;
	
	if(!secret.empty())
	{
		BinaryString key;
		Sha256().pbkdf2_hmac(secret, salt, key, 32, 100000);
		
		uint64_t i = 0;
		while(true)
		{
			BinaryString subsalt;
			subsalt.writeBinary(i);
			
			// Generate subkey
			BinaryString subkey;
			Sha256().pbkdf2_hmac(key, subsalt, subkey, 32, 100);
			
			// Generate iv
			BinaryString iv;
			Sha256().pbkdf2_hmac(salt, subsalt, iv, 16, 100);
			
			if(!Block::EncryptFile(file, subkey, iv, blockDigest))
				break;
			
			mIndexRecord->blockDigests.append(blockDigest);
			++i;
		}
	} 
	else {
		while(Block::ProcessFile(file, blockDigest))
			mIndexRecord->blockDigests.append(blockDigest);
	}
	
	// Create index
	String tempFileName = File::TempName();
	File tempFile(tempFileName, File::Truncate);
	BinarySerializer serializer(&tempFile);
	serializer.write(mIndexRecord);
	tempFile.close();
	String indexFilePath = Cache::Instance->move(tempFileName);
	
	// Create index block
	delete mIndexBlock;
	mIndexBlock = new Block(indexFilePath);
}