#成果物
C#のコンソールテスト用です
https://github.com/Oinary/SecureValue/blob/master/Program.cs
#1.やりたいこと
・改ざんされちゃマズい数値を守りたい!(ゲーム内のHPやお金など)
・ファイルだけではなくメモリ上の数値も保護したい。(今回はInt型とFloat型)
#2.何を使えば出来るか
XOR(排他的論理和)で解決。
https://qiita.com/kuuso1/items/778acaa7011d98a3ff3a
簡単に言うと2進数で2つの数を演算したとき
片方がTrue(1)ならTrue。 0 xor 1 → 1
両方がTrue又はFalse(0)ならFalse。 0 xor 0 → 0
これって同じ値で演算しなおすと元の値に戻るんです。
1010 xor 0110 → 1100
1100 xor 0110 → 1010
科学の力ってすげぇ(てきとう
#3.実装してみた
まずXORを使うのには、元の値とそれを合わせる値が必要。
C#でランダムな整数をもらってきます。(これはちゃんと保存しましょう)
Random.Next()
https://docs.microsoft.com/ja-jp/dotnet/api/system.random.next?view=netframework-4.8
あとは ^ 演算子で保存、復元すれば解決!
private int Seed;
private int Value;
public int _Value
{
get
{
return Value ^ Seed;
}
set
{
Seed = new Random().Next()//ランダムなInt
Value = value ^ Seed;//あとはお好きに
}
}
##3-1.そうは上手くいかなかった
Int型は何も問題なく実装できましたが…。
Float型ってXORを直接は使えない。(馬鹿には分からなかった。
##3-2.じゃぁどう回避しようか
ヒントがここにあった…。
https://qiita.com/nia_tn1012/items/d26f0fc993895a09b30b
Floatで後ろ23ビットは仮数部と呼ばれる、我々が目にする数が格納されているところがあります。
例 2.345 → 2345 (小数点を無くした値になります)
その仮数部を隠せば良さげです。
※これはイメージです
float F = 1.55f;//得たfloat
var I = BitConverter.ToInt32(BitConverter.GetBytes(F),0);//これをbyte[]にして、Int型にさせる
var SignificandPart = I << 9;//左に9ビットシフトすると仮数部だけ残る
var SecureValue = SignificandPart ^ Seed;//あとは煮るなり焼くなり
//戻すときはこの逆で
で出来上がりなのですが、まぁ操作多いんですよ。
なんかこう、もっとサクッとFloatをIntにできないんですかね…。
・・・あったわ
その参照記事の下に別の方法が書かれています。
ポインタを扱うこと がポイント♪ で内部値をInt型で取得できます。
private int SecValue;
private int Seed;
public unsafe float _Value
{
get
{
var result = SecValue ^ Seed;
return BitConverter.ToSingle(BitConverter.GetBytes(result), 0);//戻すときは一度byte[]にしてからFloatに変換。
}
set
{
CalculatingSeed();
int v = *((int*)&value);//&valueでvalueのポインタを取得、(int*)でInt型のポインタを格納、最初の*でそのポインタの値を指す。
SecValue = v ^ Seed;//あとはお好きに
}
}
ポインタの使用は、本来はバグなど意図しない動作を防ぐために制限されています。
それを解除するため、unsafe を明示します。([VisualStudioの設定もお忘れずに][link-1])
[link-1]:https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/compiler-options/unsafe-compiler-option
これで守りたい値の保護方法が実装できそうです。
#4.さいごに
不正の種類はいくつもあるので、それ相応の対応をしなければなりません。
が、あの手この手で不正してくるはずです。
実装するコストと見合っているかどうかも検討しないと、クオリティや製作時間に響いちゃいます。
僕みたいな初級の個人ゲームクリエイターならお遊び程度でいいんじゃないでしょうかね。
では初記事をご覧いただきありがとうございました。
※ってか一番大事なメモリエディタの画像なくね?