text:
Harness

This adds a command line utility, some helper scripts, and unit tests to validate the algorithm.
make
cd tests
./runtests.sh ../HohhaHarness

The helper scripts use python3 - install it if you don't already have it.

I am really sorry but, I can't accept it at the moment.
I am making some minor but important improvements.
Not in essential algorithm format, but in "Hohha Communication package format".
For a long time, I've been working for Javascript impelementation details, I couldn't have time to work on C implementation.
I will publish it when it will be ready.

No problem.

Will you be developing the javascript in the open?

Will you show the work in progress before it is ready?
Would you accept contributions to the code you are working on?

Is the package format the same as here? (If not, can you describe the new format)

8 bytes salt
4 bytes crc
2 bytes length
1 byte left pad length
(encrypted from here to the end of the packet)
left padding
message
right padding

What if I resubmit this so that the tool works with the package/packet format?

Including unit tests for the package/packet format, so that this and the new javascript implementation can be validated with the same tests.
To prove that the two implementations are the same algorithm, and can work together with the same formats.

Give me a couple of days, I will submit the latest format.
I haven't changed many things.
The new Hohha Communication packet format will be:
typedef struct attribute((packed)) {
// AlignedLenSize;
//   Highest 1 bit(&128) : 1->Packet is encrypted 0->Packet is NOT encrypted
//   Low 3 bits(&7) : 1 --> Aligned length is between 0..255; 2-> 255..65535 3->0..2^24-1 4-> 65536..2^32-1 THIS VALUE IS NEVER ENCRYPTED
uint8_t AlignedLenSize;
uint8_t Salt[SALT_SIZE]; // Salt value unique for packet
uint32_t PlaintextCRC; // Plaintext CRC value to check integrity of the packet LITTLE ENDIAN
uint8_t Padding; // LeftPad + RightPad
uint8_t AlignedLen[8]; // Plaintext or ciphertext aligned length. May be 1,2,3,4 or 8 bytes!!! 8 BYTES IS NOT IMPLEMENTED!
} THohhaPacketHeader;
I realized that, if I don't encrypt the aligned length of the packet, it will be better for various reasons..
But padding length will be encrypted on the header.
Thank you for your contributions. And of course, every contributions are wellcome.
I haven't extensively tested yet, but, here is the code if you want to play with:(If you want, make your modifications based on this code and re-send it)
/*B.
Hohha Dynamic XOR Algorithm. Copyright (c) 2015 İsmail Kizir
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,
and/or 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.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Alternatively you can use and distribute this file under the terms of the GNU General Public License
*/
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/time.h>
#include <inttypes.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
// Portable endian macros by Mathias Panzenböck
#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(WINDOWS)
define WINDOWS
#endif
#if defined(linux) || defined(CYGWIN)
include <endian.h>
#elif defined(APPLE)
include <libkern/OSByteOrder.h>
define htobe16(x) OSSwapHostToBigInt16(x)
define htole16(x) OSSwapHostToLittleInt16(x)
define be16toh(x) OSSwapBigToHostInt16(x)
define le16toh(x) OSSwapLittleToHostInt16(x)
define htobe32(x) OSSwapHostToBigInt32(x)
define htole32(x) OSSwapHostToLittleInt32(x)
define be32toh(x) OSSwapBigToHostInt32(x)
define le32toh(x) OSSwapLittleToHostInt32(x)
define htobe64(x) OSSwapHostToBigInt64(x)
define htole64(x) OSSwapHostToLittleInt64(x)
define be64toh(x) OSSwapBigToHostInt64(x)
define le64toh(x) OSSwapLittleToHostInt64(x)
define __BYTE_ORDER    BYTE_ORDER
define __BIG_ENDIAN    BIG_ENDIAN
define __LITTLE_ENDIAN LITTLE_ENDIAN
define __PDP_ENDIAN    PDP_ENDIAN
#elif defined(OpenBSD)
include <sys/endian.h>
#elif defined(NetBSD) || defined(FreeBSD) || defined(DragonFly)
include <sys/endian.h>
define be16toh(x) betoh16(x)
define le16toh(x) letoh16(x)
define be32toh(x) betoh32(x)
define le32toh(x) letoh32(x)
define be64toh(x) betoh64(x)
define le64toh(x) letoh64(x)
#elif defined(WINDOWS)
include <winsock2.h>
include <sys/param.h>
if BYTE_ORDER == LITTLE_ENDIAN
define htobe16(x) htons(x)
define htole16(x) (x)
define be16toh(x) ntohs(x)
define le16toh(x) (x)
define htobe32(x) htonl(x)
define htole32(x) (x)
define be32toh(x) ntohl(x)
define le32toh(x) (x)
define htobe64(x) htonll(x)
define htole64(x) (x)
define be64toh(x) ntohll(x)
define le64toh(x) (x)
elif BYTE_ORDER == BIG_ENDIAN
	/* that would be xbox 360 */

define htobe16(x) (x)
define htole16(x) __builtin_bswap16(x)
define be16toh(x) (x)
define le16toh(x) __builtin_bswap16(x)
define htobe32(x) (x)
define htole32(x) __builtin_bswap32(x)
define be32toh(x) (x)
define le32toh(x) __builtin_bswap32(x)
define htobe64(x) (x)
define htole64(x) __builtin_bswap64(x)
define be64toh(x) (x)
define le64toh(x) __builtin_bswap64(x)
else
error byte order not supported
endif
define __BYTE_ORDER    BYTE_ORDER
define __BIG_ENDIAN    BIG_ENDIAN
define __LITTLE_ENDIAN LITTLE_ENDIAN
define __PDP_ENDIAN    PDP_ENDIAN
#else
error platform not supported
#endif
/* ---------------------------- BASE64 ENCODE/DECODE FUNCTIONS -------------------------------------
/
/
cencoder.c - c source to a base64 encoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
typedef enum
{
step_A, step_B, step_C
} base64_encodestep;
typedef struct
{
base64_encodestep step;
char result;
int stepcount;
} base64_encodestate;
typedef enum
{
step_a, step_b, step_c, step_d
} base64_decodestep;
typedef struct
{
base64_decodestep step;
char plainchar;
} base64_decodestate;
const int CHARS_PER_LINE = 72;
void base64_init_encodestate(base64_encodestate* state_in)
{
state_in->step = step_A;
state_in->result = 0;
state_in->stepcount = 0;
}
char base64_encode_value(char value_in)
{
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (value_in > 63) return '=';
return encoding[(int)value_in];
}
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
{
const char* plainchar = plaintext_in;
const char* const plaintextend = plaintext_in + length_in;
char* codechar = code_out;
char result;
char fragment;
result = state_in->result;

switch (state_in->step)
{
	while (1)
	{
case step_A:
		if (plainchar == plaintextend)
		{
			state_in->result = result;
			state_in->step = step_A;
			return codechar - code_out;
		}
		fragment = *plainchar++;
		result = (fragment & 0x0fc) >> 2;
		*codechar++ = base64_encode_value(result);
		result = (fragment & 0x003) << 4;
case step_B:
		if (plainchar == plaintextend)
		{
			state_in->result = result;
			state_in->step = step_B;
			return codechar - code_out;
		}
		fragment = *plainchar++;
		result |= (fragment & 0x0f0) >> 4;
		*codechar++ = base64_encode_value(result);
		result = (fragment & 0x00f) << 2;
case step_C:
		if (plainchar == plaintextend)
		{
			state_in->result = result;
			state_in->step = step_C;
			return codechar - code_out;
		}
		fragment = *plainchar++;
		result |= (fragment & 0x0c0) >> 6;
		*codechar++ = base64_encode_value(result);
		result  = (fragment & 0x03f) >> 0;
		*codechar++ = base64_encode_value(result);

		++(state_in->stepcount);
		if (state_in->stepcount == CHARS_PER_LINE/4)
		{
			//*codechar++ = '\n';
			state_in->stepcount = 0;
		}
	}
}
/* control should not reach here */
return codechar - code_out;

}
int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
{
char* codechar = code_out;
switch (state_in->step)
{
case step_B:
	*codechar++ = base64_encode_value(state_in->result);
	*codechar++ = '=';
	*codechar++ = '=';
	break;
case step_C:
	*codechar++ = base64_encode_value(state_in->result);
	*codechar++ = '=';
	break;
case step_A:
	break;
}
//*codechar++ = '\n';

return codechar - code_out;

}
int base64_decode_value(char value_in)
{
static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
static const char decoding_size = sizeof(decoding);
value_in -= 43;
if (value_in < 0 || value_in >= decoding_size) return -1;
return decoding[(int)value_in];
}
void base64_init_decodestate(base64_decodestate* state_in)
{
state_in->step = step_a;
state_in->plainchar = 0;
}
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in)
{
const char* codechar = code_in;
char* plainchar = plaintext_out;
char fragment;
*plainchar = state_in->plainchar;

switch (state_in->step)
{
	while (1)
	{
case step_a:
		do {
			if (codechar == code_in+length_in)
			{
				state_in->step = step_a;
				state_in->plainchar = *plainchar;
				return plainchar - plaintext_out;
			}
			fragment = (char)base64_decode_value(*codechar++);
		} while (fragment < 0);
		*plainchar    = (fragment & 0x03f) << 2;
case step_b:
		do {
			if (codechar == code_in+length_in)
			{
				state_in->step = step_b;
				state_in->plainchar = *plainchar;
				return plainchar - plaintext_out;
			}
			fragment = (char)base64_decode_value(*codechar++);
		} while (fragment < 0);
		*plainchar++ |= (fragment & 0x030) >> 4;
		*plainchar    = (fragment & 0x00f) << 4;
case step_c:
		do {
			if (codechar == code_in+length_in)
			{
				state_in->step = step_c;
				state_in->plainchar = *plainchar;
				return plainchar - plaintext_out;
			}
			fragment = (char)base64_decode_value(*codechar++);
		} while (fragment < 0);
		*plainchar++ |= (fragment & 0x03c) >> 2;
		*plainchar    = (fragment & 0x003) << 6;
case step_d:
		do {
			if (codechar == code_in+length_in)
			{
				state_in->step = step_d;
				state_in->plainchar = *plainchar;
				return plainchar - plaintext_out;
			}
			fragment = (char)base64_decode_value(*codechar++);
		} while (fragment < 0);
		*plainchar++   |= (fragment & 0x03f);
	}
}
/* control should not reach here */
return plainchar - plaintext_out;

}
char Base64Encode(const char input, uint32_t inputlen)
{
/* set up a destination buffer large enough to hold the encoded data /
char output = (char*)malloc(8 + (inputlen * 4)/3);
/* keep track of our encoded position /
char c = output;
/* store the number of bytes encoded by a single call /
int cnt = 0;
/ we need an encoder state */
base64_encodestate s;
/---------- START ENCODING ----------/
/* initialise the encoder state /
base64_init_encodestate(&s);
/ gather data from the input and send it to the output /
cnt = base64_encode_block(input, inputlen, c, &s);
c += cnt;
/ since we have encoded the entire input string, we know that
there is no more input data; finalise the encoding /
cnt = base64_encode_blockend(c, &s);
c += cnt;
/---------- STOP ENCODING  ----------*/
/* we want to print the encoded data, so null-terminate it: */
*c = 0;
return output;
}
char Base64Decode(const char input)
{
/* set up a destination buffer large enough to hold the encoded data /
unsigned ilen = strlen(input);
char output = (char*)malloc(ilen);
/* keep track of our decoded position /
char c = output;
/* store the number of bytes decoded by a single call /
int cnt = 0;
/ we need a decoder state */
base64_decodestate s;
/---------- START DECODING ----------/
/* initialise the decoder state /
base64_init_decodestate(&s);
/ decode the input data /
cnt = base64_decode_block(input, ilen, c, &s);
c += cnt;
/ note: there is no base64_decode_blockend! /
/---------- STOP DECODING  ----------*/
/* we want to print the decoded data, so null-terminate it: */
*c = 0;
return output;
}
/* ---------------------------- BASE64 ENCODE/DECODE FUNCTIONS ENDS HERE -------------------------------------
*/
/* ---------------- utility fncs */
uint32_t GetElapsedTimeInMilliSeconds(struct timeval *StartTime)
{
struct timeval Now;
gettimeofday (&Now, NULL);
return (Now.tv_sec - StartTime->tv_sec) * 1000 + (Now.tv_usec - StartTime->tv_usec) / 1000;
}
double PrintElapsedTime(struct timeval StartTime, unsigned long long int TotalProcessedBytes)
{
double TotalMBytes = ((double)TotalProcessedBytes/(1024.01024));
unsigned EInMs = GetElapsedTimeInMilliSeconds(StartTime);
double Average = TotalMBytes / (1.0 * EInMs) * 1000.0;
printf("\n\tTotal data processed: %6.2f MBytes\n\tElapsed Time: %u ms.\n\tAverage: %10.4f MBytes/secs \n",TotalMBytes, EInMs, Average);
return Average;
}
void IncByOne(uint8_t *Buf, uint32_t BufLen)
{
unsigned t;
for (t=0; t<BufLen; t++)
Buf[t]++;
}
uint8_t *CreateDataBuf(Size)
{
uint8_t *B;
B = (uint8_t *)calloc(1, Size);
if (B == NULL)
{
printf("Out of memory!");
exit(-1);
}
return B;
}
static const unsigned int CRC32Table[256] = {
0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351
};
unsigned int digital_update_crc32(unsigned int crc, const unsigned char *data, size_t len)
{
while (len--)
{
crc = CRC32Table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8);
data++;
}
return crc;
}
unsigned int digital_crc32(uint8_t *buf, size_t len)
{
return digital_update_crc32(0xffffffff, buf, len) ^ 0xffffffff;
}
/* ------------------------- END CRC UTILITY FUNCTIONS ----------------- */
#define RANDOM_BUF_SIZE 8192
uint8_t RandomBuf[RANDOM_BUF_SIZE];
uint32_t RandomBufStartPos=999999999; // It must be a number greater than RANDOM_BUF_SIZE for initialization
void ReadRandomBytesFromUDEv(uint32_t ByteCount, uint8_t *Buffer)
{
FILE *fp;
fp = fopen("/dev/urandom", "r");
if (!fp)
{
fprintf(stderr, "\n\nERROR OPENING /dev/urandom!!!!\n\n");
exit(-1);
}
fread(Buffer, ByteCount, 1, fp);
fclose(fp);
}
void RandomizeBuffer()
{
#ifdef VERBOSE
printf("Randomizing ... \n");
#endif
RandomBufStartPos=0;
ReadRandomBytesFromUDEv(RANDOM_BUF_SIZE, RandomBuf);
}
void GetRandomNumbers(uint32_t ByteCount, uint8_t *Buffer)
{
if (RANDOM_BUF_SIZE < ByteCount)
{
ReadRandomBytesFromUDEv(ByteCount, Buffer);
return;
}
if (RANDOM_BUF_SIZE < RandomBufStartPos+ByteCount)
RandomizeBuffer();
memcpy(Buffer, RandomBuf + RandomBufStartPos, ByteCount);
RandomBufStartPos += ByteCount;
}
uint8_t GetRandomUInt8(void)
{
if (RandomBufStartPos >= RANDOM_BUF_SIZE)
RandomizeBuffer();
return RandomBuf[RandomBufStartPos++];
}
uint32_t GetRandomUInt32(void)
{
if (RandomBufStartPos+sizeof(uint32_t) > RANDOM_BUF_SIZE)
RandomizeBuffer();
RandomBufStartPos += sizeof(uint32_t);
return *((uint32_t *)(RandomBuf + RandomBufStartPos-sizeof(uint32_t)));
}
uint64_t GetRandomUInt64(void)
{
if (RandomBufStartPos+sizeof(uint64_t) > RANDOM_BUF_SIZE)
RandomizeBuffer();
RandomBufStartPos += sizeof(uint64_t);
return *((uint64_t *)(RandomBuf + RandomBufStartPos-sizeof(uint64_t)));
}
// Standart C has not ROL or ROR function, but most modern cpus has instructions for circular shift operations
// This is a quick and dirty code for standart C versions and Intel Family cpu assembler optimized versions
#define GCC_INTEL_OPTIMIZED
#if defined(GCC_INTEL_OPTIMIZED)
#define ROL32_1(v) asm ("rol %0;" :"=r"(v) /* output / :"0"(v) / input / );
#define ROR32_1(v) asm ("ror %0;" :"=r"(v) / output / :"0"(v) / input */ );
#else
#define ROL32_1(v) v=(((v) << 1) | ((v) >> 31))
#define ROR32_1(v) v=(((v) >> 1) | ((v) << 31))
#endif
char *GetBinStr(uint32_t val, char *ResBuf)
{
char *p;
unsigned int t;
p = ResBuf;
t = 0x80000000; // scan 32 bits
for ( ; t > 0; t = t >> 1)
{
if (val & t)
*p++ = '1';
else *p++ = '0';
}
*p = 0;
return ResBuf;
}
/* ------------------------- END UTILITY FUNCTIONS ----------------- */
#define SALT_SIZE 8 // LEAVE AS IT IS
#define MAX_NUM_JUMPS 4 // If you change this limit, you must write proper hand optimized functions
#define FALSE (0U)
#define TRUE (!(FALSE))
#define VERBOSE
/* Function used to determine if V is unique among the first Pos elements

Used by the xorGetKey function to check particle length uniqueness
*/
#define MIN_BODY_SIZE 64
#define MAX_BODY_SIZE 256 // DO NOT SET THIS LIMIT TO MORE THAN 256 BYTES! Or you must also change encryption&decryption code for key coverage

#define SP_NUM_JUMPS 0
#define SP_BODY_LEN 1
#define SP_SALT_DATA 3
#define SP_BODY (SP_SALT_DATA+SALT_SIZE)
#define GetBodyLen(K) (K[SP_BODY_LEN] + 256 * K[SP_BODY_LEN+1])
#define GetBodyPtr(K) (K + SP_BODY)
#define GetNumJumps(K) (K[SP_NUM_JUMPS])
#define xorComputeKeyBufLen(BodyLen) (SP_BODY+BodyLen)
int xorGetKey(uint8_t NumJumps, uint32_t BodyLen, uint8_t *KeyBuf)
{
// Creates XOR key
// The first byte will be equal to NumJumps
// Following 2 bytes is key body length
// Following 4 bytes are random salt data
// Following BodyLen bytes are random numbers obtained from buffered /dev/urandom data. BODYLEN MUST BE A POWER OF 2!
// Result buffer must be enough to store key!! No error checking is done!!!
// Return negative on error; zero if successfull
if (((BodyLen-1) & BodyLen) != 0)
return -1; // Key body length must be a power of 2!
if (NumJumps < 2)
return -2; // Number of jumps must be greater than or equal to 2
if (NumJumps > MAX_NUM_JUMPS)
return -3;
if (BodyLen < MIN_BODY_SIZE)
return -4;
if (BodyLen > MAX_BODY_SIZE)
return -5;
#ifdef VERBOSE
printf("Generating key ... BodyLen: %u NumJumps: %u\n",BodyLen,NumJumps);
#endif
KeyBuf[SP_NUM_JUMPS] = (uint8_t)(NumJumps&255);
KeyBuf[SP_BODY_LEN] = (uint8_t)((BodyLen % 256) & 0xff);
KeyBuf[SP_BODY_LEN+1] = (uint8_t)((BodyLen / 256) & 0xff);
GetRandomNumbers(SALT_SIZE + BodyLen, KeyBuf + SP_SALT_DATA); // Fill 4 bytes salt data with random numbers
return 0;
}
#define xorComputeKeyCheckSum(K) digital_crc32(GetBodyPtr(K), GetBodyLen(K))
inline unsigned int CheckKeyIntegrity(uint8_t *K, size_t TotalKeyBufLen)
{
unsigned int BodyLen = GetBodyLen(K);
return (
((SP_BODY + BodyLen) == TotalKeyBufLen) &&
(((BodyLen-1) & BodyLen) == 0) && // Key body must be a multiple of two
(BodyLen >= MIN_BODY_SIZE && BodyLen <= MAX_BODY_SIZE) &&
(GetNumJumps(K) >= 2 && GetNumJumps(K) <= MAX_NUM_JUMPS)
);
}
void xorAnalyzeKey(uint8_t *K)
{
uint32_t t;
printf("-------------------------- Shifting xor key analyze ----------------------------\nNumJumps: %u\nBodyLen: %u\nKeycrc: %u\nSalt: ",
K[0], GetBodyLen(K), xorComputeKeyCheckSum(K));
for (t=0; t < SALT_SIZE; t++)
{
printf(" %u", K[SP_SALT_DATA+t]);
}
printf("\n");
}
#if SALT_SIZE != 8
#error SALT_SIZE is not supported
#endif
/* UNOPTIMIZED VERSION for BETTER UNDERSTANDING OF THE FUNCTIONING OF THE ALGORITHM. IT IS NOT USED IN REAL LIFE. USE OPTIMIZED VERSIONS!

Encrypts or decrypts InOutBuf
KeyBuf is the raw key buffer
KeyCheckSum is 32 bit CRC checksum: Used to prevent "Related key attacks". If some bits of the key changes, entire cyphertext changes
InOutDataLen is the length of the data to be encrypted or decrypted
InOutBuf is the pointer to the data to be encrypted or decrypted
Salt(or nonce) is a 8 bytes random number array.
This logic ensures us this: An original key is created with an original salt value, for example for an online communication
for each distinct packet, in the packet header, we can transmit a specific salt value for that packet and we can encrypt it with original key and salt
when the receiver receives the packet, decrypts the new salt value with the original salt value of the key and passes that salt value to function,
and decrypts packet body with that salt value. This method prevents "known plaintext" attacks amongst others.
*/
//define DISABLE_HAND_OPTIMIZED_FNCS
uint32_t xorEncrypt(uint8_t *K, uint8_t *Salt, uint32_t KeyCheckSum, size_t InOutDataLen, uint8_t *InOutBuf)
{ // Encrypts message and returns CRC32 of the PLAINTEXT!
// SaltData is a SALT_SIZE bytes uint8 array!
// Our aim is to create maximum random output from "any" input. It may an all 0 file or all random distribution. It doesn't matter
// In order to do this, we have :
//   Salt: 8 bytes of random salt data
//   KeyChecksum: 32 bit CRC key checksum
//   Body: KeyBody bytes of key body
//   Checksum: Plaintext crc checksum
//   M: Our moving pointer on the key body, which tells us where we are
//   InOutBuf: Plaintext(or ciphertext for decryption)
// We must use those variables in order to:
//   Create maximum random output to prevent detecting a pattern on ciphertext
//   Hide the key body even if the attacker knows both the ciphertext and the plaintext
// Method:
//   Our first number to be XORed with the first plaintext byte depends on the random salt value
//   Our starting point on the key body depends on the random salt value
//   All subsequent ciphertext outputs depend on the starting values: Even attacker intercepts the ciphertext and plaintext,
//       the data gathered will not be useful to deciphher subsequent encryptions. Because, they will use different salt data.
//   To hide our key body elements
//     We XOR at least two body elements(jumps) with each other.
//     We use a third dynamic variable initially set to Key CRC and dynamically updated according to plaintext checksum
//     We update key body elements according to Salt values
//     We update salt data according to key body elements
//     Our jump start point and steps are hidden
//     We use the previous XOR values obtained to XOR with the next XOR values(chaining)
register uint32_t Salt1,Salt2;
register size_t t = InOutDataLen;
register uint8_t tt;
register uint32_t M; // This is our moving pointer on key body bytes
register uint32_t Checksum=0xffffffff, V = KeyCheckSum;
register uint32_t BodyMask = GetBodyLen(K)-1; // +1 because we will use this "Mersenne number" for & operation instead of modulus operation
register uint8_t *p;
uint8_t Body[MAX_BODY_SIZE];

memcpy(Body,K+SP_BODY, BodyMask+1);
p = InOutBuf;
// We compute our start values as much randomly as possible upon salt(or nonce or iv) value which is transmitted with every data to be encrypted or decrypted
Salt1 = ((uint32_t)(Salt[0]) | ((uint32_t)(Salt[1]) << 8) | ((uint32_t)(Salt[2]) << 16) | ((uint32_t)(Salt[3]) << 24));
Salt2 = ((uint32_t)(Salt[4]) | ((uint32_t)(Salt[5]) << 8) | ((uint32_t)(Salt[6]) << 16) | ((uint32_t)(Salt[7]) << 24));
// Our initial jump position in the key body depends on a random value
M = ((((uint32_t)Salt[3]) * ((uint32_t)Salt[7]))) & BodyMask;
while (t--)
{
// First jump point
Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^Salt2) & BodyMask;
ROL32_1(Salt2);
// Second jump point
Salt2 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt1);
M = (M^V) & BodyMask;
ROR32_1(Salt1);

// Following jumps
for (tt=2; tt<GetNumJumps(K); tt++)
{
  if (tt&1)
  {
    Salt2 ^= (uint32_t)(Body[M]);
    Body[M] = (uint8_t)(Salt1);
    M = (M^Salt1) & BodyMask;
    ROR32_1(Salt1);
  }
  else {
    Salt1 ^= (uint32_t)(Body[M]);
    Body[M] = (uint8_t)(Salt2);
    M = (M^V) & BodyMask;
    ROL32_1(Salt2);
  }
}
Checksum = CRC32Table[*p ^ ((Checksum >> 24) & 0xff)] ^ (Checksum << 8);
*p ^= ((uint8_t)(Salt1^Salt2^V));
V ^= Checksum;
ROL32_1(V);
p++;

}
return Checksum ^ 0xffffffff;
}
uint32_t xorDecrypt(uint8_t *K, uint8_t *Salt, uint32_t KeyCheckSum, size_t InOutDataLen, uint8_t *InOutBuf)
{ // Decrypts message and returns CRC32 of the PLAINTEXT
// SaltData is a 8 bytes uint8 array!
register uint32_t Salt1,Salt2;
register size_t t = InOutDataLen;
register uint8_t tt;
register uint32_t M; // This is our moving pointer on key body bytes
register uint32_t Checksum=0xffffffff, V = KeyCheckSum;
register uint32_t BodyMask = GetBodyLen(K)-1; // +1 because we will use this "Mersenne number" for & operation instead of modulus operation
register uint8_t *p;
uint8_t Body[MAX_BODY_SIZE];
memcpy(Body,K+SP_BODY, BodyMask+1);
p = InOutBuf;
// We compute our start values as much randomly as possible upon salt(or nonce or iv) value which is transmitted with every data to be encrypted or decrypted
Salt1 = (uint32_t)(Salt[0]) | ((uint32_t)(Salt[1]) << 8) | ((uint32_t)(Salt[2]) << 16) | ((uint32_t)(Salt[3]) << 24);
Salt2 = (uint32_t)(Salt[4]) | ((uint32_t)(Salt[5]) << 8) | ((uint32_t)(Salt[6]) << 16) | ((uint32_t)(Salt[7]) << 24);
// Our initial jump position in the key body depends on a random value
M = ((((uint32_t)Salt[3]) * ((uint32_t)Salt[7]))) & BodyMask;
//printf("Salt1: %u Salt2: %u M: %u\n ",Salt1,Salt2,M);
while (t--)
{
//V ^= ((uint32_t)1 << (uint32_t)(M&(uint32_t)31));
// First jump point
Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^Salt2) & BodyMask;
ROL32_1(Salt2);
// Second jump point
Salt2 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt1);
M = (M^V) & BodyMask;
ROR32_1(Salt1);

// Following jumps
for (tt=2; tt<GetNumJumps(K); tt++)
{
  if (tt&1)
  {
    Salt2 ^= (uint32_t)(Body[M]);
    Body[M] = (uint8_t)(Salt1);
    M = (M^Salt1) & BodyMask;
    ROR32_1(Salt1);
  }
  else {
    Salt1 ^= (uint32_t)(Body[M]);
    Body[M] = (uint8_t)(Salt2);
    M = (M^V) & BodyMask;
    ROL32_1(Salt2);
  }
}
*p ^= ((uint8_t)(Salt1^Salt2^V));
Checksum = CRC32Table[*p ^ ((Checksum >> 24) & 0xff)] ^ (Checksum << 8);
V ^= Checksum;
ROL32_1(V);
p++;

}
return Checksum ^ 0xffffffff;
}
#ifdef DISABLE_HAND_OPTIMIZED_FNCS
#define xorEncryptHOP2 xorEncrypt
#define xorDecryptHOP2 xorDecrypt
#define xorEncryptHOP3 xorEncrypt
#define xorEncryptHOP4 xorEncrypt
#define xorDecryptHOP3 xorDecrypt
#define xorDecryptHOP4 xorDecrypt
#else
uint32_t xorEncryptHOP2(uint8_t *K, uint8_t *Salt, uint32_t KeyCheckSum, size_t InOutDataLen, uint8_t *InOutBuf)
{
register uint32_t Salt1,Salt2;
register size_t t = InOutDataLen;
register uint32_t M; // This is our moving pointer on key body bytes
register uint32_t Checksum=0xffffffff, V = KeyCheckSum;
register uint32_t BodyMask = GetBodyLen(K)-1; // +1 because we will use this "Mersenne number" for & operation instead of modulus operation
register uint8_t *p;
uint8_t Body[MAX_BODY_SIZE];
memcpy(Body,K+SP_BODY, BodyMask+1);
p = InOutBuf;
// We compute our start values as much randomly as possible upon salt(or nonce or iv) value which is transmitted with every data to be encrypted or decrypted
Salt1 = ((uint32_t)(Salt[0]) | ((uint32_t)(Salt[1]) << 8) | ((uint32_t)(Salt[2]) << 16) | ((uint32_t)(Salt[3]) << 24));
Salt2 = ((uint32_t)(Salt[4]) | ((uint32_t)(Salt[5]) << 8) | ((uint32_t)(Salt[6]) << 16) | ((uint32_t)(Salt[7]) << 24));
// Our initial jump position in the key body depends on a random value
M = ((((uint32_t)Salt[3]) * ((uint32_t)Salt[7]))) & BodyMask;
while (t--)
{
// First jump point
Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^Salt2) & BodyMask;
ROL32_1(Salt2);
// Second jump point
Salt2 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt1);
M = (M^V) & BodyMask;
ROR32_1(Salt1);

Checksum = CRC32Table[*p ^ ((Checksum >> 24) & 0xff)] ^ (Checksum << 8);
*p ^= ((uint8_t)(Salt1^Salt2^V));
V ^= Checksum;
ROL32_1(V);
p++;

}
return Checksum ^ 0xffffffff;
}
uint32_t xorDecryptHOP2(uint8_t *K, uint8_t *Salt, uint32_t KeyCheckSum, size_t InOutDataLen, uint8_t *InOutBuf)
{
register uint32_t Salt1,Salt2;
register size_t t = InOutDataLen;
register uint32_t M; // This is our moving pointer on key body bytes
register uint32_t Checksum=0xffffffff, V = KeyCheckSum;
register uint32_t BodyMask = GetBodyLen(K)-1; // +1 because we will use this "Mersenne number" for & operation instead of modulus operation
register uint8_t *p;
uint8_t Body[MAX_BODY_SIZE];
memcpy(Body,K+SP_BODY, BodyMask+1);
p = InOutBuf;
// We compute our start values as much randomly as possible upon salt(or nonce or iv) value which is transmitted with every data to be encrypted or decrypted
Salt1 = ((uint32_t)(Salt[0]) | ((uint32_t)(Salt[1]) << 8) | ((uint32_t)(Salt[2]) << 16) | ((uint32_t)(Salt[3]) << 24));
Salt2 = ((uint32_t)(Salt[4]) | ((uint32_t)(Salt[5]) << 8) | ((uint32_t)(Salt[6]) << 16) | ((uint32_t)(Salt[7]) << 24));
// Our initial jump position in the key body depends on a random value
M = ((((uint32_t)Salt[3]) * ((uint32_t)Salt[7]))) & BodyMask;
//printf("Salt1: %u Salt2: %u M: %u\n ",Salt1,Salt2,M);
while (t--)
{
// First jump point
Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^Salt2) & BodyMask;
ROL32_1(Salt2);
// Second jump point
Salt2 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt1);
M = (M^V) & BodyMask;
ROR32_1(Salt1);

*p ^= ((uint8_t)(Salt1^Salt2^V));
Checksum = CRC32Table[*p ^ ((Checksum >> 24) & 0xff)] ^ (Checksum << 8);
V ^= Checksum;
ROL32_1(V);
p++;

}
return Checksum ^ 0xffffffff;
}
uint32_t xorEncryptHOP3(uint8_t *K, uint8_t *Salt, uint32_t KeyCheckSum, size_t InOutDataLen, uint8_t *InOutBuf)
{
register uint32_t Salt1,Salt2;
register size_t t = InOutDataLen;
register uint32_t M; // This is our moving pointer on key body bytes
register uint32_t Checksum=0xffffffff, V = KeyCheckSum;
register uint32_t BodyMask = GetBodyLen(K)-1; // +1 because we will use this "Mersenne number" for & operation instead of modulus operation
register uint8_t *p;
uint8_t Body[MAX_BODY_SIZE];
memcpy(Body,K+SP_BODY, BodyMask+1);
p = InOutBuf;
// We compute our start values as much randomly as possible upon salt(or nonce or iv) value which is transmitted with every data to be encrypted or decrypted
Salt1 = ((uint32_t)(Salt[0]) | ((uint32_t)(Salt[1]) << 8) | ((uint32_t)(Salt[2]) << 16) | ((uint32_t)(Salt[3]) << 24));
Salt2 = ((uint32_t)(Salt[4]) | ((uint32_t)(Salt[5]) << 8) | ((uint32_t)(Salt[6]) << 16) | ((uint32_t)(Salt[7]) << 24));
// Our initial jump position in the key body depends on a random value
M = ((((uint32_t)Salt[3]) * ((uint32_t)Salt[7]))) & BodyMask;
while (t--)
{
// First jump point
Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^Salt2) & BodyMask;
ROL32_1(Salt2);
// Second jump point
Salt2 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt1);
M = (M^V) & BodyMask;
ROR32_1(Salt1);

Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^V) & BodyMask;
ROL32_1(Salt2);

Checksum = CRC32Table[*p ^ ((Checksum >> 24) & 0xff)] ^ (Checksum << 8);
*p ^= ((uint8_t)(Salt1^Salt2^V));
V ^= Checksum;
ROL32_1(V);
p++;

}
return Checksum ^ 0xffffffff;
}
uint32_t xorDecryptHOP3(uint8_t *K, uint8_t *Salt, uint32_t KeyCheckSum, size_t InOutDataLen, uint8_t *InOutBuf)
{
register uint32_t Salt1,Salt2;
register size_t t = InOutDataLen;
register uint32_t M; // This is our moving pointer on key body bytes
register uint32_t Checksum=0xffffffff, V = KeyCheckSum;
register uint32_t BodyMask = GetBodyLen(K)-1; // +1 because we will use this "Mersenne number" for & operation instead of modulus operation
register uint8_t *p;
uint8_t Body[MAX_BODY_SIZE];
memcpy(Body,K+SP_BODY, BodyMask+1);
p = InOutBuf;
// We compute our start values as much randomly as possible upon salt(or nonce or iv) value which is transmitted with every data to be encrypted or decrypted
Salt1 = ((uint32_t)(Salt[0]) | ((uint32_t)(Salt[1]) << 8) | ((uint32_t)(Salt[2]) << 16) | ((uint32_t)(Salt[3]) << 24));
Salt2 = ((uint32_t)(Salt[4]) | ((uint32_t)(Salt[5]) << 8) | ((uint32_t)(Salt[6]) << 16) | ((uint32_t)(Salt[7]) << 24));
// Our initial jump position in the key body depends on a random value
M = ((((uint32_t)Salt[3]) * ((uint32_t)Salt[7]))) & BodyMask;
while (t--)
{
// First jump point
Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^Salt2) & BodyMask;
ROL32_1(Salt2);
// Second jump point
Salt2 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt1);
M = (M^V) & BodyMask;
ROR32_1(Salt1);

Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^V) & BodyMask;
ROL32_1(Salt2);

*p ^= ((uint8_t)(Salt1^Salt2^V));
Checksum = CRC32Table[*p ^ ((Checksum >> 24) & 0xff)] ^ (Checksum << 8);
V ^= Checksum;
ROL32_1(V);
p++;

}
return Checksum ^ 0xffffffff;
}
uint32_t xorEncryptHOP4(uint8_t *K, uint8_t *Salt, uint32_t KeyCheckSum, size_t InOutDataLen, uint8_t *InOutBuf)
{
register uint32_t Salt1,Salt2;
register size_t t = InOutDataLen;
register uint32_t M; // This is our moving pointer on key body bytes
register uint32_t Checksum=0xffffffff, V = KeyCheckSum;
register uint32_t BodyMask = GetBodyLen(K)-1; // +1 because we will use this "Mersenne number" for & operation instead of modulus operation
register uint8_t *p;
uint8_t Body[MAX_BODY_SIZE];
memcpy(Body,K+SP_BODY, BodyMask+1);
p = InOutBuf;
// We compute our start values as much randomly as possible upon salt(or nonce or iv) value which is transmitted with every data to be encrypted or decrypted
Salt1 = ((uint32_t)(Salt[0]) | ((uint32_t)(Salt[1]) << 8) | ((uint32_t)(Salt[2]) << 16) | ((uint32_t)(Salt[3]) << 24));
Salt2 = ((uint32_t)(Salt[4]) | ((uint32_t)(Salt[5]) << 8) | ((uint32_t)(Salt[6]) << 16) | ((uint32_t)(Salt[7]) << 24));
// Our initial jump position in the key body depends on a random value
M = ((((uint32_t)Salt[3]) * ((uint32_t)Salt[7]))) & BodyMask;
while (t--)
{
// First jump point
Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^Salt2) & BodyMask;
ROL32_1(Salt2);
// Second jump point
Salt2 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt1);
M = (M^V) & BodyMask;
ROR32_1(Salt1);

// Following jumps
Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^V) & BodyMask;
ROL32_1(Salt2);

Salt2 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt1);
M = (M^Salt1) & BodyMask;
ROR32_1(Salt1);

Checksum = CRC32Table[*p ^ ((Checksum >> 24) & 0xff)] ^ (Checksum << 8);
*p ^= ((uint8_t)(Salt1^Salt2^V));
V ^= Checksum;
ROL32_1(V);
p++;

}
return Checksum ^ 0xffffffff;
}
uint32_t xorDecryptHOP4(uint8_t *K, uint8_t *Salt, uint32_t KeyCheckSum, size_t InOutDataLen, uint8_t *InOutBuf)
{
register uint32_t Salt1,Salt2;
register size_t t = InOutDataLen;
register uint32_t M; // This is our moving pointer on key body bytes
register uint32_t Checksum=0xffffffff, V = KeyCheckSum;
register uint32_t BodyMask = GetBodyLen(K)-1; // +1 because we will use this "Mersenne number" for & operation instead of modulus operation
register uint8_t *p;
uint8_t Body[MAX_BODY_SIZE];
memcpy(Body,K+SP_BODY, BodyMask+1);
p = InOutBuf;
// We compute our start values as much randomly as possible upon salt(or nonce or iv) value which is transmitted with every data to be encrypted or decrypted
Salt1 = ((uint32_t)(Salt[0]) | ((uint32_t)(Salt[1]) << 8) | ((uint32_t)(Salt[2]) << 16) | ((uint32_t)(Salt[3]) << 24));
Salt2 = ((uint32_t)(Salt[4]) | ((uint32_t)(Salt[5]) << 8) | ((uint32_t)(Salt[6]) << 16) | ((uint32_t)(Salt[7]) << 24));
// Our initial jump position in the key body depends on a random value
M = ((((uint32_t)Salt[3]) * ((uint32_t)Salt[7]))) & BodyMask;
while (t--)
{
// First jump point
Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^Salt2) & BodyMask;
ROL32_1(Salt2);
// Second jump point
Salt2 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt1);
M = (M^V) & BodyMask;
ROR32_1(Salt1);

// Following jumps
Salt1 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt2);
M = (M^V) & BodyMask;
ROL32_1(Salt2);

Salt2 ^= (uint32_t)(Body[M]);
Body[M] = (uint8_t)(Salt1);
M = (M^Salt1) & BodyMask;
ROR32_1(Salt1);

*p ^= ((uint8_t)(Salt1^Salt2^V));
Checksum = CRC32Table[*p ^ ((Checksum >> 24) & 0xff)] ^ (Checksum << 8);
V ^= Checksum;
ROL32_1(V);
p++;

}
return Checksum ^ 0xffffffff;
}
typedef uint32_t (*THOPEncryptorFnc)(uint8_t *Key, uint8_t *Salt, uint32_t KeyCheckSum, size_t InOutDataLen, uint8_t *InOutBuf);
typedef uint32_t (*THOPDecryptorFnc)(uint8_t *Key, uint8_t *Salt, uint32_t KeyCheckSum, size_t InOutDataLen, uint8_t *InOutBuf);
static inline THOPEncryptorFnc xorGetProperHOPEncryptorFnc(uint8_t *Key)
{
if (GetNumJumps(Key) == 2)
return &xorEncryptHOP2;
if (GetNumJumps(Key) == 3)
return &xorEncryptHOP3;
if (GetNumJumps(Key) == 4)
return &xorEncryptHOP4;
return NULL;
}
static inline THOPDecryptorFnc xorGetProperHOPDecryptorFnc(uint8_t Key)
{
if (GetNumJumps(Key) == 2)
return &xorDecryptHOP2;
if (GetNumJumps(Key) == 3)
return &xorDecryptHOP3;
if (GetNumJumps(Key) == 4)
return &xorDecryptHOP4;
return NULL;
}
/ --------------------- HOHHA PROTOCOL SPECIFIC FUNCTIONS --------------- */
// Hohha communication header structure:
// 1 byte AlignedLenSize which describes the size of the variable which describes the length of the plaintext body, in bytes
// 8 bytes packet salt value for encryption
// 4 bytes -> Plaintext checksum
// 1 byte Left padding(number of random characters) before the real plaintext or ciphertext
// AlignedLenSize bytes for packet plaintext length(low byte first)
#define ALIGN_TO(v,n) ((uint32_t)((v)+(n)-1) & (uint32_t)(0xffffffff - (n - 1)))
typedef struct attribute((packed)) {
// AlignedLenSize;
//   Highest 1 bit(&128) : 1->Packet is encrypted 0->Packet is NOT encrypted
//   Low 3 bits(&7) : 1 --> Aligned length is between 0..255; 2-> 255..65535 3->0..2^24-1 4-> 65536..2^32-1 THIS VALUE IS NEVER ENCRYPTED
uint8_t AlignedLenSize;
uint8_t Salt[SALT_SIZE]; // Salt value unique for packet
uint32_t PlaintextCRC; // Plaintext CRC value to check integrity of the packet LITTLE ENDIAN
uint8_t Padding; // LeftPad + RightPad
uint8_t AlignedLen[8]; // Plaintext or ciphertext aligned length. May be 1,2,3,4 or 8 bytes!!! 8 BYTES IS NOT IMPLEMENTED!
} THohhaPacketHeader;
//#define HHLEN sizeof(THohhaPacketHeader)
static inline uint8_t GetAlignedLenSize(size_t AlignedLen)
{
if (AlignedLen < (1<<8))
return 1;
if (AlignedLen < (1<<16))
return 2;
if (AlignedLen < (1<<24))
return 3;
if (AlignedLen <= 0xffffffff)
return 4;
return 8;
}
static inline size_t GetCommHeaderLenByAlignedLenSize(uint8_t AlignedLenSize)
{
return sizeof(THohhaPacketHeader) - 8 + AlignedLenSize;
}
static inline unsigned int GetCommHeaderLenByAlignedLen(unsigned int AlignedLen)
{
return GetCommHeaderLenByAlignedLenSize(GetAlignedLenSize(AlignedLen));
}
static inline unsigned int GetCommHeaderLenByHeader(THohhaPacketHeader *Hdr)
{
return GetCommHeaderLenByAlignedLenSize(Hdr->AlignedLenSize & 7);
}
#define HOHHA_TOTAL_COMM_PACKET_SIZE(DataSize,DataAlignment) ((ALIGN_TO(DataSize,DataAlignment)) + GetCommHeaderLenByAlignedLen(DataSize))
#define HOHHA_TOTAL_COMM_PACKET_SIZE_WITHOUT_ENCRYPTION(DataSize) ((DataSize) + GetCommHeaderLenByAlignedLen(DataSize))
// This function sets the exact ciphertext or plaintext length on the hohha communication header
static inline void SetHeaderAlignedLenValue(THohhaPacketHeader *PacketHeader, unsigned int AlignedDataLen)
{
uint8_t AlignedLenSize = GetAlignedLenSize(AlignedDataLen);
PacketHeader->AlignedLenSize = AlignedLenSize;
if (AlignedLenSize == 1)
PacketHeader->AlignedLen[0] = AlignedDataLen;
else if (AlignedLenSize == 2)
{
PacketHeader->AlignedLen[0] = (uint8_t)(AlignedDataLen >> 8);
PacketHeader->AlignedLen[1] = (uint8_t)(AlignedDataLen & 0xff);
}
else if (AlignedLenSize == 3)
{
PacketHeader->AlignedLen[0] = (uint8_t)((AlignedDataLen >> 16) & 0xff);
PacketHeader->AlignedLen[1] = (uint8_t)((AlignedDataLen >> 8) & 0xff);
PacketHeader->AlignedLen[2] = (uint8_t)(AlignedDataLen & 0xff);
}
else
{
PacketHeader->AlignedLen[0] = (uint8_t)((AlignedDataLen >> 24) & 0xff);
PacketHeader->AlignedLen[1] = (uint8_t)((AlignedDataLen >> 16) & 0xff);
PacketHeader->AlignedLen[2] = (uint8_t)((AlignedDataLen >> 8) & 0xff);
PacketHeader->AlignedLen[3] = (uint8_t)(AlignedDataLen & 0xff);
}
}
// This function gets the Aligned ciphertext or plaintext length from the hohha communication header
static inline ssize_t GetHeaderAlignedLenValue(THohhaPacketHeader *PacketHeader)
{
uint8_t V = PacketHeader->AlignedLenSize & 7;
if (V == 1)
return PacketHeader->AlignedLen[0];
if (V == 2)
return ((uint32_t)(PacketHeader->AlignedLen[0]) << 8) | PacketHeader->AlignedLen[1];
if (V == 3)
return ((uint32_t)(PacketHeader->AlignedLen[0]) << 16) | ((uint32_t)(PacketHeader->AlignedLen[1]) << 8) | PacketHeader->AlignedLen[2];
if (V == 4)
return ((uint32_t)(PacketHeader->AlignedLen[0]) << 24) | ((uint32_t)(PacketHeader->AlignedLen[1]) << 16) | ((uint32_t)(PacketHeader->AlignedLen[2]) << 8) | PacketHeader->AlignedLen[3];
return -1;
}
void CreateHohhaCommunicationPacket2(uint8_t *K, uint32_t KeyCheckSum, size_t InDataLen, uint8_t *InBuf, uint32_t DataAlignment, uint8_t *OutBuf)
{ // This function encrypts InBuf and creates a communication packet with a proper header
// OutBuf must be already allocated and must be enough large to store (InDataLen-1 + HOHHA_PACKET_ALIGNMENT + HHLEN) bytes
if (!OutBuf || !(DataAlignment == 8 || DataAlignment == 16 || DataAlignment == 32 || DataAlignment == 64))
{
//printf("INVALID DATAALIGNMENT: %d\n", DataAlignment);
return;
}
uint8_t *OriginalSalt = K + SP_SALT_DATA;
size_t AlignedDataLen = ALIGN_TO(InDataLen,DataAlignment);
THOPEncryptorFnc EncryptorFnc = xorGetProperHOPEncryptorFnc(K);
uint8_t AlignedLenSize = GetAlignedLenSize(InDataLen);
size_t HHLEN = GetCommHeaderLenByAlignedLenSize(AlignedLenSize);
size_t LPad;
THohhaPacketHeader *PacketHeader = (THohhaPacketHeader *)OutBuf;
uint8_t *OBufStart = OutBuf + HHLEN;
SetHeaderAlignedLenValue((THohhaPacketHeader *)OutBuf, AlignedDataLen);
LPad = (AlignedDataLen-InDataLen) >> 1;
PacketHeader->Padding = (uint8_t)(AlignedDataLen-InDataLen);
// Now, let's copy our plaintext to new packet
memcpy(OBufStart + LPad, InBuf, InDataLen);
// First, let's create a new salt value unique for this transmission and copy original salt data to a buffer
GetRandomNumbers(SALT_SIZE, (uint8_t *)&(PacketHeader->Salt));
// Fill padding data if necessary
if (LPad)
{
uint8_t *dp = OBufStart;
uint32_t PadVal = GetRandomUInt32();
uint32_t R = LPad;
// We put left padding characters
while (R--)
{
  PadVal = (214013*PadVal+2531011);
  *dp = (uint8_t)((PadVal>>16)&0xff);
  ++dp;
}
// Then, we put right padding characters if necessary
R = AlignedDataLen - (LPad + InDataLen);
dp = OBufStart + LPad + InDataLen;
while (R--)
{
  PadVal = (214013*PadVal+2531011);
  *dp = (uint8_t)((PadVal>>16)&0xff);
  ++dp;
}

}
// Now, let's encrypt our data
PacketHeader->PlaintextCRC = htole32(EncryptorFnc(K, PacketHeader->Salt, KeyCheckSum, AlignedDataLen, OBufStart));
// We encrypted our packet. Now, let's encrypt packet header with original salt and key. But we don't encrypt header's first byte(AlignedLenSize)
EncryptorFnc(K, OriginalSalt, KeyCheckSum, HHLEN-(1+AlignedLenSize), OutBuf+1);
// Set encrypted flag to TRUE
*OutBuf |= 128;
}
uint8_t *CreateHohhaCommunicationPacket(uint8_t *K, uint32_t KeyCheckSum, size_t InDataLen, uint8_t *InBuf, uint32_t DataAlignment)
{ // This function encrypts InBuf and creates a communication packet with a proper header
// Allocates and returns encrypted packet data with size equal to HOHHA_TOTAL_COMM_PACKET_SIZE(DataSize)
// If DoNotEncrypt is true, data will not be encrypted and copied into the packet as plaintext
if (!(DataAlignment == 8 || DataAlignment == 16 || DataAlignment == 32 || DataAlignment == 64))
{
//printf("INVALID DATAALIGNMENT: %d\n", DataAlignment);
return NULL;
}
size_t AlignedDataLen = ALIGN_TO(InDataLen,DataAlignment);
uint8_t AlignedLenSize = GetAlignedLenSize(InDataLen);
size_t HHLEN = GetCommHeaderLenByAlignedLenSize(AlignedLenSize);
uint8_t *OutBuf = malloc(AlignedDataLen + HHLEN);
if (OutBuf)
CreateHohhaCommunicationPacket2(K, KeyCheckSum, InDataLen, InBuf, DataAlignment, OutBuf);
return OutBuf;
}
uint8_t *CreateHohhaCommunicationPacketPlaintext(size_t InDataLen, uint8_t *InBuf)
{ // This function encrypts InBuf and creates a communication packet with a proper header but without encryption and data alignment
uint8_t AlignedLenSize = GetAlignedLenSize(InDataLen);
size_t HHLEN = GetCommHeaderLenByAlignedLenSize(AlignedLenSize);
uint8_t *OutBuf = malloc(InDataLen + HHLEN);
if (!OutBuf)
return OutBuf;
THohhaPacketHeader *PacketHeader = (THohhaPacketHeader *)OutBuf;
SetHeaderAlignedLenValue((THohhaPacketHeader *)OutBuf, InDataLen);
PacketHeader->Padding = 0;
// Now, let's copy our plaintext to new packet
memcpy(OutBuf + HHLEN, InBuf, InDataLen);
PacketHeader->PlaintextCRC = digital_crc32(InBuf, InDataLen);
return OutBuf;
}
void CreateHohhaCommunicationPacket2Plaintext(size_t InDataLen, uint8_t *InBuf, uint8_t *OutBuf)
{ // This function encrypts InBuf and creates a communication packet with a proper header but without encryption and data alignment
// OutBuf must be already allocated and must be enough large to store (InDataLen + 4 + HHLEN) bytes
uint8_t AlignedLenSize = GetAlignedLenSize(InDataLen);
size_t HHLEN = GetCommHeaderLenByAlignedLenSize(AlignedLenSize);
THohhaPacketHeader *PacketHeader = (THohhaPacketHeader *)OutBuf;
SetHeaderAlignedLenValue((THohhaPacketHeader *)OutBuf, InDataLen);
PacketHeader->Padding = 0;
// Now, let's copy our plaintext to new packet
memcpy(OutBuf + HHLEN, InBuf, InDataLen);
PacketHeader->PlaintextCRC = digital_crc32(InBuf, InDataLen);
}
uint8_t *DecryptCommPacket(uint8_t *K, uint32_t KeyCheckSum, size_t TotalPacketLen, uint8_t *InOutBuf, ssize_t *PlainTextLen)
{ // Decrypts the packet and returns a pointer to decrypted data(NULL on error)
// On return, PlainTextLen will contain length of the plaintext on success or negative on error
size_t ALenSize = (*InOutBuf & 7);
uint32_t PlaintextCRC;
THohhaPacketHeader *PacketHeader = (THohhaPacketHeader *)InOutBuf;
size_t HHLEN = GetCommHeaderLenByHeader(PacketHeader);
*PlainTextLen = GetHeaderAlignedLenValue(PacketHeader);
if (!ALenSize || ALenSize > 4 || *PlainTextLen < 0)
{
*PlainTextLen = -1;
return NULL; // Body len size must be 1,2,3 or 4!!!
}
//printf("PacketHeader->AlignedLenSize: %u\n", PacketHeader->AlignedLenSize);
if  (!(PacketHeader->AlignedLenSize & 128))
{ // Message is not encrypted.
PlaintextCRC = digital_crc32(InOutBuf + HHLEN, *PlainTextLen);
if (PacketHeader->PlaintextCRC != PlaintextCRC)
{
*PlainTextLen = -2; // CRC mismatch
return NULL;
}
return InOutBuf+HHLEN;
}
uint8_t *OriginalSalt = K + SP_SALT_DATA;
THOPDecryptorFnc DecryptorFnc = xorGetProperHOPDecryptorFnc(K);
// First, we must decrypt the header with key and original salt value
DecryptorFnc(K, OriginalSalt, KeyCheckSum, HHLEN-(ALenSize + 1), InOutBuf+1);
if (TotalPacketLen-HHLEN < *PlainTextLen)
{
*PlainTextLen = -3; // Invalid plaintext length. Corrupted packet
return NULL;
}
// Then, we must decrypt the packet with salt value obtained from header
PlaintextCRC = htole32(DecryptorFnc(K, PacketHeader->Salt, KeyCheckSum, *PlainTextLen, InOutBuf + HHLEN));
// Now, let's compute exact plaintext size. Because *PlainTextLen still contains aligned data length
size_t LeftPad = PacketHeader->Padding >> 1;
size_t RightPad = PacketHeader->Padding - LeftPad;
*PlainTextLen -= PacketHeader->Padding;
//printf("Real data size: %lld Pad: %u Decrypted data from encrypted packet:::  %s\n",(long long int)(*PlainTextLen), PacketHeader->Padding, InOutBuf+HHLEN+((THohhaPacketHeader *)InOutBuf)->LeftPadding);
// Let's make integrity checks:
if (PacketHeader->PlaintextCRC != PlaintextCRC)
{
PlainTextLen = -2; // CRC mismatch
return NULL;
}
return InOutBuf+HHLEN+LeftPad;
}
/ --------------------- HOHHA PROTOCOL SPECIFIC FUNCTIONS ENDS HERE --------------- */
#endif
//#define xorEncryptDecrypt xorEncryptDecryptHOP5
/* Memcpy Benchmark1 :

This function
Creates a N bytes random data buffer
Creates another N bytes zero filled buffer (DestBuf)
Starts an iteration
For each iteration, increases every byte of the data by 1
Copies the data buffer to DestBuf
Prints the elapsed time
*/
double MemCpyBenchmark1(uint32_t TestSampleLength, uint32_t NumIterations)
{
uint8_t *Data = CreateDataBuf(TestSampleLength);
uint8_t *DestBuf = CreateDataBuf(TestSampleLength);
unsigned long long int TotalProcessedBytes = 0;
unsigned t;

/printf("-------------------- MemCpyBenchmark1 1: BASIC FUNCTIONALITY -------------------------\n"
"This function\n 1.Creates a %u bytes random data buffer\nCreates another buffer(DestBuf) with the same size\nMakes %u iteration\n"
"For each iteration, increases every byte of the data by 1\nCopies the data buffer to DestBuf\nPrints the elapsed time",TestSampleLength,NumIterations);/
printf("MemCpyBenchmark1\n\tTestSampleLength: %u\n\tNumIterations: %u ... ",TestSampleLength,NumIterations);
struct timeval StartTime;
gettimeofday (&StartTime, NULL);
for (t=0; t<NumIterations; t++)
{
IncByOne(Data, TestSampleLength);
memcpy(DestBuf, Data, TestSampleLength);
TotalProcessedBytes += TestSampleLength;
}
PrintElapsedTime(&StartTime,TotalProcessedBytes);
double Average = PrintElapsedTime(&StartTime,TotalProcessedBytes);
free(Data);
free(DestBuf);
return Average;
}
/* Benchmark1 :

This function
Creates a key with NumJumps particles and with a body length of BodyLen
Creates a N bytes random zero filled buffer
Starts an iteration of NumIterations times
For each iteration, increases every byte of the data by 1
Encrypts the data
Prints the elapsed time
*/
double Benchmark1(uint8_t NumJumps, uint32_t BodyLen, uint32_t TestSampleLength, uint32_t NumIterations)
{
uint8_t *KeyBuf = (uint8_t *)malloc(xorComputeKeyBufLen(BodyLen)); assert (KeyBuf);
uint8_t *Data = CreateDataBuf(TestSampleLength);
unsigned long long int TotalProcessedBytes = 0;
uint32_t t;
uint8_t Salt[SALT_SIZE];
uint32_t KeyCheckSum;
int Err;

printf("Benchmark1\n\tNumJumps: %u\n\tBodyLen: %u\n\tTestSampleLength: %u\n\tNumIterations: %u ... ",NumJumps,BodyLen,TestSampleLength,NumIterations);
GetRandomNumbers(TestSampleLength, Data);
Err = xorGetKey(NumJumps, BodyLen, KeyBuf);
if (Err != 0)
{
printf("Couldn't create the key. Error: %d\n",Err);
exit(-1);
}
KeyCheckSum = xorComputeKeyCheckSum(KeyBuf);
xorAnalyzeKey(KeyBuf);
struct timeval StartTime;
gettimeofday (&StartTime, NULL);
for (t=0; t<NumIterations; t++)
{
IncByOne(Data, TestSampleLength);
GetRandomNumbers(SALT_SIZE, Salt);
xorEncrypt(KeyBuf, (uint8_t *)(&Salt), KeyCheckSum, TestSampleLength, Data);
TotalProcessedBytes += TestSampleLength;
}
double Average = PrintElapsedTime(&StartTime,TotalProcessedBytes);
free(Data);
free(KeyBuf);
return Average;
}
static inline uint32_t BufCheckSum(uint8_t *Buf, uint64_t BufLen)
{
return digital_crc32(Buf, BufLen);
}
double BenchmarkHOP(uint8_t NumJumps, uint32_t BodyLen, uint32_t TestSampleLength, uint32_t NumIterations)
{
uint8_t *KeyBuf = (uint8_t *)malloc(xorComputeKeyBufLen(BodyLen)); assert (KeyBuf);
uint8_t *Data = CreateDataBuf(TestSampleLength);
unsigned long long int TotalProcessedBytes = 0;
uint32_t t;
uint32_t KeyCheckSum;
uint8_t SaltData[SALT_SIZE];
assert(KeyBuf);
printf("BenchmarkHop\n\tNumJumps: %u\n\tBodyLen: %u\n\tTestSampleLength: %u\n\tNumIterations: %u ... ",NumJumps,BodyLen,TestSampleLength,NumIterations);
GetRandomNumbers(SALT_SIZE, SaltData);
GetRandomNumbers(TestSampleLength, Data);
int Err = xorGetKey(NumJumps, BodyLen, KeyBuf);
if (Err != 0)
{
printf("Couldn't create the key. Error: %d\n",Err);
exit(-1);
}
KeyCheckSum = xorComputeKeyCheckSum(KeyBuf);
xorAnalyzeKey(KeyBuf);
struct timeval StartTime;
gettimeofday (&StartTime, NULL);
BufCheckSum(Data, TestSampleLength);
THOPEncryptorFnc EncryptorFnc = xorGetProperHOPEncryptorFnc(KeyBuf);
for (t=0; t<NumIterations; t++)
{
IncByOne(Data, TestSampleLength);
EncryptorFnc(KeyBuf, (uint8_t *)(&SaltData), KeyCheckSum, TestSampleLength, Data);
TotalProcessedBytes += TestSampleLength;
}
double Average = PrintElapsedTime(&StartTime,TotalProcessedBytes);
free(Data);
free(KeyBuf);
return Average;
}
#define TESTSTR1 "TÜRKÇE karakter kullanınız DENEME. TÜRKÇE karakter kullanınız DENEME. uzuuuuuuun. TÜRKÇE karakter kullanınız DENEME. Çok uzun çok!222TÜRKÇE karakter kullanınız DENEME. TÜRKÇE karakter kullanınız DENEME. uzuuuuuuun. TÜRKÇE karakter kullanınız DENEME. Çok uzun çok!frfrTÜRKÇE karakter kullanınız DENEME. TÜRKÇE karakter kullanınız DENEME. uzuuuuuuun. TÜRKÇE karakter kullanınız DENEME. Çok uzun çok!"
#define TESTSTR1_LEN strlen(TESTSTR1)
void CheckOptimizedVersion(unsigned NumJumps, unsigned BodyLen)
{
unsigned long long int DLen, OriginalPlainTextCheckSum, CheckSumReturnedFromEncryptor, CheckSumReturnedFromDecryptor;
unsigned RawKeyLen = xorComputeKeyBufLen(BodyLen);
uint8_t *KeyBuf = (uint8_t *)malloc(RawKeyLen); assert (KeyBuf);
uint8_t PlainTextBuf[132000], Data[132000];
unsigned long long int KeyCheckSum;
uint8_t SaltData[SALT_SIZE];
GetRandomNumbers(SALT_SIZE, SaltData);
printf("-------------------- TESTING OPTIMIZED VERSION FOR %u PARTICLES -------------------------\n",NumJumps);
int Err = xorGetKey(NumJumps, BodyLen, KeyBuf);
if (Err != 0)
{
printf("Couldn't create the key. Error: %d\n",Err);
exit(-1);
}
KeyCheckSum = xorComputeKeyCheckSum(KeyBuf);
DLen = TESTSTR1_LEN;
memcpy(Data, TESTSTR1, DLen);
memcpy(PlainTextBuf, TESTSTR1, DLen);
for (DLen = 0; DLen < TESTSTR1_LEN; DLen++)
{
PlainTextBuf[DLen] = (uint8_t)(DLen & 255);
Data[DLen] = PlainTextBuf[DLen];
OriginalPlainTextCheckSum = BufCheckSum(Data, DLen+1);
CheckSumReturnedFromEncryptor = xorEncrypt(KeyBuf, (uint8_t *)(&SaltData), KeyCheckSum, DLen+1, Data); // We encrypt with non-optimized version
if (OriginalPlainTextCheckSum != CheckSumReturnedFromEncryptor)
{
printf("Original Checksum %llu returned from BufChecksum fnc <> Checksum %llu returned from xorEncryptDecrypt\n",OriginalPlainTextCheckSum,CheckSumReturnedFromEncryptor);
exit(-1);
}
THOPDecryptorFnc DecryptorFnc = xorGetProperHOPDecryptorFnc(KeyBuf);
CheckSumReturnedFromDecryptor = DecryptorFnc(KeyBuf, (uint8_t *)(&SaltData), KeyCheckSum, DLen+1, Data);
if (OriginalPlainTextCheckSum != CheckSumReturnedFromDecryptor)
{
  printf("Original Checksum %llu returned from BufChecksum fnc <> Checksum %llu returned from HOP decyptor\n",OriginalPlainTextCheckSum,CheckSumReturnedFromDecryptor);
  exit(-1);
}
if (memcmp((char *)Data, (char *)PlainTextBuf, DLen+1) != 0)
{
  printf("String: %s ... optimized version test result: FAILED!!!!\n----------------------------------------\n", Data);
  exit(-1);
}

}
printf("xorEncryptDecryptHOP%u SUCCESSFUL!\n",NumJumps);
}
void Test1(unsigned NumJumps, unsigned BodyLen)
{
unsigned long long int DLen, OriginalPlainTextCheckSum, CheckSumReturnedFromEncryptor, CheckSumReturnedFromDecryptor;
unsigned RawKeyLen = xorComputeKeyBufLen(BodyLen);
uint8_t *KeyBuf = (uint8_t *)malloc(RawKeyLen); assert (KeyBuf);
uint8_t Data[2048],Data2[2048];
char *Base64EncodedKeyStr, *Base64CipherText;
uint32_t KeyCheckSum;
//uint8_t SaltData[SALT_SIZE];
//GetRandomNumbers(SALT_SIZE, SaltData);
uint8_t *SaltData = KeyBuf + SP_SALT_DATA;
printf("----------- TEST 1: BASIC FUNCTIONALITY(%u Jumps) --------------\n",NumJumps);
int Err = xorGetKey(NumJumps, BodyLen, KeyBuf);
if (Err != 0)
{
printf("Couldn't create the key. Error: %d\n",Err);
exit(-1);
}
KeyCheckSum = xorComputeKeyCheckSum(KeyBuf);
Base64EncodedKeyStr = Base64Encode((const char *)KeyBuf, RawKeyLen);
printf("Base64 encoded key: %s\n", Base64EncodedKeyStr);
xorAnalyzeKey(KeyBuf);
memset(&Data, 0, sizeof(Data));
memset(&Data2, 0, sizeof(Data2));
DLen = TESTSTR1_LEN;
memcpy(Data, TESTSTR1, DLen);
memcpy(Data2, TESTSTR1, DLen);
OriginalPlainTextCheckSum = BufCheckSum(Data, DLen);
CheckSumReturnedFromEncryptor = xorEncrypt(KeyBuf, SaltData, KeyCheckSum, DLen, Data); // We encrypt with non-optimized version
if (OriginalPlainTextCheckSum != CheckSumReturnedFromEncryptor)
{
printf("Original Checksum %llu returned from BufChecksum fnc <> Checksum %llu returned from non-optimized encryptor\n",OriginalPlainTextCheckSum,CheckSumReturnedFromEncryptor);
exit(-1);
} else printf("OriginalPlainTextCheckSum %llu = CheckSumReturnedFromEncryptor %llu :: SUCCESS!\n",OriginalPlainTextCheckSum,CheckSumReturnedFromEncryptor);
// Now let's encrypt with the optimized encryptor
THOPEncryptorFnc EncryptorFnc = xorGetProperHOPEncryptorFnc(KeyBuf);
THOPDecryptorFnc DecryptorFnc = xorGetProperHOPDecryptorFnc(KeyBuf);
CheckSumReturnedFromEncryptor = EncryptorFnc(KeyBuf, SaltData, KeyCheckSum, DLen, Data2);
if (OriginalPlainTextCheckSum != CheckSumReturnedFromEncryptor)
{
printf("Original Checksum %llu returned from BufChecksum fnc <> Checksum %llu returned from optimized encryptor\n",OriginalPlainTextCheckSum,CheckSumReturnedFromEncryptor);
exit(-1);
} else printf("OriginalPlainTextCheckSum %llu = CheckSumReturnedFromOptimizedEncryptor %llu :: SUCCESS!\n",OriginalPlainTextCheckSum,CheckSumReturnedFromEncryptor);
if (memcmp((char *)Data, Data2, DLen) != 0)
{
printf("Non-optimized and optimized encryptor functions outputs are different! FAILED! FAILED!\n");
exit(-1);
}
Base64CipherText = Base64Encode((const char *)Data, DLen);
printf("Base64CipherText: %s\n", Base64CipherText);
printf("\n\nDecryption process:\n\n");
uint8_t *K = (uint8_t *)Base64Decode(Base64EncodedKeyStr);
if (memcmp((char *)KeyBuf, (char *)K, RawKeyLen) != 0)
{
printf("Original key and base64 encoded and decoded keys are different!!!!!\n");
exit(-1);
}
//CheckSumReturnedFromDecryptor = xorDecrypt(K, (uint8_t *)(&SaltData), KeyCheckSum, DLen, Data);
CheckSumReturnedFromDecryptor = DecryptorFnc(K, SaltData, KeyCheckSum, DLen, Data);
if (OriginalPlainTextCheckSum != CheckSumReturnedFromDecryptor)
{
printf("Original Checksum %llu returned from BufChecksum fnc <> Checksum %llu returned from HOP decyptor\n",OriginalPlainTextCheckSum,CheckSumReturnedFromDecryptor);
exit(-1);
} else printf("OriginalPlainTextCheckSum %llu = CheckSumReturnedFromDecryptor %llu :: SUCCESS!\n",OriginalPlainTextCheckSum,CheckSumReturnedFromDecryptor);
if (memcmp((char *)Data, TESTSTR1, DLen) == 0)
{
printf("String: %s ... Test1 result: SUCCESSFUL!!!!\n----------------------------------------\n", Data);
}
else {
printf("String: %s ... Test1 result: FAILED!!!!\n----------------------------------------\n", Data);
exit(-1);
}
}
void CommPacketTest(unsigned NumJumps, unsigned BodyLen)
{
unsigned long long int DLen;
unsigned RawKeyLen = xorComputeKeyBufLen(BodyLen);
uint8_t *KeyBuf = (uint8_t *)malloc(RawKeyLen); assert (KeyBuf);
uint8_t Data[2048],Data2[2048];
char *Base64EncodedKeyStr;
uint32_t KeyCheckSum;
uint8_t SaltData[SALT_SIZE];
GetRandomNumbers(SALT_SIZE, SaltData);
printf("----------- COMM PACKETS TEST(%u Jumps) --------------\n",NumJumps);
int Err = xorGetKey(NumJumps, BodyLen, KeyBuf);
if (Err != 0)
{
printf("Couldn't create the key. Error: %d\n",Err);
exit(-1);
}
KeyCheckSum = xorComputeKeyCheckSum(KeyBuf);
Base64EncodedKeyStr = Base64Encode((const char *)KeyBuf, RawKeyLen);
printf("Base64 encoded key: %s\n", Base64EncodedKeyStr);
memset(&Data, 0, sizeof(Data));
memset(&Data2, 0, sizeof(Data2));
DLen = TESTSTR1_LEN;
memcpy(Data, TESTSTR1, DLen);
#define PACK_ALIGNMENT 16
uint32_t CommPacketTotalSize = HOHHA_TOTAL_COMM_PACKET_SIZE(DLen,PACK_ALIGNMENT);
uint8_t *CommPacket = malloc(CommPacketTotalSize);
CreateHohhaCommunicationPacket2(KeyBuf, KeyCheckSum, DLen, Data, PACK_ALIGNMENT, CommPacket);
char *Base64EncodedCommPacket = Base64Encode((const char *)CommPacket, CommPacketTotalSize);
printf("Encrypted communication packet: %s\n", Base64EncodedCommPacket);
free(Base64EncodedCommPacket);
// Now, let's decrypt it
ssize_t DpRes;
uint8_t *PPText = DecryptCommPacket(KeyBuf, KeyCheckSum, CommPacketTotalSize, CommPacket, &DpRes);
if (DpRes < 0 || DpRes != DLen)
{
printf("DecryptCommPacket error: %lld. DLen: %lld\n", (long long int)DpRes, (long long int)DLen);
exit(-1);
}
//  THohhaPacketHeader *PacketHeader = (THohhaPacketHeader *)CommPacket;
if (memcmp((char *)PPText, TESTSTR1, DLen) == 0)
{
printf("String: %.*s ... Hohha Comm Packet Test result: SUCCESSFUL!!!!\n----------------------------------------\n", (int)(DpRes), PPText);
}
else {
printf("String: %.*s ... Hohha Comm Packet Test result: FAILED!!!!\n----------------------------------------\n", (int)(DpRes), PPText);
exit(-1);
}
free(CommPacket);
CommPacketTotalSize = HOHHA_TOTAL_COMM_PACKET_SIZE_WITHOUT_ENCRYPTION(DLen);
CommPacket = calloc(1, CommPacketTotalSize);
CreateHohhaCommunicationPacket2Plaintext(DLen, Data, CommPacket);
Base64EncodedCommPacket = Base64Encode((const char *)CommPacket, CommPacketTotalSize);
printf("Plaintext communication packet in base64: %s\n", Base64EncodedCommPacket);
free(Base64EncodedCommPacket);
// Now, let's decrypt it
PPText = DecryptCommPacket(KeyBuf, KeyCheckSum, CommPacketTotalSize, CommPacket, &DpRes);
if (DpRes < 0 || DpRes != DLen)
{
printf("DecryptCommPacket error: %lld. DLen: %lld\n", (long long int)DpRes, (long long int)DLen);
exit(-1);
}
//PacketHeader = (THohhaPacketHeader *)CommPacket;
if (memcmp((char *)PPText, TESTSTR1, DLen) == 0)
{
printf("String: %.*s ... Hohha plaintext Comm Packet Test result: SUCCESSFUL!!!!\n----------------------------------------\n", (int)(DpRes), PPText);
}
else {
printf("String: %.*s ... Hohha plaintext Comm Packet Test result: FAILED!!!!\n----------------------------------------\n", (int)(DpRes), PPText);
exit(-1);
}
free(CommPacket);
exit(-1);
}
void CircularShiftTest()
{
uint32_t t, Nn = (uint32_t)(0b10000000000000000000000000000010U);
char Buf[256];
printf("Circular shift left:\n");
for (t=0; t<5; t++)
{
printf("%s\n", GetBinStr(Nn,Buf));
ROL32_1(Nn);
}
printf("Circular shift right:\n");
for (t=0; t<6; t++)
{
printf("%s\n", GetBinStr(Nn,Buf));
ROR32_1(Nn);
}
}
ssize_t EncryptFile(const char *InFileName, const char *OutFileName, uint8_t *KeyBuf, uint32_t KeyCheckSum)
{
int32_t FDesc;
int64_t Len, RLen;
uint8_t *Data;
uint8_t SaltData[SALT_SIZE];
ssize_t CheckSum=0;
if ((FDesc = open(InFileName, O_RDONLY)) == -1)
{
printf("Error in opening file!\n");
return -1;
}
Len = lseek(FDesc, 0, SEEK_END);
lseek(FDesc, 0, SEEK_SET);
Data = (uint8_t *)malloc(Len);
if (Data == NULL)
{
printf("OUT OF MEMORY!\n");
close(FDesc);
return -1;
}
RLen = read(FDesc, Data, Len);
if (RLen != Len)
{
printf("Error in reading file!\n");
free(Data);
close(FDesc);
return -1;
}
close(FDesc);
//GetRandomNumbers(8, (uint8_t *)(&SaltData));
// Copy key's original salt value to salt buffer
memcpy(&SaltData, KeyBuf+SP_SALT_DATA, SALT_SIZE);
THOPEncryptorFnc EncryptorFnc = xorGetProperHOPEncryptorFnc(KeyBuf);
CheckSum = (ssize_t)EncryptorFnc(KeyBuf, (uint8_t *)(&SaltData), KeyCheckSum, Len, Data);
if ((FDesc = creat(OutFileName, 700)) == -1)
{
printf("Error in creating output file!\n");
free(Data);
return -1;
}
write(FDesc,Data,Len);
free(Data);
close(FDesc);
return CheckSum;
}
#define BMP_FILE_HEADER_LEN 54
ssize_t EncryptBMPFile(const char *InFileName, const char *OutFileName, uint8_t *KeyBuf, uint32_t KeyCheckSum)
{ // Encrypts a bmp file for visual attack and returns -1 on error.
int32_t FDesc;
int64_t Len, RLen;
uint8_t *Data;
uint8_t SaltData[SALT_SIZE];
ssize_t CheckSum=0;
if ((FDesc = open(InFileName, O_RDONLY)) == -1)
{
printf("Error in opening file!\n");
return -1;
}
Len = lseek(FDesc, 0, SEEK_END);
if (lseek(FDesc, 0, SEEK_SET) != 0)
{
printf("Error seeking to beginning of file!\n");
return -1;
}
Data = (uint8_t *)malloc(Len);
if (Data == NULL)
{
printf("OUT OF MEMORY!\n");
close(FDesc);
free(Data);
return -1;
}
RLen = read(FDesc, Data, Len);
if (RLen != Len || RLen <= BMP_FILE_HEADER_LEN)
{
printf("Error in reading file!\n");
close(FDesc);
free(Data);
return -1;
}
close(FDesc);
//GetRandomNumbers(8, (uint8_t *)(&SaltData));
// Copy key's original salt value to salt buffer
memcpy(&SaltData, KeyBuf+SP_SALT_DATA, SALT_SIZE);
THOPEncryptorFnc EncryptorFnc = xorGetProperHOPEncryptorFnc(KeyBuf);
CheckSum = (ssize_t)EncryptorFnc(KeyBuf, (uint8_t *)(&SaltData), KeyCheckSum, Len-BMP_FILE_HEADER_LEN, Data + BMP_FILE_HEADER_LEN);
if ((FDesc = creat(OutFileName, 777)) == -1)
{
printf("Error in creating output file!\n");
free(Data);
return -1;
}
if (write(FDesc,Data,Len) != Len)
{
printf("Error writing file!\n");
free(Data);
return -1;
}
free(Data);
close(FDesc);
return CheckSum;
}
#define SAMPLE_FILE_PATH "/home/ikizir/Downloads/panda.bmp"
#define SAMPLE_OUT_FILE_PATH "/home/ikizir/Downloads/panda_enc.bmp"
void TestEncryptFile(unsigned NumJumps, unsigned BodyLen)
{
unsigned long long int ChkSum;
unsigned RawKeyLen = xorComputeKeyBufLen(BodyLen);
uint8_t *KeyBuf = (uint8_t *)malloc(RawKeyLen);
uint32_t KeyCheckSum;
char *Base64EncodedKeyStr;
printf("----------- FILE ENC TEST(%u Jumps) --------------\n",NumJumps);
int Err = xorGetKey(NumJumps, BodyLen, KeyBuf);
if (Err != 0)
{
printf("Couldn't create the key. Error: %d\n",Err);
exit(-1);
}
KeyCheckSum = xorComputeKeyCheckSum(KeyBuf);
Base64EncodedKeyStr = Base64Encode((const char *)KeyBuf, RawKeyLen);
printf("Base64 encoded key: %s\n", Base64EncodedKeyStr);
xorAnalyzeKey(KeyBuf);
ChkSum = EncryptFile(SAMPLE_FILE_PATH, SAMPLE_OUT_FILE_PATH, KeyBuf, KeyCheckSum);
printf("Result: %llu\n", ChkSum);
}
void TestEncryptBMPFile(const char *InFileName, const char *OutFileName, unsigned NumJumps, unsigned BodyLen)
{
unsigned long long int ChkSum;
unsigned RawKeyLen = xorComputeKeyBufLen(BodyLen);
uint8_t *KeyBuf = (uint8_t *)malloc(RawKeyLen);
uint32_t KeyCheckSum;
char *Base64EncodedKeyStr;
printf("----------- FILE ENC TEST(%u Jumps) --------------\n",NumJumps);
int Err = xorGetKey(NumJumps, BodyLen, KeyBuf);
if (Err != 0)
{
printf("Couldn't create the key. Error: %d\n",Err);
exit(-1);
}
KeyCheckSum = xorComputeKeyCheckSum(KeyBuf);
Base64EncodedKeyStr = Base64Encode((const char *)KeyBuf, RawKeyLen);
printf("Base64 encoded key: %s\n", Base64EncodedKeyStr);
xorAnalyzeKey(KeyBuf);
ChkSum = EncryptBMPFile(InFileName, OutFileName, KeyBuf, KeyCheckSum);
printf("Result: %llu\n", ChkSum);
}
void CreateVisualProofs()
{
TestEncryptBMPFile("/home/ikizir/Downloads/allzero.bmp", "/home/ikizir/Downloads/allzero_enc_2J_64.bmp", 2, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/allzero.bmp", "/home/ikizir/Downloads/allzero_enc_3J_64.bmp", 3, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/allzero.bmp", "/home/ikizir/Downloads/allzero_enc_4J_64.bmp", 4, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/allzero.bmp", "/home/ikizir/Downloads/allzero_enc_2J_128.bmp", 2, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/allzero.bmp", "/home/ikizir/Downloads/allzero_enc_3J_128.bmp", 3, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/allzero.bmp", "/home/ikizir/Downloads/allzero_enc_4J_128.bmp", 4, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/allzero.bmp", "/home/ikizir/Downloads/allzero_enc_2J_256.bmp", 2, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/allzero.bmp", "/home/ikizir/Downloads/allzero_enc_3J_256.bmp", 3, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/allzero.bmp", "/home/ikizir/Downloads/allzero_enc_4J_256.bmp", 4, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/panda.bmp", "/home/ikizir/Downloads/panda_enc_2J_64.bmp", 2, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/panda.bmp", "/home/ikizir/Downloads/panda_enc_3J_64.bmp", 3, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/panda.bmp", "/home/ikizir/Downloads/panda_enc_4J_64.bmp", 4, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/panda.bmp", "/home/ikizir/Downloads/panda_enc_2J_128.bmp", 2, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/panda.bmp", "/home/ikizir/Downloads/panda_enc_3J_128.bmp", 3, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/panda.bmp", "/home/ikizir/Downloads/panda_enc_4J_128.bmp", 4, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/panda.bmp", "/home/ikizir/Downloads/panda_enc_2J_256.bmp", 2, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/panda.bmp", "/home/ikizir/Downloads/panda_enc_3J_256.bmp", 3, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/panda.bmp", "/home/ikizir/Downloads/panda_enc_4J_256.bmp", 4, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/Bitmap1.bmp", "/home/ikizir/Downloads/Bitmap1_enc_2J_64.bmp", 2, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/Bitmap1.bmp", "/home/ikizir/Downloads/Bitmap1_enc_3J_64.bmp", 3, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/Bitmap1.bmp", "/home/ikizir/Downloads/Bitmap1_enc_4J_64.bmp", 4, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/Bitmap1.bmp", "/home/ikizir/Downloads/Bitmap1_enc_2J_128.bmp", 2, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/Bitmap1.bmp", "/home/ikizir/Downloads/Bitmap1_enc_3J_128.bmp", 3, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/Bitmap1.bmp", "/home/ikizir/Downloads/Bitmap1_enc_4J_128.bmp", 4, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/Bitmap1.bmp", "/home/ikizir/Downloads/Bitmap1_enc_2J_256.bmp", 2, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/Bitmap1.bmp", "/home/ikizir/Downloads/Bitmap1_enc_3J_256.bmp", 3, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/Bitmap1.bmp", "/home/ikizir/Downloads/Bitmap1_enc_4J_256.bmp", 4, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/Viking.bmp", "/home/ikizir/Downloads/Viking_enc_2J_64.bmp", 2, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/Viking.bmp", "/home/ikizir/Downloads/Viking_enc_3J_64.bmp", 3, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/Viking.bmp", "/home/ikizir/Downloads/Viking_enc_4J_64.bmp", 4, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/Viking.bmp", "/home/ikizir/Downloads/Viking_enc_2J_128.bmp", 2, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/Viking.bmp", "/home/ikizir/Downloads/Viking_enc_3J_128.bmp", 3, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/Viking.bmp", "/home/ikizir/Downloads/Viking_enc_4J_128.bmp", 4, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/Viking.bmp", "/home/ikizir/Downloads/Viking_enc_2J_256.bmp", 2, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/Viking.bmp", "/home/ikizir/Downloads/Viking_enc_3J_256.bmp", 3, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/Viking.bmp", "/home/ikizir/Downloads/Viking_enc_4J_256.bmp", 4, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/B.bmp", "/home/ikizir/Downloads/B_enc_2J_64.bmp", 2, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/B.bmp", "/home/ikizir/Downloads/B_enc_3J_64.bmp", 3, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/B.bmp", "/home/ikizir/Downloads/B_enc_4J_64.bmp", 4, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/B.bmp", "/home/ikizir/Downloads/B_enc_2J_128.bmp", 2, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/B.bmp", "/home/ikizir/Downloads/B_enc_3J_128.bmp", 3, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/B.bmp", "/home/ikizir/Downloads/B_enc_4J_128.bmp", 4, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/B.bmp", "/home/ikizir/Downloads/B_enc_2J_256.bmp", 2, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/B.bmp", "/home/ikizir/Downloads/B_enc_3J_256.bmp", 3, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/B.bmp", "/home/ikizir/Downloads/B_enc_4J_256.bmp", 4, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/penguen.bmp", "/home/ikizir/Downloads/penguen_enc_2J_64.bmp", 2, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/penguen.bmp", "/home/ikizir/Downloads/penguen_enc_3J_64.bmp", 3, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/penguen.bmp", "/home/ikizir/Downloads/penguen_enc_4J_64.bmp", 4, 64);
TestEncryptBMPFile("/home/ikizir/Downloads/penguen.bmp", "/home/ikizir/Downloads/penguen_enc_2J_128.bmp", 2, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/penguen.bmp", "/home/ikizir/Downloads/penguen_enc_3J_128.bmp", 3, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/penguen.bmp", "/home/ikizir/Downloads/penguen_enc_4J_128.bmp", 4, 128);
TestEncryptBMPFile("/home/ikizir/Downloads/penguen.bmp", "/home/ikizir/Downloads/penguen_enc_2J_256.bmp", 2, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/penguen.bmp", "/home/ikizir/Downloads/penguen_enc_3J_256.bmp", 3, 256);
TestEncryptBMPFile("/home/ikizir/Downloads/penguen.bmp", "/home/ikizir/Downloads/penguen_enc_4J_256.bmp", 4, 256);
}
int main()
{
uint32_t BodyLen = 128;
//printf("CRC: %u\n", digital_crc32((uint8_t *)"A", 1));
//printf("CRC: %u\n", digital_crc32((uint8_t *)"Ismail", 6));
Test1(2, BodyLen);
CommPacketTest(3, 128);
//exit(-1);
CreateVisualProofs();
//  exit(-1);
//CircularShiftTest();
//uint32_t TestSampleLength = 8192;
uint32_t NumIterations = 1000000;
//D1();
Test1(2, BodyLen);
Test1(3, BodyLen);
Test1(4, BodyLen);
//Test1(4, BodyLen);
//Test1(5, BodyLen);
//exit(-1);

CheckOptimizedVersion(2, BodyLen);
CheckOptimizedVersion(3, BodyLen);
CheckOptimizedVersion(4, BodyLen);
//CheckOptimizedVersion(5, BodyLen);
double Average16M,Average64M,Average256M,Average1024M,Average8192M;
double Average16H2,Average64H2,Average256H2,Average1024H2,Average8192H2;
double Average16H3,Average64H3,Average256H3,Average1024H3,Average8192H3;
double Average16H4,Average64H4,Average256H4,Average1024H4,Average8192H4;
Average16M = MemCpyBenchmark1(16, NumIterations);
Average64M = MemCpyBenchmark1(64, NumIterations);
Average256M = MemCpyBenchmark1(256, NumIterations);
Average1024M = MemCpyBenchmark1(1024, NumIterations);
Average8192M = MemCpyBenchmark1(8192, NumIterations);
/*
double Average16,Average64,Average256,Average1024,Average8192;
Average16 = Benchmark1(NumJumps, BodyLen, 16, NumIterations);
Average64 = Benchmark1(NumJumps, BodyLen, 64, NumIterations);
Average256 = Benchmark1(NumJumps, BodyLen, 256, NumIterations);
Average1024 = Benchmark1(NumJumps, BodyLen, 1024, NumIterations);
Average8192 = Benchmark1(NumJumps, BodyLen, 8192, NumIterations);
printf("\n\nNON-HAND-OPTIMIZED VERSION BENCHMARKS:\n"
"16                  64                  256                 1024                 8192\n"
"------------------- ------------------- ------------------- -------------------- --------------------\n"
"%19.2f %19.2f %19.2f %19.2f %19.2f\n\n", Average16, Average64, Average256, Average1024, Average8192);
*/
Average16H2 = BenchmarkHOP(2, BodyLen, 16, NumIterations);
Average64H2 = BenchmarkHOP(2, BodyLen, 64, NumIterations);
Average256H2 = BenchmarkHOP(2, BodyLen, 256, NumIterations);
Average1024H2 = BenchmarkHOP(2, BodyLen, 1024, NumIterations);
Average8192H2 = BenchmarkHOP(2, BodyLen, 8192, NumIterations);
Average16H3 = BenchmarkHOP(3, BodyLen, 16, NumIterations);
Average64H3 = BenchmarkHOP(3, BodyLen, 64, NumIterations);
Average256H3 = BenchmarkHOP(3, BodyLen, 256, NumIterations);
Average1024H3 = BenchmarkHOP(3, BodyLen, 1024, NumIterations);
Average8192H3 = BenchmarkHOP(3, BodyLen, 8192, NumIterations);
Average16H4 = BenchmarkHOP(4, BodyLen, 16, NumIterations);
Average64H4 = BenchmarkHOP(4, BodyLen, 64, NumIterations);
Average256H4 = BenchmarkHOP(4, BodyLen, 256, NumIterations);
Average1024H4 = BenchmarkHOP(4, BodyLen, 1024, NumIterations);
Average8192H4 = BenchmarkHOP(4, BodyLen, 8192, NumIterations);
printf("\n\nMemcpy BENCHMARKS(Real life usage):\n"
"16                  64                  256                 1024                8192               \n"
"------------------- ------------------- ------------------- ------------------- -------------------\n"
"%19.2f %19.2f %19.2f %19.2f %19.2f\n\n", Average16M, Average64M, Average256M, Average1024M, Average8192M);
printf("\n\n2-Jumps BENCHMARKS(Real life usage):\n"
"16                  64                  256                 1024                8192               \n"
"------------------- ------------------- ------------------- ------------------- -------------------\n"
"%19.2f %19.2f %19.2f %19.2f %19.2f\n\n", Average16H2, Average64H2, Average256H2, Average1024H2, Average8192H2);
printf("\n\n3-Jumps BENCHMARKS(Real life usage):\n"
"16                  64                  256                 1024                8192               \n"
"------------------- ------------------- ------------------- ------------------- -------------------\n"
"%19.2f %19.2f %19.2f %19.2f %19.2f\n\n", Average16H3, Average64H3, Average256H3, Average1024H3, Average8192H3);
printf("\n\n4-Jumps BENCHMARKS(Real life usage):\n"
"16                  64                  256                 1024                8192               \n"
"------------------- ------------------- ------------------- ------------------- -------------------\n"
"%19.2f %19.2f %19.2f %19.2f %19.2f\n\n", Average16H4, Average64H4, Average256H4, Average1024H4, Average8192H4);
return 0;
}

You can write me privately if you want:
ikizir@gmail.com

If you want, make your modifications based on this code and re-send it

Can you push a branch for that, or push it to your master branch?  For two reasons: github thinks the code you pasted is markdown, so now it's all funny formatted.  Second, if I rebase on that, your code should should have a commit id, or there are bound to be merge conflicts later (ex: Suppose I commit your changes, rebase my work on it, and push to you; now my commit of your changes conflicts with your local changes).

Give me a couple of days. I will push it to master branch.
The reason I am postponing is to "synchronize" the C and Javascript versions.
To keep the compatibility in both versions(lack of instructions etc.), sometimes, I may change the C code to be able to write a better Javascript code.

Check this out: https://github.com/ed770878/hohha-js
If you pull these changes to the c implementation, then it will be easy to validate the javascript implementation.
Replace the keys in the below command with the key generated by the javascript (or, vice versa).  Don't forget to 'quote' the salt.
make
./HohhaHarness -e -K 'CIAAPZftm89jFihivrctXMlZ0XT82ZLFHsE/A2/KSIHZC/tWguc8mXAdG3OVPTyRKgpeoNAHnDsOGouOpXdgcXwC3gXixOcCyc5OUajkFV3Ou4a+bt5mXSqFePEYbmr6XFCAWm4tOwOuueAqiLqQwYJ1Ku0GO+wasYxyGV1Fk4z29neQ2LhokC3y/A==' -S '61 151 237 155 207 99 22 40' -M 'Hello Mysterious World!'

1Bj7NxAjXrUmrmrhHY38xAnMlc6w7eU=

Or this, I find is easier on the command line.
K='CIAAPZftm89jFihivrctXMlZ0XT82ZLFHsE/A2/KSIHZC/tWguc8mXAdG3OVPTyRKgpeoNAHnDsOGouOpXdgcXwC3gXixOcCyc5OUajkFV3Ou4a+bt5mXSqFePEYbmr6XFCAWm4tOwOuueAqiLqQwYJ1Ku0GO+wasYxyGV1Fk4z29neQ2LhokC3y/A=='

S='61 151 237 155 207 99 22 40'

./HohhaHarness -e -K "$K" -S "$S" -M 'Hello Mysterious World!"

1Bj7NxAjXrUmrmrhHY38xAnMlc6w7eU=

For further validation, you can also copy some of the unit test data into the javascript version.  The unit tests are provided in this pull request - but running the tests is only automated for the c code.
In the javascript version, don't forget to deselect "random salt", or it won't use the same salt as the unit test.  Also, don't forget to select "base64 encoded" for the input, or it will encrypt the base64 string itself instead of the encoded binary data.

I've updated master branch.
If you make your updates based on this code, I will accept them.
You seem to be a professional.
Can you help me to find a good and really fast (preferably static huffman table based) compression/decompression library?

It must be very very lightweight. I always prefer single file implementations.
It must work on plain browser javascript without node.js etc. bindings(I don't want to use browserify. I've just ported node.js buffer to javascript)
It must be reasonably fast.
Works the same on browser, node and C

I don't want compression only for "compression".
My communication is text based. And a lot of different application will send text based data.
Text based data is easier for attackers.
I want to minimize the attack risks.
But if we can compress the data before encryption, the data will be less predictable.
I feel that Huffman with a good prepared static table may work well. Because, I am sending abundantly base64 encoded data: Static Huffman table may be well suited for this purpose and Huffman entirely changes the characters. There will be no trace of ASCII.
https://github.com/wilkerlucio/huffman_js
is simple to use. But,

I don't know how fast it is
There is no C implementation

I tried to play with it on jsfiddle.net.
There is a function to save huffman tree; but, I couldn't "train" it well. Bad compression ratios. Maybe, not because of the library itself. We must find a good way to form an "optimal" huffman tree for my communication patterns.
This is what I am actually working on.
For the moment, I still prefer not to publish javascript code yet. Because, it is much more dynamic than the C counterpart. Heavily under development.
I don't like to work with anonymous people, but, anyway ...
Thank you for your contributions.

What do you think about this javascript version?
https://github.com/ed770878/hohha-js

If you make your updates based on this code, I will accept them.

The automatic merge was a success - no conflicts.  I rebuilt it and ran the unit tests.  They all still pass.
make
cd test
./runtests.sh ../HohhaHarness

You know, you can try changes before merging them, like this:
#assuming you are starting in your own master branch
# checkout a new temporary branch, to test the merge
git checkout -b tmp
# pull the proposed changes into the tmp branch
git pull https://github.com/ed770878/HohhaDynamicXOR.git harness
# test test test, then go back to your own stuff
git checkout master
# you can merge the tmp branch, or do the merge in github
# finally, you can delete the tmp branch
git branch -D tmp

Text based data is easier for attackers. I want to minimize the attack risks. But if we can compress the data before encryption, the data will be less predictable.

Don't count on compression to make the encryption stronger.  If an attacker knows that the encrypted content is in some recognizable format (like a compression format), then they might use that knowledge to crack the encryption just as easily as if it were plain text.  Compression can make it make the algorithm weak in other ways, too.  It could enable attacks like the padding oracle, by attacking the padding or other structures of the compression format.
One more thing about plain text.  Remember, computers will do the cracking.  Computers read bytes, not text.  If the algorithm is good, it should be just as hard to crack an encrypted plain text message as it is to crack encrypted random binary data.
If you really must have compression, maybe look at this port of zlib to javascript (it claims to be "very fast"): https://github.com/nodeca/pako.

I don't like to work with anonymous people

Hi!  I'm Oscar, from the Internet!

Hello Oscar,
Javascript demo looks nice. Everything, the demo etc.
I can link to your javascript lib from the main page.
But there may be a small bug:
I change the salt, I encrypt the same text with the same key but with the
new salt, but the ciphertext remains the same.
I hope, this is not a bug, or worse, it's not a bug in main
implementation(I mean, C implementation).
I will check your request again write about it later. I've changed the
code. How doesn't it conflict? Haven't you changed anything in my code?
You're right about the compression. Let's forget about it for the moment.
Algorithm is good. Padding also hides the data well.
On Wed, Jan 27, 2016 at 7:02 AM, ed770878 notifications@github.com wrote:

What do you think about this javascript version?
https://github.com/ed770878/hohha-js
If you make your updates based on this code, I will accept them.
The automatic merge was a success - no conflicts. I rebuilt it and ran the
unit tests. They all still pass.
make
cd test
./runtests.sh ../HohhaHarness
You know, you can try changes before merging them, like this:
#assuming you are starting in your own master branch
checkout a new temporary branch, to test the merge
git checkout -b tmp
pull the proposed changes into the tmp branch
git pull https://github.com/ed770878/HohhaDynamicXOR.git harness
test test test, then go back to your own stuff
git checkout master
you can merge the tmp branch, or do the merge in github
finally, you can delete the tmp branch
git branch -D tmp
Text based data is easier for attackers. I want to minimize the attack
risks. But if we can compress the data before encryption, the data will be
less predictable.
Don't count on compression to make the encryption stronger. If an attacker
knows that the encrypted content is in some recognizable format (like a
compression format), then they might use that knowledge to crack the
encryption just as easily as if it were plain text. Compression can make it
make the algorithm weak in other ways, too. It could enable attacks like
the padding oracle https://en.wikipedia.org/wiki/Padding_oracle_attack,
by attacking the padding or other structures of the compression format.
One more thing about plain text. Remember, computers will do the cracking.
Computers read bytes, not text. If the algorithm is good, it should be just
as hard to crack an encrypted plain text message as it is to crack
encrypted random binary data.
If you really must have compression, maybe look at this port of zlib to
javascript (it claims to be "very fast"): https://github.com/nodeca/pako.
I don't like to work with anonymous people
Hi! I'm Oscar, from the Internet!
—
Reply to this email directly or view it on GitHub
https://github.com/ikizir/HohhaDynamicXOR/pull/12#issuecomment-175400122
.

But there may be a small bug: I change the salt, I encrypt the same text with the same key but with the new salt, but the ciphertext remains the same.

Hmm.  It works for me, but you can file a bug report for it.  Say what exactly did you do to cause the bug, what browser it was on, etc.
What I did:

uncheck "random salt" so it doesn't change automatically
encrypt - the ciphertext does not change
change one number in the salt
encrypt - the ciphertext is different
change salt back to the original
encrypt - the ciphertext is also back to the original

How doesn't it conflict? Haven't you changed anything in my code?

We edited different lines.  There were no edit conflicts.  Git was able to merge our edits.  I made as few edits to your code as possible, because I wanted to be sure that adding the harness did not change your algorithm in any way.
Now that there is a stable set of unit tests in place, it is much safer to make changes to the algorithm code.  If you do some major refactoring of the code, as long as all the unit tests still pass, you can be reasonably sure there are no mistakes in the refactoring.  It doesn't mean the algorithm should never change, just that it should not be changed by accident.  If algorithm output is changed, and if the change is not an accident, then the unit test data can all be regenerated.

OK,
I will check javascript again, with your instructions.
I trust you.
It's sure, you know better than me how to use Git :)
I am going to accept changes.
And ... "Oscar from the Internet" is still anonymous :)
On Wed, Jan 27, 2016 at 7:57 AM, ed770878 notifications@github.com wrote:

But there may be a small bug: I change the salt, I encrypt the same text
with the same key but with the new salt, but the ciphertext remains the
same.
Hmm. It works for me, but you can file a bug report for it. Say what
exactly did you do to cause the bug, what browser it was on, etc.
What I did:

uncheck "random salt" so it doesn't change automatically
encrypt - the ciphertext does not change
change one number in the salt
encrypt - the ciphertext is different
change salt back to the original
encrypt - the ciphertext is also back to the original

How doesn't it conflict? Haven't you changed anything in my code?
We edited different lines. There were no edit conflicts. Git was able to
merge our edits. I made as few edits to your code as possible, because I
wanted to be sure that adding the harness did not change your algorithm in
any way.
Now that there is a stable set of unit tests in place, it is much safer to
make changes to the algorithm code. If you do some major refactoring of the
code, as long as all the unit tests still pass, you can be reasonably sure
there are no mistakes in the refactoring. It doesn't mean the algorithm
should never change, just that it should not be changed by accident. If
algorithm output is changed, and if the change is not an accident, then the
unit test data can all be regenerated.
—
Reply to this email directly or view it on GitHub
https://github.com/ikizir/HohhaDynamicXOR/pull/12#issuecomment-175418786
.

repo: ikizir/HohhaDynamicXOR


text:
Cannot parse alias.* as column definition in select statements

statement like "select m.* from modell m  where m.name = null" fails

Support of * select statements in combination with aliases now supported.

source: gharchive/issue

repo: iks-github/SqlPojoMemoDB

license_type: permissive

license_source: bigquery


text:
Stack@Illinois!

Doin' it for the meme.

oh true, lemme do that quick

source: gharchive/pull-request

repo: illinois/queue

license: NCSA

license_source: github-api


text:
Button more missing in first time running application

Thank's your pod is very help me to make first application. But in xcode 8.3.3, ios 10.3, running in simulator Iphone SE found bug. Button more missing in first time application running but if click in area more can see all text. after click less, in second it's display more appear. Hope this bug can clear in next push.
Success!

Hi,
Same issue, is there a workaround?
Thanks

@mariokovacevic i use this code and this issue is done.
let readMoreTextAttributes:[String: Any] = [
NSForegroundColorAttributeName: view.tintColor,
NSFontAttributeName: UIFont.boldSystemFont(ofSize: 15)
]
hope help you.

you probably have a mismatch between font or frame width used when view is created and a final font

authors: freishya ilyapuchka mariokovacevic

repo: ilyapuchka/ReadMoreTextView

license: mit


text:
Unknown lag from DC2

hey! i was using dangerouscaves before, and now i updated to dangerous caves2, im going to do a heapdup later today, but with 40 - 60 players for some reason dangerouscaves2 is on top of the timings and i also have some mobs, cave aging and cave-ins disabled, and before updating to dangerouscaves 2 it was not like this: https://timings.aikar.co/?id=0d18e4256e7f496d9afa39cadcf0d4de#plugins

Can't find anything really related to lags from DC2. Would be better if you'll try spark tool.

Someone messaged me with the same problem. I guess it's confirmed now.
Tried to fix the issue in latest commit https://github.com/imDaniX/Dangerous-Caves-2/commit/6857a801495b3a2e05b77de48878e02907294aef

hey, im going to take a guess here, i have a plugin called serverbooster, wich limits entities per chunk, and if a limit is reached it will prevent mobs from spawning, even if another plugin is trying to spawn one, maybe your plugin tries to tick a mob that has been removed and it creates some kind of loop or something, i dont really know much about java so im just taking a guess

DC2 tries to spawn a new mob(with some chance) when server is trying to spawn vanilla mob, so, I don't think so.
Anyway, this is not the case. The lag is coming from 4-tick(entity) scheduler, and it somehow loads chunks.
Honestly, I still can't find any major freezes coming from DC2 in your timings. Right now I'm lack of information, because there's only two of you guys who experiencing it.
Did you try latest build?

Closed due to inactivity.

Meh, someone messaged me about chunk loading on latest version. Still waiting for some the spark analysis.

Hey! I Came back, sorry i have not been active, i was changing My host provider to a dedicated server and now i'm not anymore in a shared host, i tought maybe the lag was being caused by the host, but yes it was the plugin
Recently in My new host (one of the lastest ryzen with 64gb)
I installed your plugin again because i Saw You updated the plugin, and it had been working Nice for two days, and suddenly My tps went down to 8, only with 4 players on the server, and when i went to timings i saw this: https://timings.aikar.co/?id=ad93e7aa36514ea794c69f196c3e4d93#plugins
Dangerous caves was at the top with a count of 4000000+, i also managed to make a heap dump with spark so probably later today i Will send a download link once i'm able, what i think may be happening is that the plugin has a memory leak and it can get so Bad from one second to another, yesterday i had the plugin on the server with 50 people playing and there were no problems, and today with no reason this happened with 4 players.

If you can please test latest build.

Should be fixed now.

okay, i will test it

authors: imDaniX plebexer

license: MIT


text:
Tree Chart

You could do a Tree Chart. Maybe with a zoom animation, and autoincrease.

@imaNNeoFighT tree chart in new version?

@imaNNeoFighT tree chart in new version?

I do not promise.
I will work on this library in my free time. Otherwise, you can donate me to push me to work more.

I do not promise.
I will work on this library in my free time. Otherwise, you can donate me to push me to work more.

authors: Maclaon guillermopineda imaNNeoFighT


text:
在项目中集成hubot

hubot是github开发的机器人组件，github用于部署。打算在caas中引入hubot，可以用来部署程序、发微博等等。

太早

repo: imcj/caas


text:
Add Feature: Stats Overview Display

Feature Description
Add the ability to allow site to display various stats/data/analytics (eg. # of pages, # of blog posts, # of GH contributors, page visits, ect.)
The possibilities are endless
Problem/Solution
Gives a customizable overview of data that you may want to display
Alternatives Considered
None
Additional Context
Some inspiration:
Neofetch
github-stats

We can use GitHub's API to fetch contributor data, which can be displayed on the site.
For page and post counts, we can use Hugo's internal variables.
Can you assign this issue to me ? @3knight

repo: imfing/hextra


text:
"Corruption detected" on messages sent by Heka

Here is my heka Output config :
[MonitoringPrometheusOutput]
type = "UdpOutput"
message_matcher = "Type == 'MonitoringInput'"
encoder = "ProtobufEncoder"
address = "xxx.xxx.xxx.xxx:50569"}}"

Messages are sent via UDP to the exporter, but they all get rejected with the error :
 Corruption detected at bytes: xxx
Apparently when calling :
n, record, err := sr.GetRecordFromStream(listener)

record is always empty. the exporter calls :
bytesRead = bytes.IndexByte(buf, message.RECORD_SEPARATOR)

and bytesRead is always -1.
does it mean I don't use the right encoder ? I get confused, as your code states that it should receive heka protobuf messages.

try adding: use_framing = true to your output config
example:
[MonitoringPrometheusOutput]
type = "UdpOutput"
message_matcher = "Type == 'MonitoringInput'"
encoder = "ProtobufEncoder"
address = "xxx.xxx.xxx.xxx:50569"

authors: PrFalken davidbirdsong


text:
Thread safe request context

Is it possible with this module to achieve thread safe request context? I found some documentation on official cxf website (http://cxf.apache.org/faq.html) and that part of code:
((BindingProvider)proxy).getRequestContext().put("thread.local.request.context", "true");

The documentation indicated is about client proxies. Not server side. play-cxf is server side only. You don't need to use it for calling other SOAP services. I think all available SOAP clients should work well together with Play out-of-the-box.

authors: kustra lsnpatryks

repo: imindeu/play-cxf


text:
Seems tunnel has broken?

Currently I use 2.0.0, but failed to use mobiledevice tunnel in two device, all log out

Failed to bind to port 22!

Can I enable verbose log to figure out what really happened?

Can you try ports equal to or above 1024?

I always port to 2222  or  other larger value

Any way to enable verbose log?
@imkira

What do you mean by "port to 2222" ? Your error message shows "port 22".

Sorry,   seems I make a mistake by bind device 2222 to local 22,  it should be tunnel 2222 22, I make a  wrong assume of the from to port. Thanks for you reply.

Nice! I'm closing this assuming you're already found the solution to your problem.

repo: imkira/mobiledevice


text:
Implementation of a 'Frequency'-value

A Value indicting how often a Message should be send from FIROS to the outside of the ROS-World.
It should be enough to change the Publish Routine in Topic-Handler.

Fixed by: e82b1a04d92e25da4e9b6d70e30770d452c5aff1

Commit is in Master.


text:
Produce function mutates the base state with Buffer.

🐛 Bug Report
Produce function mutates the base state with Buffer.
Link to repro
There is no need for the repo, it's quite simple code for Node.js:
const { produce } = require('immer');

const ob = { buf: Buffer.from(`qwerty`) };
const ob1 = produce(ob, draftState => {
  draftState.buf.write('MUTATED');
});
console.log(ob.buf.toString());

Expected behavior
console.log(ob.buf.toString()) should prints qwerty, because base state should't be mutated. But it prints MUTATE, so the Buffer was overwritten.
Environment
Node: v13.13.0
Immer: 6.0.3

As documented Immer only supports plain arrays and objects, Maps, Sets, and specially marked custom classes. To mutate buffers you will have to clone and assign it to buf manually.

authors: mweststrate yrsh

repo: immerjs/immer