暗号化で対数を計算するにはどうすればよいですか?
-
27-10-2019 - |
質問
Safer+を実装するために、バイトで非線形関数を実行しようとしています。アルゴリズムでは、バイトでベース45対数を計算する必要があり、その方法がわかりません。
ログ45(201) = 1.39316393
これをバイトに割り当てると、値は1に切り捨てられ、正確な結果を回復できません。
私はこれをどのように処理することになっていますか?
解決
暗号化はしばしば使用します プライムフィールド、 この場合、GF(257)。 指数テーブルを作成します それは次のように見えます:
exp | log ----+---- 0 | 1 1 | 45 2 | 226 3 | 147 ... | ... 128 | 0 ... | ... 255 | 40 ---------
「ログ」値は45ですexp %257。 modPow
このテーブルを構築するための関数(電力に数字を上げ、何らかの価値をモジュロ)します。通常はゼロの対数が未定義であるため、「EXP」128の値は特別なケースであることがわかります。
「ログ」列でITを見つけることにより、数値の対数を計算します。その行の「exp」列の値は対数です。
これが初期化のスケッチです:
BigInteger V45 = new BigInteger(45);
BigInteger V257 = new BigInteger(257);
byte[] exp = new byte[256];
for (int idx = 0; idx < 256; ++idx)
exp[idx] = BigInteger.ModPow(V45, new BigInteger(idx), V257) % 256;
byte[] log = new byte[256];
for (int idx = 0; idx < 256; ++idx)
log[exp[idx]] = idx;
たとえば、このセットアップでログ45(131) = log[131]
= 63、および4538 = exp[38]
= 59.
(私はc#を書いたことがありません;私はただから推測しています BigInteger
ドキュメンテーション;データ型にはエラーが発生する可能性があります。)
他のヒント
バイト値(0〜255)があり、ログベース45を取得し、別のバイトに保存したいですか?他の人が言ったように、あなたはそれをする際にある程度の正確さを失うでしょう。しかし、あなた できる 単にキャストするよりもうまくいく double
結果として byte
.
255のログベース45は約1.455675です。一定の要因を掛けることにより、精度をある程度失って、バイトに保存できます。一定の要因は何ですか? 100を使用できます。これにより、145の値が得られますが、バイトのほぼ半分の範囲を失っています。表現したい最大の値は1.455675であるため、一定の乗数を使用できます 255/log45(255)
, 、または約175.176。
これはどれだけうまく機能しますか?どれどれ ...
var mult = 255.0 / Math.Log(255, 45);
Console.WriteLine("Scaling factor is {0}", mult);
double errMax = double.MinValue;
double errMin = double.MaxValue;
double errTot = 0;
for (int i = 1; i < 256; ++i)
{
// Get the log of the number you want
var l = Math.Log(i, 45);
// Convert to byte
var b = (byte)(l * mult);
// Now go back the other way.
var a = Math.Pow(45, (double)b / mult);
var err = (double)(i - a) / i;
errTot += err;
errMax = Math.Max(errMax, err);
errMin = Math.Min(errMin, err);
Console.WriteLine("{0,3:N0}, {1,3:N0}, {2}, {3:P4}", i, b, a, err);
}
Console.WriteLine("max error = {0:P4}", errMax);
Console.WriteLine("min error = {0:P4}", errMin);
Console.WriteLine("avg error = {0:P4}", errTot / 255);
私のマシンの.NET 4の下では、最大誤差は2.1419%、平均誤差は1.0501%です。
結果を丸めて平均エラーを減らすことができます Math.Pow
. 。あれは:
var a = Math.Round(Math.Pow(45, (double)b / mult));
これにより、平均誤差が0.9300%に減少しますが、最大誤差は3.8462%に増加します。
コードを表示するのに役立つかもしれませんが、結果を保存することからあなたの問題は発生していると思います。
非整数番号を保存したい場合は、それをバイトに入れたくありません。代わりに、結果をダブルまたはより適切なものに保存します。
double result = math.log(154,45);
より安全な+が何であるかわからないので、この答えは役に立たないかもしれませんが、うまくいけば正しい方向に向けられるはずです。
これは実際には答えではありませんが、この質問を見ているユーザーのほんの一部は、おそらく double
aに入力します byte[]
タイプ。できることは単純です:
double theDouble = 78.24435;
byte[] theResult = BitConverter.GetBytes(theDouble);
と
byte[] theByteArray = new byte[]{0, 4, 2, 3}; //for example
double theCorrespondingDouble = BitConverter.ToDouble(theByteArray);
これはを使用します BitConverter
.NET Initialyに存在すると思われるクラス。