AnyankaKeys/CSharp/AnyankaKeys.cs
2026-04-07 07:14:02 +02:00

271 lines
10 KiB
C#

using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text.RegularExpressions;
using System.Text;
namespace Anyanka{
public class AnyankaKeys{
public static readonly char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".ToCharArray();
public static readonly byte[] PRIVATE_KEY = Enumerable.Range(0, 0x100).Select<int, byte>(i => (byte)i).ToArray<byte>();
const int MULTIPLIER = 1;
const byte MULTIPLIER_JUMPS = 3;
const byte MULTIPLIER_JUMP = 7;
public static readonly uint[] PRIMES = new uint[]{
0x3FFFFFFB, 0x3FFFFF29, 0x3FFFFF0B,
0x2FFFFFFF, 0x2FFFFF5B, 0x1FFFFFFF,
0x279DB13D, 0x279DB113,
0x2AAAAAAB, 0x1555556B, 0x27D4EB2F, 0x165667B1,
0x1000007F, 0x3B9ACA07, 0x01000193, 0x1EADBEEF, 0x0AFEBABE, 0x0BADC0DE, 0x3B9AC9C1, 0x1D295C4D, 0x990BF9F, 0x1CFAA2DB,
0xDEADBEEF, 0xCAFEBABF, 0xBAADF00D
};
public static readonly double LOGARITHM_256 = Math.Log(0x100);
public static readonly Regex RE_KEY = new Regex(@"^[a-z_][a-z0-9_]*$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public delegate byte ChangeBaseInputHandler<T>(T value);
public delegate void ChangeBaseOutputHandler(byte value);
private char[] alphabet;
private Dictionary<char, int> dictionary;
private byte[] private_key;
private int multiplier;
private byte multiplier_jumps;
private byte multiplier_jump;
private uint[] primes;
private int _base;
private int encrypt_i = 0;
private byte[] password = new byte[]{0};
public AnyankaKeys(object? inputs = null){
alphabet = unique<char>(get_array<char>(get<object>("alphabet", inputs, ALPHABET) ?? ALPHABET));
dictionary = new Dictionary<char, int>();
private_key = get_numbers<byte>(get<object>("private_key", inputs, PRIVATE_KEY) ?? PRIVATE_KEY);
multiplier = get_number<int>(get<object>("multiplier", inputs, MULTIPLIER) ?? MULTIPLIER);
multiplier_jumps = get_number<byte>(get<object>("multiplier_jumps", inputs, MULTIPLIER_JUMPS) ?? MULTIPLIER_JUMPS);
multiplier_jump = get_number<byte>(get<object>("multiplier_jump", inputs, MULTIPLIER_JUMP) ?? MULTIPLIER_JUMP);
primes = get_numbers<uint>(get<object>("primes", inputs, PRIMES) ?? PRIMES);
_base = get_number<int>(get<object>("base", inputs, alphabet.Length) ?? alphabet.Length);
for(int i = 0; i < alphabet.Length; i++)
dictionary[alphabet[i]] = i;
set_password(get<string>("password", inputs, "") ?? "");
if(_base < alphabet.Length)
_base = alphabet.Length;
}
public void set_password(string password){
List<byte> changed = new List<byte>();
if(!string.IsNullOrEmpty(password))
change_base<char>(password, _base, 0x100, (char value) => (byte)value, (byte value) => changed.Add(value));
if(changed.Count == 0)
changed.Add(0);
this.password = changed.ToArray<byte>();
}
private uint get_multiplier(int i){
uint value = (uint)(i + multiplier + primes[
i = (i + multiplier_jump) % primes.Length
]) & 0x3FFFFFFF;
for (int j = 0; j < multiplier_jumps; j++){
int shift = 13 + i % 8;
value = ((value ^ (
(i & 1) == 1 ? value >> shift : value << shift
)) + primes[
i = (i + multiplier_jump) % primes.Length
]) & 0x3FFFFFFF;
}
return value;
}
public string encrypt(string data){
int i = (int)(get_multiplier(encrypt_i + data.Length + (int)(DateTime.Now.Ticks % 1000)) % _base);
string summatory = alphabet[i].ToString();
byte[] bytes = Encoding.UTF8.GetBytes(data);
int j = (int)Math.Ceiling(bytes.Length * LOGARITHM_256 / Math.Log(_base)) + 2;
char[] encrypted = new char[j];
encrypt_i = (encrypt_i + i) % _base;
change_base<byte>(bytes, _base, 0x100, (byte value) => value, (byte value) => {
uint multiplier = get_multiplier(i ++);
encrypted[-- j] = alphabet[(multiplier + value + private_key[
multiplier / _base % private_key.Length
] + password[multiplier % password.Length]) % _base];
});
return summatory + new string(encrypted, j, encrypted.Length - j);
}
public string decrypt(string data){
int i = dictionary[data[0]] + data.Length - 1;
int j = (int)Math.Ceiling(data.Length * Math.Log(_base) / LOGARITHM_256) + 2;
byte[] decrypted = new byte[j];
change_base<char>(data.Substring(1), 0x100, _base, (char value) => {
uint multiplier = get_multiplier(-- i);
return (byte)(((dictionary[value] - private_key[
multiplier / _base % private_key.Length
] - multiplier - password[multiplier % password.Length]) % _base + _base) % _base);
}, (byte value) => {
decrypted[-- j] = value;
});
return Encoding.UTF8.GetString(decrypted, j, decrypted.Length - j);
}
public static List<string> get_keys(object? items){
List<string> keys = new List<string>();
if(items is string item_string){
if(RE_KEY.IsMatch(item_string))
keys.Add(item_string);
}else if(items is IEnumerable<string> strings){
foreach(string item_i in strings)
if(!keys.Contains(item_i) && RE_KEY.IsMatch(item_i))
keys.Add(item_i);
}else if(items is IEnumerable<object?> list)
foreach(object? item in list){
if(item == null)
continue;
if(item is string string_item){
if(!keys.Contains(string_item) && RE_KEY.IsMatch(string_item))
keys.Add(string_item);
}else
foreach(string key in get_keys(item))
if(!keys.Contains(key) && RE_KEY.IsMatch(key))
keys.Add(key);
}
return keys;
}
public static List<Dictionary<string, object?>> get_dictionaries(object? items){
List<Dictionary<string, object?>> dictionaries = new List<Dictionary<string, object?>>();
if(items is Dictionary<string, object?> dictionary)
dictionaries.Add(dictionary);
else if(items is IEnumerable<object?> list)
foreach(object? item in list)
dictionaries.AddRange(get_dictionaries(item));
return dictionaries;
}
public static T? get<T>(object keys, object? dictionaries, T? _default = default(T?)){
List<string> keys_list = get_keys(keys);
if(keys_list.Count != 0)
foreach(Dictionary<string, object?> dictionary in get_dictionaries(dictionaries))
foreach(string key in keys_list)
if(dictionary.TryGetValue(key, out object? value) && value is T typed)
return typed;
return _default;
}
public static T[] unique<T>(IEnumerable<T> items){
return items.Distinct<T>().ToArray<T>();
}
public static void change_base<T>(
IEnumerable<T> data,
int to_base,
int from_base = 0x100,
ChangeBaseInputHandler<T>? input_handler = null,
ChangeBaseOutputHandler? output_handler = null
){
int stack = 0;
bool has = false;
if(input_handler == null)
input_handler = (T value) => Convert.ToByte(value);
if(output_handler == null)
output_handler = (byte value) => { };
foreach(T value in data){
stack = stack * from_base + input_handler(value);
while(stack >= to_base){
has = true;
output_handler((byte)(stack % to_base));
stack /= to_base;
}
}
if(!has || stack != 0)
output_handler((byte)stack);
}
public static T[] get_array<T>(object data){
if(data is T item_t)
return new T[]{item_t};
if(data is string text && typeof(T) == typeof(char))
return text.ToCharArray() as T[] ?? new T[]{};
if(data is IEnumerable<T> list_t)
return list_t.ToArray();
if(data is IEnumerable list){
List<T> results = new List<T>();
foreach(object? item in list)
if(item is T typed)
results.Add(typed);
return results.ToArray();
}
return new T[]{};
}
public static T get_number<T>(object data){
if(data is T item)
return item;
return (T)Convert.ChangeType(data, typeof(T));
}
public static T[] get_numbers<T>(object data){
if(data is T item_t)
return new T[]{item_t};
if(data is T[] item_set)
return item_set;
if(data is IEnumerable list){
List<T> results = new List<T>();
foreach(object? item in list)
if(item != null)
results.Add(get_number<T>(item));
return results.ToArray();
}
return new T[]{};
}
}
}