Digest-QuickXor
view release on metacpan or search on metacpan
/*
* libquickxor - QuickXorHash Library
*
* © 2019 by Tekki (Rolf Stöckli)
*
* The original C# algorithm was published by Microsoft under the following copyright:
*
* Copyright (c) 2016 Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, andor sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*/
#include <stdio.h>
#include <string.h>
#include "qxhash.h"
#include "base64.h"
QX* QX_new() {
QX* pqx = NULL;
pqx = calloc(1, sizeof(QX));
if (pqx) {
pqx->kDataLength = QX_DATA_LENGTH;
pqx->kShift = QX_SHIFT;
pqx->kWidthInBits = QX_WIDTH_IN_BITS;
pqx->kWidthInBytes = QX_WIDTH_IN_BYTES;
}
return pqx;
}
void QX_add(QX* pqx, uint8_t* addData, size_t addSize) {
// the bitvector where we'll start xoring
size_t vectorArrayIndex = pqx->shiftSoFar / 64;
// the position within the bit vector at which we begin xoring
int vectorOffset = pqx->shiftSoFar % 64;
size_t iterations = addSize > pqx->kWidthInBits ? pqx->kWidthInBits : addSize;
for (size_t i = 0; i < iterations; ++i) {
size_t nextCell = vectorArrayIndex + 1;
int bitsInVectorCell = 64;
if (nextCell == pqx->kDataLength) {
nextCell = 0;
if (pqx->kWidthInBits % 64 > 0) {
bitsInVectorCell = pqx->kWidthInBits % 64;
}
}
uint8_t xoredByte = 0x0;
for (size_t j = i; j < addSize; j += pqx->kWidthInBits) {
xoredByte ^= addData[j];
}
pqx->data[vectorArrayIndex] ^= ((uint64_t)xoredByte) << vectorOffset;
if (vectorOffset > bitsInVectorCell - 8) {
pqx->data[nextCell] ^= ((uint64_t)xoredByte) >> (bitsInVectorCell - vectorOffset);
}
vectorOffset += pqx->kShift;
if (vectorOffset >= bitsInVectorCell) {
vectorArrayIndex = nextCell;
vectorOffset -= bitsInVectorCell;
}
}
// update the starting position in a circular shift pattern
pqx->shiftSoFar += pqx->kShift * (addSize % pqx->kWidthInBits);
pqx->shiftSoFar %= pqx->kWidthInBits;
pqx->lengthSoFar += addSize;
}
char* QX_b64digest(QX* pqx) {
uint8_t* digest = NULL;
size_t hashSize;
char* hash = NULL;
digest = QX_digest(pqx);
hashSize = 2 * pqx->kWidthInBytes;
hash = calloc(1, hashSize);
if (digest && hash) {
B64_encode(digest, pqx->kWidthInBytes, hash, hashSize);
}
free(digest);
digest = NULL;
return hash;
}
uint8_t* QX_digest(QX* pqx) {
uint8_t* digest = NULL;
uint8_t* digestLength = NULL;
size_t lengthSize = sizeof(pqx->lengthSoFar);
// create a byte array big enough to hold all our data
digest = calloc(1, pqx->kWidthInBytes);
( run in 0.499 second using v1.01-cache-2.11-cpan-71847e10f99 )