I am trying to perform non-linear functions on bytes to implement SAFER+. The algorithm requires computing base-45 logarithm on bytes, and I don't understand how to do it.
log45(201) = 1.39316393
When I assign this to a byte, the value is truncated to 1, and I can't recover the exact result.
How am I supposed to handle this?
So you have a byte value (from 0 to 255), and you want to get the log base 45, and store it in another byte? As others have said, you're going to lose some accuracy in doing that. However, you can do better than just casting the
double
result to abyte
.The log base 45 of 255 is approximately 1.455675. You can store that in a byte, with some loss of accuracy, by multiplying it by a constant factor. What constant factor? You could use 100, which would give you a value of 145, but you're losing almost half the range of a byte. Since the largest value you want to represent is 1.455675, you can use a constant multiplier of
255/log45(255)
, or about 175.176.How well does this work? Let's see ...
Under .NET 4 on my machine, that gives me a maximum error of 2.1419%, and an average error of 1.0501%.
You can reduce the average error by rounding the result from
Math.Pow
. That is:That reduces the average error to 0.9300%, but increases the maximum error to 3.8462%.
This is not really an answer, but a fraction of the users viewing this question will probably be interrested in the conversion of a
double
type to abyte[]
type. What could be done is simply:and
this uses the
BitConverter
class which I believe exists in .NET initialy.Showing us the code might help but I suspect your problem comes from storing the result.
If you want to store a non-integer number you don't want to put it into a byte since that will truncate it (as you are seeing). Instead store the result in a double or something more appropriate:
I should add that I'm not sure what SAFER+ is so this answer may not be helpful but hopefully it should point you in the right direction.
Cryptography often uses prime fields, in this case, GF(257). Create an exponentiation table that looks like this:
The "log" values are 45exp % 257. You'll need an arbitrary precision arithmetic library with a
modPow
function (raise a number to a power, modulo some value) to build this table. You can see that the value for "exp" 128 is a special case, since normally the logarithm of zero is undefined.Compute the logarithm of a number by finding the it in the "log" column; the value in the "exp" column of that row is the logarithm.
Here's a sketch of the initialization:
With this setup, for example, log45(131) =
log[131]
= 63, and 4538 =exp[38]
= 59.(I've never written C#; I'm just guessing from the
BigInteger
documentation; there are likely to be errors with the data types.)