-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFormulaHasher.cpp
More file actions
209 lines (166 loc) · 5.26 KB
/
FormulaHasher.cpp
File metadata and controls
209 lines (166 loc) · 5.26 KB
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/*
* Author: Ctl-F (Spencer Brough)
* Date: 07/15/2020
* */
#include "FormulaHasher.h"
namespace ctl_f {
FormulaHasher::FormulaHasher() {
}
FormulaHasher::~FormulaHasher() {
}
string FormulaHasher::hash(string input) {
if (input.length() < HASH_SIZE) {
input = growInput(input);
}
else if (input.length() > HASH_SIZE) {
input = shrinkInput(input);
}
return sewInput(input);
}
/*
Take the character from the end, split it in half
and add it to the front of the string's characters
and so on
*/
string FormulaHasher::shrinkInput(string input) {
if (input == "") {
return "";
}
input = xorFilter(input);
int index = 0;
char currentChar;
while (input.length() > HASH_SIZE) {
currentChar = input[input.length()-1];
input[index] += (currentChar & 0b11110000) >> 4;
input[index] ^= (~(currentChar & 0b00001111)) | (currentChar & 0b11110000);
if (++index >= input.length()) {
index = 0;
}
input[index] += (currentChar & 0b00001111);
input[index] ^= (~((currentChar & 0b11110000) >> 4)) | ((currentChar & 0b00001111) << 4);
if (++index >= input.length()) {
index = 0;
}
input = input.erase(input.length() - 1);
}
return xorFilter(input);
}
// apply a simple xor filter over the string by itself
// use an accumulated shift to offset the character each time
string FormulaHasher::xorFilter(string input) {
if (input == "") {
return "";
}
char c;
int accumulator = 0;
for (int i = 0; i < input.length(); i++) {
c = input[i];
for (int j = 0; j < input.length(); j++) {
input[j] ^= (c << accumulator);
if (++accumulator > 4) {
accumulator = 0;
}
}
}
return input;
}
/*
We are going to take each bit in each character
invert it and move forward by an accumulated counter
e.g.
given: 01000010
we will grab the zero, invert it to get a 1
then we add 1 to the accumulator
then we move forward by the accumulator (1) and grab the 1
inverting it we get 0 and the output character becomes 10
and we add 2 to the accumulator (3)
we then move forward by 3 getting a 0, inverting it becomes a 1
and adding it to the output become 101
then we add 1 to the accumulator (4) and we move forward by 4
and so on.
NOTE: for a zero bit we add 1 to the accumulator
for a one bit we add 2 to the accumulator
When the accumulator reaches 8 we will wrap it down to zero and
continue until we've generated a new byte. then we move forward to
the next byte and repeat until the given string is the correct length
*/
string FormulaHasher::growInput(string input) {
int length = input.length();
if (length < 1) {
return "";
}
// strings with 4 or less characters seem to break the xorFilter so we're going to do a psudo growth before
// proceeding with the rest of the algorithm
unsigned char modMask = 0b01101001;
if(input.length() <= 4){
int offset = 0;
while(input.length() < 8){
input += input[offset++] % modMask + offset;
modMask <<= 1;
if(offset >= input.length()){
offset = 0;
}
}
}
input = xorFilter(input);
const unsigned char BIT_MASK = 0b00000001;
unsigned int currentBit = 0;
// as explained above
int accumulator = 0;
// the byte of data we are currently generating
unsigned char currentGeneration = 0;
// how many bits have we generated so far in the current generation
int generationCount = 0;
// Take the first character, swap the halves and modulate by the length to get the starting index
// current index in the input string
unsigned char firstChar = input[0];
size_t currentStringIndex = ((firstChar & 0b11110000) >> 4) | ((firstChar & 0b00001111) << 4);
currentStringIndex %= input.length();
// reference to the original string character
char currentStringCharacter = input[currentStringIndex];
while (input.length() < HASH_SIZE) {
// take the current bit
currentBit = (currentStringCharacter >> accumulator) & BIT_MASK;
// logical not to get just a zero or a one
// a bitwise not would give us a 255 or a 254
currentGeneration |= !currentBit;
currentGeneration <<= 1;
accumulator += currentBit + 1;
if (accumulator > 7) {
accumulator -= 8;
}
if (++generationCount == 8) {
generationCount = 0;
input += (char)currentGeneration;
if (++currentStringIndex >= input.length()) {
currentStringIndex = 0;
}
currentStringCharacter = input[currentStringIndex];
}
}
return xorFilter(input);
}
/*
* Take the character, apply it to a character with an accumulative offset over the string
* to apply: Add, mod by 7, xor by result
* */
string FormulaHasher::sewInput(string input) {
if(input == "") {
return "";
}
if(input.length() < 2){
return input;
}
input = xorFilter(input);
int accumulatedOffset = 1;
char currentChar = 0;
for(int i=0; i<input.length(); i++){
currentChar = input[i];
input[i + accumulatedOffset] ^= (currentChar + input[i + accumulatedOffset]) % 7;
if(++accumulatedOffset + i >= input.length()){
accumulatedOffset = -i;
}
}
return xorFilter(input);
}
};