Disregard the above - I jumped on the wrong function :-(
0
Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.
Actually this appears only work with 1048577. In other words, if I try any other numbers it fails. For example, 1048977 yields 10401 but is reversed to 1048577
I realize that bits 16-19 are going to be lost, but I'm being told that those bytes are not used. Therefore, if someone can prove that the algo can't be reversed, I'll award the 500 pts and if someone can produce the algorithm, I'll add 500 pts for a total of 1,000 pts.
>>>
No. You are loosing the bits 0-20(!) also by 'id >> 20' - this discards the lower 20 bits of any number
<<<
Actually the terminalId is set to >> 20. The checkNbr is then given 16 of those bytes by AND'ing it with FFFF (which effectively throws away everything above the 15th bit).
Therefore, the terminalId is bits 20 and above (which is then multiplied by 1000) and the checkNbr is bits 0-15. As a result, the only lost data is bits 16-19.
You're absolutely correct. 1048577 >> 20 is equal to 1. However, that's only the first part of the equation.
unsigned long terminalId = (unsigned long)PullTerminalId(id) * 10000;
// PullTerminalId returns the passed value shifted right 20 places
The second part then takes the same starting value (1048577 in the example) and then moves its 15 left digits into another variable:
unsigned long checkNbr = (unsigned)(id & 0xFFFF);
Therefore,
* bits 0-15 go into local variable checkNbr
* bits 20+ got into local variable terminalId (where they're mult by 1000)
See what I mean. You're focusing only on the terminalId where the right-most 20 bits are intentionally removed. 16 of those bits are then isolated into checkNbr.
But it's not lost as the first part of the equation doesn't alter the value used in the second. See what I mean?
The shifting of the bits occurs in a separate function on a variable local to that function. Back in the main calling function the original input value is being used again to then isolate bits 0-15.
I think what might be throwing you is that:
1048577 & 0xFFFF == 1
Looks very strange, but if you input the value into calc and then switch to binary, you'll see that only the left-most and right-most bit are on. AND'ing this value with 0xFFFF will yield the value 1. I think this is where you're thinking data is being lost when it isn't
So it breaks down like this where I've noted the impact of each function call or arithmetic operation in comments:
get_human_check_id(1048577);
// calling get_human_check_id with a value of 1048577
unsigned long get_human_check_id(unsigned long id)
{
// id == 1048577
unsigned long terminalId = (unsigned long)PullTerminalId(id) * 10000;
// calls PullTerminalId and then multiplies results by 1000
// id == 1048577
// terminalId == 1001
unsigned long checkNbr = (unsigned)(id & 0xFFFF);
// assigns checkNbr to the right 16 bits of the value in id
// id == 1048577
// terminalId == 1001
// checkNbr == 1
return terminalId + checkNbr;
// adds terminalId (1001) and checkNbr (1) and returns that value (1001)
}
unsigned PullTerminalId(unsigned long id)
{
// id == 1048577
return ((unsigned)(id >> 20));
// returns only the 20+ bits of id (but id is not changed)
}
In order for it to be reversable, for every possible output of the get_human_check_id function, there would have to be only one possible input. If two inputs to get_human_check_id generate the same output, then there is no way for the reverse function to determine which of those inputs to generate as its output.
2 to the 20th power (1048576) as an input to get_human_check_id generates an output of 10000. An input of 10000 also generates an output of 10000. So a reverse algorithm given an input of 10000 cannot determine what output to generate. So the get_human_check_id algorithm is not reversable.
>>>> What I need is a function that will do the reverse.
>>>> The algorithm cannot be reversed.
efn - and jkr in his later posts - is absolutely right. Bit shifting means reducing information as some bits turn to 0 independent of the source number. A reducing algorithm never is reverseable.
You should make some XOR operation instead:
z = x^y;
x = z^y;
Here bits are toggled if a bit is set in y or remain as it is if a bit of y is 0. Both operations will reverse the original bit when doing it again.
I have no control over the original function. I'm simply looking to see if I can produce the reverse of that function within the framework of their system. IOW, I know bits 16-19 are not used so that's not a problem. However, as efn said the major problem will be that since multiple inputs can result in the same output, then by definition, I'll never be able to reverse to the original value. Basically, it would be like trying to reverse engineer a hash code, which can't be reversed for the same reason.
Actually, the inner loop could be simplified a little.
...
result = (a << 20u) + residue;
for(b = 0; b < 16; b++) {
printf("get_human_check_id(%u) = %u\n", result,
get_human_check_id(result);
result += 65536;
}
...
There will always be n*16 results, where 0 <= n <= 7.
0
Featured Post
Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.
unsigned get_human_check_id(unsigne
{
return ((unsigned)(id << 20));
}