Exemplo n.º 1
0
bool CBInitHDKeyFromData(CBHDKey * key, uint8_t * data, CBHDKeyVersion versionBytes, CBHDKeyType type){
	CBInitHDKey(key);
	// Set version bytes
	key->versionBytes = versionBytes;
	// Chain code
	memcpy(key->chainCode, data + 13, 32);
	if (type == CB_HD_KEY_TYPE_PRIVATE){
		// Private
		memcpy(key->keyPair->privkey, data + 46, 32);
		// Calculate public key
		CBKeyGetPublicKey(CBHDKeyGetPrivateKey(key), CBHDKeyGetPublicKey(key));
	}else
		// Assume public
		memcpy(CBHDKeyGetPublicKey(key), data + 45, 33);
	// Depth
	key->depth = data[4];
	if (key->depth == 0) {
		// Master
		key->childID.priv = false;
		key->childID.childNumber = 0;
		for (uint8_t x = 5; x < 9; x++)
			if (data[x] != 0) {
				CBLogError("The fingerprint of the master key is not zero.");
				return false;
			}
	}else{
		// Not master
		uint32_t childNum = CBArrayToInt32BigEndian(data, 9);
		key->childID.priv = childNum >> 31;
		key->childID.childNumber = childNum & 0x8fffffff;
	}
	return true;
}
Exemplo n.º 2
0
void CBHDKeySerialise(CBHDKey * key, uint8_t * data){
	CBInt32ToArrayBigEndian(data, 0, key->versionBytes);
	if (key->depth == 0)
		// Master
		memset(data + 4, 0, 9);
	else{
		// Not master
		data[4] = key->depth;
		memcpy(data + 5, key->parentFingerprint, 4);
		// Child number
		CBInt32ToArrayBigEndian(data, 9, CBHDKeyGetChildNumber(key->childID));
	}
	// Chain code
	memcpy(data + 13, key->chainCode, 32);
	if (CBHDKeyGetType(key->versionBytes) == CB_HD_KEY_TYPE_PRIVATE) {
		// Private
		data[45] = 0;
		memcpy(data + 46, CBHDKeyGetPrivateKey(key), 32);
	}else
		// Assume public
		memcpy(data + 45, CBHDKeyGetPublicKey(key), 33);
}
Exemplo n.º 3
0
bool CBHDKeyDeriveChild(CBHDKey * parentKey, CBHDKeyChildID childID, CBHDKey * childKey){
	uint8_t hash[64], inputData[37];
	CBHDKeyType type = CBHDKeyGetType(parentKey->versionBytes);
	// Add childID to inputData
	CBInt32ToArrayBigEndian(inputData, 33, CBHDKeyGetChildNumber(childID));
	if (childID.priv) {
		// Private key derivation
		// Parent must be private
		if (type != CB_HD_KEY_TYPE_PRIVATE) {
			CBLogError("Attempting to derive a public-key without public-key derivation, or the key was of an unknown type.");
			return false;
		}
		// Add private key
		inputData[0] = 0;
		memcpy(inputData + 1, CBHDKeyGetPrivateKey(parentKey), 32);
	}else{
		// Public key derivation
		// Can be public or private
		if (type == CB_HD_KEY_TYPE_UNKNOWN) {
			CBLogError("Attempting to derive a key from an unknown key.");
			return false;
		}
		// Add the public key
		memcpy(inputData, CBHDKeyGetPublicKey(parentKey), 33);
	}
	// Get HMAC-SHA512 hash
	CBHDKeyHmacSha512(inputData, parentKey->chainCode, hash);
	// Copy over chain code, childID and version bytes
	memcpy(childKey->chainCode, hash + 32, 32);
	childKey->childID = childID;
	childKey->versionBytes = parentKey->versionBytes;
	// Set fingerprint of parent
	memcpy(childKey->parentFingerprint, CBHDKeyGetHash(parentKey), 4);
	// Set depth
	childKey->depth = parentKey->depth + 1;
	// Calculate key
	if (type == CB_HD_KEY_TYPE_PRIVATE) {
		// Calculating the private key
		// Add private key to first 32 bytes and modulo the order the curve
		// Split into four 64bit integers and add each one
		bool overflow = 0;
		for (uint8_t x = 4; x--;) {
			uint64_t a = CBArrayToInt64BigEndian(hash, 8*x);
			uint64_t b = CBArrayToInt64BigEndian(CBHDKeyGetPrivateKey(parentKey), 8*x) + overflow;
			uint64_t c = a + b;
			overflow = (c < b)? 1 : 0;
			CBInt64ToArrayBigEndian(CBHDKeyGetPrivateKey(childKey), 8*x, c);
		}
		if (overflow || memcmp(CBHDKeyGetPrivateKey(childKey), CB_CURVE_ORDER, 32) > 0) {
			// Take away CB_CURVE_ORDER
			bool carry = 0;
			for (uint8_t x = 4; x--;) {
				uint64_t a = CBArrayToInt64BigEndian(CBHDKeyGetPrivateKey(childKey), 8*x);
				uint64_t b = CBArrayToInt64BigEndian(CB_CURVE_ORDER, 8*x) + carry;
				carry = a < b;
				a -= b;
				CBInt64ToArrayBigEndian(CBHDKeyGetPrivateKey(childKey), 8*x, a);
			}
		}
		// Derive public key from private key
		CBKeyGetPublicKey(childKey->keyPair->privkey, CBHDKeyGetPublicKey(childKey));
		// Do not bother checking validity???
	}else{
		// Calculating the public key
		// Multiply the first 32 bytes by the base point (derive public key) and add to the public key point.
		CBKeyGetPublicKey(hash, CBHDKeyGetPublicKey(childKey));
		CBAddPoints(CBHDKeyGetPublicKey(childKey), CBHDKeyGetPublicKey(parentKey));
	}
	return true;
}