Files
OpenBullet/RuriLib/Blocks/BlockFunction.cs
T

1266 lines
48 KiB
C#

using Extreme.Net;
using RuriLib.LS;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Media;
namespace RuriLib
{
/// <summary>
/// A block that can execute a specific function on one or multiple inputs.
/// </summary>
public class BlockFunction : BlockBase
{
/// <summary>
/// The function name.
/// </summary>
public enum Function
{
/// <summary>Simply replaced the variables of the input.</summary>
Constant,
/// <summary>Encodes an input as a base64 string.</summary>
Base64Encode,
/// <summary>Decodes the string from a base64-encoded input.</summary>
Base64Decode,
/// <summary>Hashes an input string.</summary>
Hash,
/// <summary>Generates a HMAC for a given string.</summary>
HMAC,
/// <summary>Translates words in a given string.</summary>
Translate,
/// <summary>Converts a formatted date to a unix timestamp.</summary>
DateToUnixTime,
/// <summary>Gets the length of a string.</summary>
Length,
/// <summary>Converts all uppercase caracters in a string to lowercase.</summary>
ToLowercase,
/// <summary>Converts all lowercase characters in a string to uppercase.</summary>
ToUppercase,
/// <summary>Replaces some text with something else, with or without using regex.</summary>
Replace,
/// <summary>Gets the first match for a specific regex pattern.</summary>
RegexMatch,
/// <summary>Encodes the input to be used in a URL.</summary>
URLEncode,
/// <summary>Decodes a URL-encoded input.</summary>
URLDecode,
/// <summary>Encodes the input to be displayed in HTML or XML.</summary>
HTMLEntityEncode,
/// <summary>Decoded an input containing HTML or XML entities.</summary>
HTMLEntityDecode,
/// <summary>Converts a unix timestamp to a formatted date.</summary>
UnixTimeToDate,
/// <summary>Retrieves the current time as a unix timestamp.</summary>
CurrentUnixTime,
/// <summary>Converts a unix timestamp to the ISO8601 format.</summary>
UnixTimeToISO8601,
/// <summary>Generates a random integer.</summary>
RandomNum,
/// <summary>Generates a random string based on a mask.</summary>
RandomString,
/// <summary>Rounds a decimal input to the upper integer.</summary>
Ceil,
/// <summary>Rounds a decimal input to the lower integer.</summary>
Floor,
/// <summary>Rounds a decimal input to the nearest integer.</summary>
Round,
/// <summary>Computes mathematical operations between decimal numbers.</summary>
Compute,
/// <summary>Counts the occurrences of a string in another string.</summary>
CountOccurrences,
/// <summary>Clears the cookie jar used for HTTP requests.</summary>
ClearCookies,
/// <summary>Encrypts a string with RSA given a Key.</summary>
RSA,
/// <summary>Waits a given amount of milliseconds.</summary>
Delay,
/// <summary>Retrieves the character at a given index in the input string.</summary>
CharAt,
/// <summary>Gets a substring of the input.</summary>
Substring,
/// <summary>Reverses the input string.</summary>
ReverseString,
/// <summary>Removes leading or trailing whitespaces from a string.</summary>
Trim,
/// <summary>Gets a valid random User-Agent header.</summary>
GetRandomUA,
/// <summary>Encrypts a string with AES.</summary>
AESEncrypt,
/// <summary>Decrypts an AES-encrypted string.</summary>
AESDecrypt
}
/// <summary>
/// The available hashing functions.
/// </summary>
public enum Hash
{
/// <summary>The MD5 hashing function (128 bits digest).</summary>
MD5,
/// <summary>The SHA-1 hashing function (160 bits digest).</summary>
SHA1,
/// <summary>The SHA-256 hashing function (256 bits digest).</summary>
SHA256,
/// <summary>The SHA-384 hashing function (384 bits digest).</summary>
SHA384,
/// <summary>The SHA-512 hashing function (512 bits digest).</summary>
SHA512,
}
#region General Properties
private string variableName = "";
/// <summary>The name of the output variable.</summary>
public string VariableName { get { return variableName; } set { variableName = value; OnPropertyChanged(); } }
private bool isCapture = false;
/// <summary>Whether the output variable should be marked for Capture.</summary>
public bool IsCapture { get { return isCapture; } set { isCapture = value; OnPropertyChanged(); } }
private string inputString = "";
/// <summary>The input string on which the function will be executed (not always needed).</summary>
public string InputString { get { return inputString; } set { inputString = value; OnPropertyChanged(); } }
private Function functionType = Function.Constant;
/// <summary>The function to execute.</summary>
public Function FunctionType { get { return functionType; } set { functionType = value; OnPropertyChanged(); } }
#endregion
#region Function Specific Properties
// -- Hash & Hmac
private Hash hashType = Hash.SHA512;
/// <summary>The hashing function to use.</summary>
public Hash HashType { get { return hashType; } set { hashType = value; OnPropertyChanged(); } }
// -- Hmac
private string hmacKey = "";
/// <summary>The key used to authenticate the message.</summary>
public string HmacKey { get { return hmacKey; } set { hmacKey = value; OnPropertyChanged(); } }
private bool hmacBase64 = false;
/// <summary>Whether to output the message as a base64-encoded string instead of a hex-encoded string.</summary>
public bool HmacBase64 { get { return hmacBase64; } set { hmacBase64 = value; OnPropertyChanged(); } }
// -- Translate
private bool stopAfterFirstMatch = true;
/// <summary>Whether to stop translating after the first match.</summary>
public bool StopAfterFirstMatch { get { return stopAfterFirstMatch; } set { stopAfterFirstMatch = value; OnPropertyChanged(); } }
/// <summary>The dictionary containing the words and their translation.</summary>
public Dictionary<string, string> TranslationDictionary { get; set; } = new Dictionary<string, string>();
// -- Date to unix
private string dateFormat = "yyyy-MM-dd:HH-mm-ss";
/// <summary>The format of the date (y = year, M = month, d = day, H = hour, m = minute, s = second).</summary>
public string DateFormat { get { return dateFormat; } set { dateFormat = value; OnPropertyChanged(); } }
// -- string replace
private string replaceWhat = "";
/// <summary>The text to replace.</summary>
public string ReplaceWhat { get { return replaceWhat; } set { replaceWhat = value; OnPropertyChanged(); } }
private string replaceWith = "";
/// <summary>The replacement text.</summary>
public string ReplaceWith { get { return replaceWith; } set { replaceWith = value; OnPropertyChanged(); } }
private bool useRegex = false;
/// <summary>Whether to use regex for replacing.</summary>
public bool UseRegex { get { return useRegex; } set { useRegex = value; OnPropertyChanged(); } }
// -- Regex Match
private string regexMatch = "";
/// <summary>The regex pattern to match.</summary>
public string RegexMatch { get { return regexMatch; } set { regexMatch = value; OnPropertyChanged(); } }
// -- Random Number
private int randomMin = 0;
/// <summary>The minimum random number that can be generated.</summary>
public int RandomMin { get { return randomMin; } set { randomMin = value; OnPropertyChanged(); } }
private int randomMax = 0;
/// <summary>The maximum random number that can be generated.</summary>
public int RandomMax { get { return randomMax; } set { randomMax = value; OnPropertyChanged(); } }
// -- CountOccurrences
private string stringToFind = "";
/// <summary>The string to count the occurrences of.</summary>
public string StringToFind { get { return stringToFind; } set { stringToFind = value; OnPropertyChanged(); } }
// -- RSA
private string rsaMod = "";
/// <summary>The modulus of the RSA key.</summary>
public string RSAMod { get { return rsaMod; } set { rsaMod = value; OnPropertyChanged(); } }
private string rsaExp = "";
/// <summary>The exponent of the RSA key.</summary>
public string RSAExp { get { return rsaExp; } set { rsaExp = value; OnPropertyChanged(); } }
// --- CharAt
private string charIndex = "0";
/// <summary>The index of the wanted character.</summary>
public string CharIndex { get { return charIndex; } set { charIndex = value; OnPropertyChanged(); } }
// -- Substring
private string substringIndex = "0";
/// <summary>The starting index for the substring.</summary>
public string SubstringIndex { get { return substringIndex; } set { substringIndex = value; OnPropertyChanged(); } }
private string substringLength = "1";
/// <summary>The length of the wanted substring.</summary>
public string SubstringLength { get { return substringLength; } set { substringLength = value; OnPropertyChanged(); } }
// -- AES
private string aesKey = "";
/// <summary>The keys used for AES encryption and decryption.</summary>
public string AesKey { get { return aesKey; } set { aesKey = value; OnPropertyChanged(); } }
#endregion
/// <summary>
/// Creates a Function block.
/// </summary>
public BlockFunction()
{
Label = "FUNCTION";
}
/// <inheritdoc />
public override BlockBase FromLS(string line)
{
// Trim the line
var input = line.Trim();
// Parse the label
if (input.StartsWith("#"))
Label = LineParser.ParseLabel(ref input);
/*
* Syntax:
* FUNCTION Name [ARGUMENTS] ["INPUT STRING"] [-> VAR/CAP "NAME"]
* */
// Parse the function
FunctionType = (Function)LineParser.ParseEnum(ref input, "Function Name", typeof(Function));
// Parse specific function parameters
switch (FunctionType)
{
case Function.Hash:
HashType = LineParser.ParseEnum(ref input, "Hash Type", typeof(Hash));
break;
case Function.HMAC:
HashType = LineParser.ParseEnum(ref input, "Hash Type", typeof(Hash));
HmacKey = LineParser.ParseLiteral(ref input, "HMAC Key");
while (LineParser.Lookahead(ref input) == TokenType.Boolean)
LineParser.SetBool(ref input, this);
break;
case Function.Translate:
if (LineParser.Lookahead(ref input) == TokenType.Boolean)
LineParser.SetBool(ref input, this);
TranslationDictionary = new Dictionary<string, string>();
while (input != "" && LineParser.Lookahead(ref input) == TokenType.Parameter)
{
LineParser.EnsureIdentifier(ref input, "KEY");
var k = LineParser.ParseLiteral(ref input, "Key");
LineParser.EnsureIdentifier(ref input, "VALUE");
var v = LineParser.ParseLiteral(ref input, "Value");
TranslationDictionary[k] = v;
}
break;
case Function.DateToUnixTime:
DateFormat = LineParser.ParseLiteral(ref input, "DATE FORMAT");
break;
case Function.Replace:
ReplaceWhat = LineParser.ParseLiteral(ref input, "What");
ReplaceWith = LineParser.ParseLiteral(ref input, "With");
if (LineParser.Lookahead(ref input) == TokenType.Boolean)
LineParser.SetBool(ref input, this);
break;
case Function.RegexMatch:
RegexMatch = LineParser.ParseLiteral(ref input, "Pattern");
break;
case Function.RandomNum:
RandomMin = LineParser.ParseInt(ref input, "Minimum");
RandomMax = LineParser.ParseInt(ref input, "Maximum");
break;
case Function.CountOccurrences:
StringToFind = LineParser.ParseLiteral(ref input, "string to find");
break;
case Function.CharAt:
CharIndex = LineParser.ParseLiteral(ref input, "Index");
break;
case Function.Substring:
SubstringIndex = LineParser.ParseLiteral(ref input, "Index");
SubstringLength = LineParser.ParseLiteral(ref input, "Length");
break;
case Function.RSA:
RSAMod = LineParser.ParseLiteral(ref input, "Modulus");
RSAExp = LineParser.ParseLiteral(ref input, "Exponent");
break;
default:
break;
}
// Try to parse the input string
if (LineParser.Lookahead(ref input) == TokenType.Literal)
InputString = LineParser.ParseLiteral(ref input, "INPUT");
// Try to parse the arrow, otherwise just return the block as is with default var name and var / cap choice
if (LineParser.ParseToken(ref input, TokenType.Arrow, false) == "")
return this;
// Parse the VAR / CAP
try
{
var varType = LineParser.ParseToken(ref input, TokenType.Parameter, true);
if (varType.ToUpper() == "VAR" || varType.ToUpper() == "CAP")
IsCapture = varType.ToUpper() == "CAP";
}
catch { throw new ArgumentException("Invalid or missing variable type"); }
// Parse the variable/capture name
try { VariableName = LineParser.ParseToken(ref input, TokenType.Literal, true); }
catch { throw new ArgumentException("Variable name not specified"); }
return this;
}
/// <inheritdoc />
public override string ToLS(bool indent = true)
{
var writer = new BlockWriter(GetType(), indent, Disabled);
writer
.Label(Label)
.Token("FUNCTION")
.Token(FunctionType);
switch (FunctionType)
{
case Function.Hash:
writer
.Token(HashType);
break;
case Function.HMAC:
writer
.Token(HashType)
.Literal(HmacKey)
.Boolean(HmacBase64, "HmacBase64");
break;
case Function.Translate:
writer
.Boolean(StopAfterFirstMatch, "StopAfterFirstMatch");
foreach (var t in TranslationDictionary)
writer
.Indent()
.Token("KEY")
.Literal(t.Key)
.Token("VALUE")
.Literal(t.Value);
writer
.Indent();
break;
case Function.DateToUnixTime:
writer
.Literal(DateFormat, "DateFormat");
break;
case Function.Replace:
writer
.Literal(ReplaceWhat)
.Literal(ReplaceWith)
.Boolean(UseRegex, "UseRegex");
break;
case Function.RegexMatch:
writer
.Literal(RegexMatch, "RegexMatch");
break;
case Function.RandomNum:
writer
.Integer(RandomMin)
.Integer(RandomMax);
break;
case Function.CountOccurrences:
writer
.Literal(StringToFind);
break;
case Function.CharAt:
writer
.Literal(CharIndex);
break;
case Function.Substring:
writer
.Literal(SubstringIndex)
.Literal(SubstringLength);
break;
case Function.RSA:
writer
.Literal(RSAMod)
.Literal(RSAExp);
break;
}
writer
.Literal(InputString, "InputString");
if (!writer.CheckDefault(VariableName, "VariableName"))
writer
.Arrow()
.Token(IsCapture ? "CAP" : "VAR")
.Literal(VariableName);
return writer.ToString();
}
/// <inheritdoc />
public override void Process(BotData data)
{
base.Process(data);
var style = NumberStyles.Number | NumberStyles.AllowCurrencySymbol;
var provider = new CultureInfo("en-US");
var localInputStrings = ReplaceValuesRecursive(inputString, data);
var outputs = new List<string>();
for(int i = 0; i < localInputStrings.Count; i++)
{
var localInputString = localInputStrings[i];
var outputString = "";
switch (FunctionType)
{
case Function.Constant:
outputString = localInputString;
break;
case Function.Base64Encode:
outputString = Base64Encode(localInputString);
break;
case Function.Base64Decode:
outputString = Base64Decode(localInputString);
break;
case Function.HTMLEntityEncode:
outputString = WebUtility.HtmlEncode(localInputString);
break;
case Function.HTMLEntityDecode:
outputString = WebUtility.HtmlDecode(localInputString);
break;
case Function.Hash:
outputString = GetHash(localInputString, hashType).ToLower();
break;
case Function.HMAC:
outputString = Hmac(localInputString, hashType, ReplaceValues(hmacKey, data), hmacBase64);
break;
case Function.Translate:
outputString = localInputString;
foreach (var entry in TranslationDictionary.OrderBy(e => e.Key.Length).Reverse())
{
if (outputString.Contains(entry.Key))
{
outputString = outputString.Replace(entry.Key, entry.Value);
if (StopAfterFirstMatch) break;
}
}
break;
case Function.DateToUnixTime:
outputString = (DateTime.ParseExact(localInputString, dateFormat, new CultureInfo("en-US"), DateTimeStyles.AllowWhiteSpaces)
.Subtract(new DateTime(1970, 1, 1)))
.TotalSeconds
.ToString();
break;
case Function.Length:
outputString = localInputString.Length.ToString();
break;
case Function.ToLowercase:
outputString = localInputString.ToLower();
break;
case Function.ToUppercase:
outputString = localInputString.ToUpper();
break;
case Function.Replace:
if (useRegex)
outputString = Regex.Replace(localInputString, ReplaceValues(replaceWhat, data), ReplaceValues(replaceWith, data));
else
outputString = localInputString.Replace(ReplaceValues(replaceWhat, data), ReplaceValues(replaceWith, data));
break;
case Function.RegexMatch:
outputString = Regex.Match(localInputString, ReplaceValues(regexMatch, data)).Value;
break;
case Function.URLEncode:
outputString = System.Uri.EscapeDataString(localInputString);
break;
case Function.URLDecode:
outputString = System.Uri.UnescapeDataString(localInputString);
break;
case Function.UnixTimeToDate:
try
{
var loc = localInputString;
if (localInputString.Length > 10) loc = localInputString.Substring(0, 10);
DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
dtDateTime = dtDateTime.AddSeconds(int.Parse(loc)).ToLocalTime();
outputString = dtDateTime.ToShortDateString();
}
catch { }
break;
case Function.CurrentUnixTime:
outputString = Math.Round((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds).ToString();
break;
case Function.UnixTimeToISO8601:
var loc2 = localInputString;
if (localInputString.Length > 10) loc2 = localInputString.Substring(0, 10);
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
dateTime = dateTime.AddSeconds(int.Parse(loc2)).ToLocalTime();
outputString = dateTime.ToString("yyyy-MM-ddTHH\\:mm\\:ss.fffZ");
break;
case Function.RandomNum:
outputString = (data.rand.Next(randomMin, randomMax)).ToString();
break;
case Function.RandomString:
var reserved = new string[] { "?l", "?u", "?d", "?s", "?h", "?a" };
var lowercase = "abcdefghijklmnopqrstuvwxyz";
var uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var digits = "0123456789";
var symbols = "\\!\"£$%&/()=?^'{}[]@#,;.:-_*+";
var hex = digits + "abcdef";
var allchars = lowercase + uppercase + digits + symbols;
outputString = localInputString;
while (reserved.Any(r => outputString.Contains(r))){
if (outputString.Contains("?l"))
outputString = ReplaceFirst(outputString, "?l", lowercase[data.rand.Next(0, lowercase.Length)].ToString());
else if (outputString.Contains("?u"))
outputString = ReplaceFirst(outputString, "?u", uppercase[data.rand.Next(0, uppercase.Length)].ToString());
else if (outputString.Contains("?d"))
outputString = ReplaceFirst(outputString, "?d", digits[data.rand.Next(0, digits.Length)].ToString());
else if (outputString.Contains("?s"))
outputString = ReplaceFirst(outputString, "?s", symbols[data.rand.Next(0, symbols.Length)].ToString());
else if (outputString.Contains("?h"))
outputString = ReplaceFirst(outputString, "?h", hex[data.rand.Next(0, hex.Length)].ToString());
else if (outputString.Contains("?a"))
outputString = ReplaceFirst(outputString, "?a", allchars[data.rand.Next(0, allchars.Length)].ToString());
}
break;
case Function.Ceil:
outputString = Math.Ceiling(Decimal.Parse(localInputString, style, provider)).ToString();
break;
case Function.Floor:
outputString = Math.Floor(Decimal.Parse(localInputString, style, provider)).ToString();
break;
case Function.Round:
outputString = Math.Round(Decimal.Parse(localInputString, style, provider), 0, MidpointRounding.AwayFromZero).ToString();
break;
case Function.Compute:
outputString = new DataTable().Compute(localInputString.Replace(',', '.'), null).ToString();
break;
case Function.CountOccurrences:
outputString = CountStringOccurrences(localInputString, stringToFind).ToString();
break;
case Function.ClearCookies:
data.Cookies.Clear();
break;
case Function.RSA:
try
{
while (outputString.Length < 2 || outputString.Substring(outputString.Length - 2) != "==")
{
outputString = SteamRSAEncrypt(new RsaParameters { Exponent = ReplaceValues(RSAExp, data), Modulus = ReplaceValues(RSAMod, data), Password = localInputString });
}
}
catch (Exception ex) { outputString = ex.ToString(); }
break;
case Function.Delay:
try { Thread.Sleep(int.Parse(localInputString)); } catch { }
break;
case Function.CharAt:
outputString = localInputString.ToCharArray()[int.Parse(ReplaceValues(charIndex, data))].ToString();
break;
case Function.Substring:
outputString = localInputString.Substring(int.Parse(ReplaceValues(substringIndex, data)), int.Parse(ReplaceValues(substringLength,data)));
break;
case Function.ReverseString:
char[] charArray = localInputString.ToCharArray();
Array.Reverse(charArray);
outputString = new string(charArray);
break;
case Function.Trim:
outputString = localInputString.Trim();
break;
case Function.GetRandomUA:
outputString = RandomUserAgent(data.rand);
break;
case Function.AESEncrypt:
outputString = AESEncrypt(ReplaceValues(aesKey, data), localInputString);
break;
case Function.AESDecrypt:
outputString = AESDecrypt(ReplaceValues(aesKey, data), localInputString);
break;
}
data.Log(new LogEntry(string.Format("Executed function {0} on input {1} with outcome {2}", functionType, localInputString, outputString), Colors.GreenYellow));
// Add to the outputs
outputs.Add(outputString);
}
var isList = outputs.Count > 1 || InputString.Contains("[*]") || InputString.Contains("(*)") || InputString.Contains("{*}");
InsertVariables(data, isCapture, isList, outputs, variableName, "", "", false, true);
}
#region Base64
/// <summary>
/// Encodes a string to base64.
/// </summary>
/// <param name="plainText">The string to encode</param>
/// <returns>The base64-encoded string</returns>
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
/// <summary>
/// Decodes a base64-encoded string.
/// </summary>
/// <param name="base64EncodedData">The base64-encoded string</param>
/// <returns>The decoded string</returns>
public static string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
#endregion
#region Hash and Hmac
/// <summary>
/// Hashes a string using the specified hashing function.
/// </summary>
/// <param name="baseString">The string to hash</param>
/// <param name="type">The hashing function</param>
/// <returns>The hash digest as a hex-encoded string</returns>
public static string GetHash(string baseString, Hash type)
{
switch (type)
{
case Hash.MD5:
return MD5(baseString);
case Hash.SHA1:
return SHA1(baseString);
case Hash.SHA256:
return SHA256(baseString);
case Hash.SHA384:
return SHA384(baseString);
case Hash.SHA512:
return SHA512(baseString);
default:
return "UNRECOGNIZED HASH TYPE";
}
}
/// <summary>
/// Gets the HMAC signature of a message given a key and a hashing function.
/// </summary>
/// <param name="baseString">The message to sign</param>
/// <param name="type">The hashing function</param>
/// <param name="key">The HMAC key</param>
/// <param name="base64">Whether the output should be encrypted as a base64 string</param>
/// <returns>The HMAC signature</returns>
public static string Hmac(string baseString, Hash type, string key, bool base64)
{
switch (type)
{
case Hash.MD5:
return HMACMD5(baseString, key, base64);
case Hash.SHA1:
return HMACSHA1(baseString, key, base64);
case Hash.SHA256:
return HMACSHA256(baseString, key, base64);
case Hash.SHA384:
return HMACSHA384(baseString, key, base64);
case Hash.SHA512:
return HMACSHA512(baseString, key, base64);
default:
return "UNRECOGNIZED HASH TYPE";
}
}
private static string MD5(string input)
{
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
foreach (byte b in hash)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
private static string HMACMD5(string input, string key, bool base64)
{
HMACMD5 hmac = new HMACMD5(System.Text.Encoding.ASCII.GetBytes(key));
var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input));
if (base64) { return Convert.ToBase64String(hash); }
else { return ToHex(hash); }
}
private static string SHA1(string input)
{
using (SHA1Managed sha1 = new SHA1Managed())
{
var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input));
var sb = new StringBuilder(hash.Length * 2);
foreach (byte b in hash)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
}
private static string HMACSHA1(string input, string key, bool base64)
{
HMACSHA1 hmac = new HMACSHA1(System.Text.Encoding.ASCII.GetBytes(key));
var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input));
if (base64) { return Convert.ToBase64String(hash); }
else { return ToHex(hash); }
}
private static string SHA256(string input)
{
using (SHA256Managed sha256 = new SHA256Managed())
{
var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));
var sb = new StringBuilder(hash.Length * 2);
foreach (byte b in hash)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
}
private static string HMACSHA256(string input, string key, bool base64)
{
HMACSHA256 hmac = new HMACSHA256(System.Text.Encoding.ASCII.GetBytes(key));
var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input));
if (base64) { return Convert.ToBase64String(hash); }
else { return ToHex(hash); }
}
private static string SHA384(string input)
{
using (SHA384Managed sha384 = new SHA384Managed())
{
var hash = sha384.ComputeHash(Encoding.UTF8.GetBytes(input));
var sb = new StringBuilder(hash.Length * 2);
foreach (byte b in hash)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
}
private static string HMACSHA384(string input, string key, bool base64)
{
HMACSHA384 hmac = new HMACSHA384(System.Text.Encoding.ASCII.GetBytes(key));
var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input));
if (base64) { return Convert.ToBase64String(hash); }
else { return ToHex(hash); }
}
private static string SHA512(string input)
{
using (SHA512Managed sha512 = new SHA512Managed())
{
var hash = sha512.ComputeHash(Encoding.UTF8.GetBytes(input));
var sb = new StringBuilder(hash.Length * 2);
foreach (byte b in hash)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
}
private static string HMACSHA512(string input, string key, bool base64)
{
HMACSHA512 hmac = new HMACSHA512(System.Text.Encoding.ASCII.GetBytes(key));
var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input));
if (base64) { return Convert.ToBase64String(hash); }
else { return ToHex(hash); }
}
private static string ToHex(byte[] bytes)
{
var sb = new StringBuilder(bytes.Length * 2);
foreach (byte b in bytes)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
#endregion
#region RSA
private string RSAEncrypt(string input, int size)
{
var data = Encoding.UTF8.GetBytes(input);
using (var rsa = new RSACryptoServiceProvider(size))
{
try
{
rsa.FromXmlString(input);
var encryptedData = rsa.Encrypt(data, true);
Console.WriteLine(Convert.ToString(encryptedData));
return Convert.ToString(encryptedData);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return "";
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
}
private string RSADecrypt(string input, int size)
{
var data = Encoding.UTF8.GetBytes(input);
using (var rsa = new RSACryptoServiceProvider(size))
{
try
{
rsa.FromXmlString(input);
var resultBytes = System.Text.Encoding.ASCII.GetBytes(input);
var decryptedBytes = rsa.Decrypt(resultBytes, true);
return Encoding.UTF8.GetString(decryptedBytes);
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
}
private string SteamRSAEncrypt(RsaParameters rsaParam)
{
// Convert the public keys to BigIntegers
var modulus = CreateBigInteger(rsaParam.Modulus);
var exponent = CreateBigInteger(rsaParam.Exponent);
// (modulus.ToByteArray().Length - 1) * 8
//modulus has 256 bytes multiplied by 8 bits equals 2048
var encryptedNumber = Pkcs1Pad2(rsaParam.Password, (2048 + 7) >> 3);
// And now, the RSA encryption
encryptedNumber = System.Numerics.BigInteger.ModPow(encryptedNumber, exponent, modulus);
//Reverse number and convert to base64
var encryptedString = Convert.ToBase64String(encryptedNumber.ToByteArray().Reverse().ToArray());
return encryptedString;
}
private static System.Numerics.BigInteger CreateBigInteger(string hex)
{
return System.Numerics.BigInteger.Parse("00" + hex, NumberStyles.AllowHexSpecifier);
}
private static System.Numerics.BigInteger Pkcs1Pad2(string data, int keySize)
{
if (keySize < data.Length + 11)
return new System.Numerics.BigInteger();
var buffer = new byte[256];
var i = data.Length - 1;
while (i >= 0 && keySize > 0)
{
buffer[--keySize] = (byte)data[i--];
}
// Padding, I think
var random = new Random();
buffer[--keySize] = 0;
while (keySize > 2)
{
buffer[--keySize] = (byte)random.Next(1, 256);
//buffer[--keySize] = 5;
}
buffer[--keySize] = 2;
buffer[--keySize] = 0;
Array.Reverse(buffer);
return new System.Numerics.BigInteger(buffer);
}
#endregion
#region Translation
/// <summary>
/// Builds a string containing translation keys.
/// </summary>
/// <returns>One translation key per line, with name and value separated by a colon</returns>
public string GetDictionary()
{
StringBuilder sb = new StringBuilder();
foreach (var pair in TranslationDictionary)
{
sb.Append($"{pair.Key}: {pair.Value}");
if (!pair.Equals(TranslationDictionary.Last())) sb.Append(Environment.NewLine);
}
return sb.ToString();
}
/// <summary>
/// Sets translation keys from an array of lines.
/// </summary>
/// <param name="lines">The lines containing the colon-separated name and value of the translation keys</param>
public void SetDictionary(string[] lines)
{
TranslationDictionary.Clear();
foreach (var line in lines)
{
if (line.Contains(':'))
{
var split = line.Split(new[] { ':' }, 2);
var key = split[0];
var val = split[1].TrimStart();
TranslationDictionary[key] = val;
}
}
}
#endregion
#region Count Occurrences
/// <summary>
/// Counts how many times a string occurs inside another string.
/// </summary>
/// <param name="input">The long string</param>
/// <param name="text">The text to search</param>
/// <returns>How many times the text appears in the long string</returns>
public static int CountStringOccurrences(string input, string text)
{
// Loop through all instances of the string 'text'.
int count = 0;
int i = 0;
while ((i = input.IndexOf(text, i)) != -1)
{
i += text.Length;
count++;
}
return count;
}
#endregion
#region RandomString
private string ReplaceFirst(string text, string search, string replace)
{
int pos = text.IndexOf(search);
if (pos < 0)
{
return text;
}
return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}
#endregion
#region AES
/// <summary>
/// Encrypts a string with AES.
/// </summary>
/// <param name="key">The encryption key</param>
/// <param name="data">The data to encrypt</param>
/// <returns>The AES-encrypted string</returns>
public static string AESEncrypt(string key, string data)
{
string encData = null;
byte[][] keys = GetHashKeys(key);
try
{
encData = EncryptStringToBytes_Aes(data, keys[0], keys[1]);
}
catch (CryptographicException) { }
catch (ArgumentNullException) { }
return encData;
}
/// <summary>
/// Decrypts an AES-encrypted string.
/// </summary>
/// <param name="key">The decryption key</param>
/// <param name="data">The AES-encrypted data</param>
/// <returns>The plaintext string</returns>
public static string AESDecrypt(string key, string data)
{
string decData = null;
byte[][] keys = GetHashKeys(key);
try
{
decData = DecryptStringFromBytes_Aes(data, keys[0], keys[1]);
}
catch (CryptographicException) { }
catch (ArgumentNullException) { }
return decData;
}
private static byte[][] GetHashKeys(string key)
{
byte[][] result = new byte[2][];
Encoding enc = Encoding.UTF8;
SHA256 sha2 = new SHA256CryptoServiceProvider();
byte[] rawKey = enc.GetBytes(key);
byte[] rawIV = enc.GetBytes(key);
byte[] hashKey = sha2.ComputeHash(rawKey);
byte[] hashIV = sha2.ComputeHash(rawIV);
Array.Resize(ref hashIV, 16);
result[0] = hashKey;
result[1] = hashIV;
return result;
}
private static string EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt =
new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return Convert.ToBase64String(encrypted);
}
private static string DecryptStringFromBytes_Aes(string cipherTextString, byte[] Key, byte[] IV)
{
byte[] cipherText = Convert.FromBase64String(cipherTextString);
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
string plaintext = null;
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt =
new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
#endregion
#region RandomUA
// All credits for this method goes to the Leaf.xNet fork of Extreme.NET
// https://github.com/csharp-leaf/Leaf.xNet
/// <summary>
/// Gets a random User-Agent header.
/// </summary>
/// <param name="rand">A random number generator</param>
/// <returns>A randomly generated User-Agent header</returns>
public static string RandomUserAgent(Random rand)
{
int random = rand.Next(99) + 1;
// Chrome = 70%
if (random >= 1 && random <= 70)
return Http.ChromeUserAgent();
// Firefox = 15%
if (random > 70 && random <= 85)
return Http.FirefoxUserAgent();
// IE = 6%
if (random > 85 && random <= 91)
return Http.IEUserAgent();
// Opera 12 = 5%
if (random > 91 && random <= 96)
return Http.OperaUserAgent();
// Opera mini = 4%
return Http.OperaMiniUserAgent();
}
#endregion
}
/// <summary>
/// The RSA parameters.
/// </summary>
struct RsaParameters
{
/// <summary>The key exponent.</summary>
public string Exponent;
/// <summary>The key modulus.</summary>
public string Modulus;
/// <summary>The encryption password.</summary>
public string Password;
}
}