feat(checksum): --checksum-choice/--cc and --checksum-seed for whole-file digest
Adds real algorithm selection (xxh64 default, plus md5 via OpenSSL EVP) and a 64-bit seed for the per-file whole-file digest used by the --incremental/ --checksum handshake and basis-dir content verification. The seed also feeds the delta path's per-block xxHash32 strong checksum (low 32 bits) so an explicit seed deterministically changes those digests too. Sender and receiver hash identically: the algorithm id and seed cross the config wire frame and the STATUS_CHECK handshake now carries a length-prefixed, bounded digest instead of a fixed 64-bit value. Unsupported algorithm names are rejected at parse time (never a silent no-op). PROTOCOL_VERSION bumped 2.9.0 -> 2.10.0; defaults (xxh64, seed 0) preserve prior byte-for-byte behavior.
This commit is contained in:
@@ -733,12 +733,18 @@ static int incremental_check(Client* client, File* file, const Config* config,
|
||||
if (!send_n_data(client->file_descriptor, &mtime_nsec, sizeof(mtime_nsec)))
|
||||
return -1;
|
||||
/* With alternate basis directories the receiver must be able to verify the
|
||||
* content of every candidate basis file, so the sender supplies its xxHash64
|
||||
* for every file even when --checksum was not requested. */
|
||||
* content of every candidate basis file, so the sender supplies its whole-file
|
||||
* digest (computed with the negotiated --checksum-choice algorithm and
|
||||
* --checksum-seed) for every file even when --checksum was not requested. */
|
||||
if (config->checksum || config_has_basis(config)) {
|
||||
uint64_t checksum;
|
||||
if (!file_checksum(file, &checksum) ||
|
||||
!send_n_data(client->file_descriptor, &checksum, sizeof(checksum)))
|
||||
uint8_t digest[CHECKSUM_MAX_DIGEST_LEN];
|
||||
size_t digest_len = 0;
|
||||
if (!file_checksum(file, (ChecksumAlgo)config->checksum_algo, config->checksum_seed, digest,
|
||||
sizeof(digest), &digest_len))
|
||||
return -1;
|
||||
uint8_t wire_len = (uint8_t)digest_len;
|
||||
if (!send_n_data(client->file_descriptor, &wire_len, sizeof(wire_len)) ||
|
||||
!send_n_data(client->file_descriptor, digest, wire_len))
|
||||
return -1;
|
||||
}
|
||||
Status s;
|
||||
@@ -774,7 +780,8 @@ static int incremental_check(Client* client, File* file, const Config* config,
|
||||
}
|
||||
|
||||
static int send_delta(Client* client, File* file, DeltaSignature* sig, Config* config) {
|
||||
Delta* delta = delta_compute(file->data->data, file->data->size, sig, config->delta_block_size);
|
||||
Delta* delta = delta_compute_seeded(file->data->data, file->data->size, sig,
|
||||
config->delta_block_size, (uint32_t)config->checksum_seed);
|
||||
/* The receiver is blocked after sending the signature. Every local
|
||||
fallback therefore needs the explicit NEXT response before full data. */
|
||||
if (!delta)
|
||||
|
||||
Reference in New Issue
Block a user