Exemple #1
0
std::shared_ptr<Tox_Pass_Key> Core::createPasskey(const QString& password, uint8_t* salt)
{
    std::shared_ptr<Tox_Pass_Key> encryptionKey(tox_pass_key_new(), tox_pass_key_free);

    CString str(password);
    if (salt)
        tox_pass_key_derive_with_salt(encryptionKey.get(), str.data(), str.size(), salt, nullptr);
    else
        tox_pass_key_derive(encryptionKey.get(), str.data(), str.size(), nullptr);

    return encryptionKey;
}
QString ClientConfiguration::toBackup(QString const& password) const {
	QByteArray encryptionKey(BACKUP_ENCRYPTION_KEY_BYTES, 0x00);

	// Generate a Salt
	QByteArray salt(BACKUP_SALT_BYTES, 0x00);
	randombytes_buf(salt.data(), BACKUP_SALT_BYTES);

	// Convert the password into bytes
	QByteArray password8Bit = password.toUtf8();

	// Generate the encryption key for the Backup from the Salt and the Password
	PKCS5_PBKDF2_HMAC(reinterpret_cast<unsigned char*>(password8Bit.data()), password8Bit.size(), reinterpret_cast<unsigned char*>(salt.data()), BACKUP_SALT_BYTES, BACKUP_KEY_PBKDF_ITERATIONS, BACKUP_ENCRYPTION_KEY_BYTES, reinterpret_cast<unsigned char*>(encryptionKey.data()));

	QByteArray nonceBytes(crypto_stream_NONCEBYTES, 0x00);

	// The backup content
	QByteArray clientId(IdentityHelper::uint64ToIdentityString(getClientIdentity().getContactId()).toLatin1());
	if (clientId.size() != BACKUP_IDENTITY_BYTES) {
		throw InternalErrorException() << QString("Could not build backup - invalid client identity length (%1 vs. %2 Bytes).").arg(clientId.size()).arg(BACKUP_IDENTITY_BYTES).toStdString();
	}
	QByteArray clientSecKey(getClientLongTermKeyPair().getPrivateKey());
	if (clientSecKey.size() != PROTO_KEY_LENGTH_BYTES) {
		throw InternalErrorException() << QString("Could not build backup - invalid client secret key length (%1 vs. %2 Bytes).").arg(clientSecKey.size()).arg(PROTO_KEY_LENGTH_BYTES).toStdString();
	}

	QByteArray backup(salt);
	backup.append(clientId);
	backup.append(clientSecKey);

	// Compute Hash
	QByteArray controlHash(crypto_hash_sha256_BYTES, 0x00);
	crypto_hash_sha256(reinterpret_cast<unsigned char*>(controlHash.data()), reinterpret_cast<unsigned char*>(backup.data() + BACKUP_SALT_BYTES), BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES);
	backup.append(controlHash.left(BACKUP_HASH_BYTES));

	if (backup.size() != (BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + BACKUP_HASH_BYTES)) {
		throw InternalErrorException() << QString("Could not build backup - invalid packet length (%1 vs. %2 Bytes).").arg(clientSecKey.size()).arg(BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + BACKUP_HASH_BYTES).toStdString();
	}

	// The Backup is build from SALT + IDENTITY + KEY + HASH
	crypto_stream_xor(reinterpret_cast<unsigned char*>(backup.data() + BACKUP_SALT_BYTES), reinterpret_cast<unsigned char*>(backup.data() + BACKUP_SALT_BYTES), BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + BACKUP_HASH_BYTES, reinterpret_cast<unsigned char*>(nonceBytes.data()), reinterpret_cast<unsigned char*>(encryptionKey.data()));

	// Encode in Base32
	return Base32::encodeBase32Sequence(backup);
}