Skip to content

Instantly share code, notes, and snippets.

@steamb23
Last active January 16, 2016 19:15
Show Gist options
  • Save steamb23/e2912aa53fac9e3052a2 to your computer and use it in GitHub Desktop.
Save steamb23/e2912aa53fac9e3052a2 to your computer and use it in GitHub Desktop.
/*
* Author : SteamB23
* License : MIT
*/
using System.Runtime.Serialization;
namespace System
{
/// <summary>
/// A 64-bit integer type that contains simple encryption features.
/// </summary>
[Serializable]
public struct SecureInt64 : ISerializable
{
const byte keysLength = 16;
readonly static long[] keys = new long[]
{
6338887092739851599,
7430565509821446124,
-9042072405887803858,
1330224199253267991,
-7155745344322912499,
-9089750803117477263,
3712924929968051920,
322698015418847168,
9214776268477700801,
6896323569820898924,
1766586946294160572,
-253872918563961160,
6507740389827041271,
1690234834608976180,
-7814391039444818982,
6742709491675838358
};
bool hashErr;
byte keyIndex;
long hash;
long value;
public SecureInt64(long value)
{
this.hashErr = false;
this.keyIndex = (byte)(value % keysLength);
long secureValue = value ^ keys[keyIndex];
this.hash = ComputeHash(secureValue);
this.value = secureValue;
}
public long Value
{
get
{
HashCheck();
if (hashErr)
{
this.hash = ComputeHash(keys[0]);
this.value = keys[0];
this.keyIndex = 0;
return Decryption(this.value, this.keyIndex);
}
else
{
return Decryption(this.value, this.keyIndex);
}
}
set
{
HashCheck();
if (hashErr)
{
this.hash = ComputeHash(keys[0]);
this.value = keys[0];
this.keyIndex = 0;
}
else
{
long secureValue = Encryption(value, out this.keyIndex);
this.hash = ComputeHash(secureValue);
this.value = secureValue;
}
}
}
public long GetRawValue()
{
return this.value;
}
bool HashCheck(long value)
{
return this.hash == ComputeHash(value);
}
void HashCheck()
{
this.hashErr = !HashCheck(this.value);
}
static long ComputeHash(long value)
{
value += ~(value << 15);
value ^= (value >> 10);
value += (value << 3);
value ^= (value >> 6);
value += ~(value << 11);
value ^= (value >> 16);
return value;
}
static long Encryption(long value, out byte keyIndex)
{
keyIndex = (byte)(value % keysLength);
return value ^ keys[keyIndex];
}
static long Decryption(long value, byte keyIndex)
{
return value ^ keys[keyIndex];
}
#region Operator overloading implements
public static SecureInt64 operator +(SecureInt64 value)
{
value.Value = +value.Value;
return value;
}
public static SecureInt64 operator -(SecureInt64 value)
{
value.Value = -value.Value;
return value;
}
public static SecureInt64 operator ~(SecureInt64 value)
{
value.Value = ~value.Value;
return value;
}
public static SecureInt64 operator ++(SecureInt64 value)
{
value.Value++;
return value;
}
public static SecureInt64 operator --(SecureInt64 value)
{
value.Value--;
return value;
}
public static SecureInt64 operator +(SecureInt64 left, long right)
{
left.Value += right;
return left;
}
public static SecureInt64 operator +(SecureInt64 left, SecureInt64 right)
{
left.Value += right.Value;
return left;
}
public static SecureInt64 operator -(SecureInt64 left, long right)
{
left.Value -= right;
return left;
}
public static SecureInt64 operator -(SecureInt64 left, SecureInt64 right)
{
left.Value -= right.Value;
return left;
}
public static SecureInt64 operator *(SecureInt64 left, long right)
{
left.Value *= right;
return left;
}
public static SecureInt64 operator *(SecureInt64 left, SecureInt64 right)
{
left.Value *= right.Value;
return left;
}
public static SecureInt64 operator /(SecureInt64 left, long right)
{
left.Value /= right;
return left;
}
public static SecureInt64 operator /(SecureInt64 left, SecureInt64 right)
{
left.Value /= right.Value;
return left;
}
public static SecureInt64 operator %(SecureInt64 left, long right)
{
left.Value %= right;
return left;
}
public static SecureInt64 operator %(SecureInt64 left, SecureInt64 right)
{
left.Value %= right.Value;
return left;
}
public static SecureInt64 operator &(SecureInt64 left, long right)
{
left.Value &= right;
return left;
}
public static SecureInt64 operator &(SecureInt64 left, SecureInt64 right)
{
left.Value &= right.Value;
return left;
}
public static SecureInt64 operator |(SecureInt64 left, long right)
{
left.Value |= right;
return left;
}
public static SecureInt64 operator |(SecureInt64 left, SecureInt64 right)
{
left.Value |= right.Value;
return left;
}
public static SecureInt64 operator ^(SecureInt64 left, long right)
{
left.Value ^= right;
return left;
}
public static SecureInt64 operator ^(SecureInt64 left, SecureInt64 right)
{
left.Value ^= right.Value;
return left;
}
public static SecureInt64 operator <<(SecureInt64 left, int right)
{
left.Value <<= right;
return left;
}
public static SecureInt64 operator >>(SecureInt64 left, int right)
{
left.Value >>= right;
return left;
}
public static bool operator ==(SecureInt64 left, long right)
{
return left.Value == right;
}
public static bool operator ==(SecureInt64 left, SecureInt64 right)
{
return left.Value == right.Value;
}
public static bool operator !=(SecureInt64 left, long right)
{
return left.Value != right;
}
public static bool operator !=(SecureInt64 left, SecureInt64 right)
{
return left.Value != right.Value;
}
public static bool operator <(SecureInt64 left, long right)
{
return left.Value < right;
}
public static bool operator <(SecureInt64 left, SecureInt64 right)
{
return left.Value < right.Value;
}
public static bool operator >(SecureInt64 left, long right)
{
return left.Value > right;
}
public static bool operator >(SecureInt64 left, SecureInt64 right)
{
return left.Value > right.Value;
}
public static bool operator <=(SecureInt64 left, long right)
{
return left.Value <= right;
}
public static bool operator <=(SecureInt64 left, SecureInt64 right)
{
return left.Value <= right.Value;
}
public static bool operator >=(SecureInt64 left, long right)
{
return left.Value >= right;
}
public static bool operator >=(SecureInt64 left, SecureInt64 right)
{
return left.Value >= right.Value;
}
public static implicit operator SecureInt64(long value)
{
return new SecureInt64(value);
}
public static implicit operator long (SecureInt64 value)
{
return value.Value;
}
#endregion
#region Operator overloading extra implements
// override object.Equals
public override bool Equals(object obj)
{
return this.Value.Equals(obj);
}
// override object.GetHashCode
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value.ToString();
}
#endregion
#region ISerializeable implements
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("value", this.value);
info.AddValue("hash", this.hash);
info.AddValue("keyIndex", this.keyIndex);
}
public SecureInt64(SerializationInfo info, StreamingContext context)
{
this.hashErr = false;
this.value = info.GetInt64("value");
this.hash = info.GetInt64("hash");
this.keyIndex = info.GetByte("keyIndex");
}
#endregion
}
}
@steamb23
Copy link
Author

steamb23 commented Jan 4, 2016

설명서

개인적으로 쓰려고 만든건데 치트유저들을 괴롭히고 싶은 분들을 위해 공개합니다.
32비트 정수형식을 원하시면 그냥 파일내의 long을 int로 바꿔주시면 될겁니다. (테스트는 안해봤어요._)

사용법

모든 연산자가 오버로딩되있기 때문에 그냥 64비트 정수형 쓰듯이 쓰시면 됩니다.

성능

성능은... 측정해보진 못했는데 아마 AES같은 알고리즘보다는 백배는 빠를겁니다 'ㅅ'!

뚫렸을 경우

이것도 키나 소스코드가 들통나면 뚫릴수야 있겠지만 키 배열에 저장되있는 키와 갯수 해쉬알고리즘(이라하기도 벅찬 놈)을 조금 수정해주는 것만으로도 일단 차단이 가능할겁니다.

알고리즘 설명

값 집어넣기 알고리즘

  1. 현재 저장된 값과 해쉬값을 비교합니다. 문제가 발견되면 값을 0으로 초기화시킵니다.
  2. 값을 XOR연산해서 암호화하는데, 이때, 16개의 키에 대한 인덱스를 값에 대한 나머지 연산을 통해 뽑아내 키를 가지고 XOR연산합니다. 뽑아낸 키의 인덱스 번호는 저장이 됩니다.
  3. 암호화된 값을 초간단 해쉬 함수에 집어넣고 돌린값을 별도로 저장해둡니다.

값 가져오기 알고리즘

  1. 현재 저장된 값과 해쉬값을 비교합니다. 문제가 발견되면 값을 0으로 초기화시킵니다.
  2. 암호화 된 값을 저장된 키의 인덱스에 대한 키를 가져와 xor연산을 사용하여 풀어냅니다.
  3. 값을 전달합니다.

@steamb23
Copy link
Author

steamb23 commented Jan 4, 2016

ISerializable를 구현하여 직렬화가 가능합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment