diff --git a/OpenBullet/Views/StackerBlocks/PageBlockFunction.xaml b/OpenBullet/Views/StackerBlocks/PageBlockFunction.xaml
index a7401bf..6b922a3 100644
--- a/OpenBullet/Views/StackerBlocks/PageBlockFunction.xaml
+++ b/OpenBullet/Views/StackerBlocks/PageBlockFunction.xaml
@@ -160,6 +160,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenBullet/Views/StackerBlocks/PageBlockFunction.xaml.cs b/OpenBullet/Views/StackerBlocks/PageBlockFunction.xaml.cs
index 4fff818..421d4bd 100644
--- a/OpenBullet/Views/StackerBlocks/PageBlockFunction.xaml.cs
+++ b/OpenBullet/Views/StackerBlocks/PageBlockFunction.xaml.cs
@@ -116,25 +116,29 @@ namespace OpenBullet.Views.StackerBlocks
break;
*/
- case BlockFunction.Function.CharAt:
+ case BlockFunction.Function.RSAPKCS1PAD2:
functionTabControl.SelectedIndex = 11;
break;
- case BlockFunction.Function.Substring:
+ case BlockFunction.Function.CharAt:
functionTabControl.SelectedIndex = 12;
break;
- case BlockFunction.Function.GetRandomUA:
+ case BlockFunction.Function.Substring:
functionTabControl.SelectedIndex = 13;
break;
+ case BlockFunction.Function.GetRandomUA:
+ functionTabControl.SelectedIndex = 14;
+ break;
+
case BlockFunction.Function.AESEncrypt:
case BlockFunction.Function.AESDecrypt:
- functionTabControl.SelectedIndex = 14;
+ functionTabControl.SelectedIndex = 15;
break;
case BlockFunction.Function.PBKDF2PKCS5:
- functionTabControl.SelectedIndex = 15;
+ functionTabControl.SelectedIndex = 16;
break;
}
}
@@ -149,6 +153,7 @@ namespace OpenBullet.Views.StackerBlocks
{ "Compute", "Calculates the value of a math expression, for example (6+3)*5 will return 45." },
{ "RSAEncrypt", "Encrypts data with RSA. All parameters must be provided as base64 strings" },
{ "RSADecrypt", "Decrypts data with RSA. All parameters must be provided as base64 strings" },
+ { "RSAPKCS1PAD" , "Encrypts data with RSA Pkcs1Pad2. Modulus and exponent must be provided as HEX strings."},
{ "Delay", "Write the amount of MILLISECONDS you want to wait in the input field" },
{ "CharAt", "Returns the character at the specified index of the string in the input field" },
{ "AESEncrypt", "Encrypts data with AES. All parameters must be provided as base64 strings. Uses SHA-256 to get a 256 bit key" },
diff --git a/RuriLib/Blocks/BlockFunction.cs b/RuriLib/Blocks/BlockFunction.cs
index cc55a73..fbfdf1c 100644
--- a/RuriLib/Blocks/BlockFunction.cs
+++ b/RuriLib/Blocks/BlockFunction.cs
@@ -117,6 +117,9 @@ namespace RuriLib
// Decrypts a string with RSA.
// RSADecrypt,
+ /// Encrypts a string with RSA PKCS1PAD2.
+ RSAPKCS1PAD2,
+
/// Waits a given amount of milliseconds.
Delay,
@@ -423,14 +426,19 @@ namespace RuriLib
LineParser.SetBool(ref input, this);
break;
- /*
- case Function.RSADecrypt:
+ /*
+ case Function.RSADecrypt:
+ RsaN = LineParser.ParseLiteral(ref input, "Public Key Modulus");
+ RsaD = LineParser.ParseLiteral(ref input, "Private Key Exponent");
+ if (LineParser.Lookahead(ref input) == TokenType.Boolean)
+ LineParser.SetBool(ref input, this);
+ break;
+ */
+
+ case Function.RSAPKCS1PAD2:
RsaN = LineParser.ParseLiteral(ref input, "Public Key Modulus");
- RsaD = LineParser.ParseLiteral(ref input, "Private Key Exponent");
- if (LineParser.Lookahead(ref input) == TokenType.Boolean)
- LineParser.SetBool(ref input, this);
+ RsaE = LineParser.ParseLiteral(ref input, "Public Key Exponent");
break;
- */
case Function.GetRandomUA:
if (LineParser.ParseToken(ref input, TokenType.Parameter, false, false) == "BROWSER")
@@ -579,6 +587,12 @@ namespace RuriLib
break;
*/
+ case Function.RSAPKCS1PAD2:
+ writer
+ .Literal(RsaN)
+ .Literal(RsaE);
+ break;
+
case Function.GetRandomUA:
if (UserAgentSpecifyBrowser)
{
@@ -792,6 +806,14 @@ namespace RuriLib
break;
*/
+ case Function.RSAPKCS1PAD2:
+ outputString = Crypto.RSAPkcs1Pad2(
+ localInputString,
+ ReplaceValues(RsaN, data),
+ ReplaceValues(RsaE, data)
+ );
+ break;
+
case Function.Delay:
try { Thread.Sleep(int.Parse(localInputString)); } catch { }
break;
diff --git a/RuriLib/Functions/Crypto/Crypto.cs b/RuriLib/Functions/Crypto/Crypto.cs
index 08119ce..2373677 100644
--- a/RuriLib/Functions/Crypto/Crypto.cs
+++ b/RuriLib/Functions/Crypto/Crypto.cs
@@ -4,6 +4,8 @@ using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
+using System.Globalization;
+using System.Numerics;
namespace RuriLib.Functions.Crypto
{
@@ -307,6 +309,68 @@ namespace RuriLib.Functions.Crypto
oaep
);
}
+
+ ///
+ /// Encrypts a message using RSA with PKCS1PAD2 padding.
+ ///
+ /// The message as a UTF-8 string
+ /// The public key's modulus as a HEX string
+ /// The public key's exponent as a HEX string
+ /// The encrypted message.
+ // Thanks to TheLittleTrain for this implementation.
+ public static string RSAPkcs1Pad2(string message, string modulus, string exponent)
+ {
+ // Convert the public key components to numbers
+ var n = HexToBigInteger(modulus);
+ var e = HexToBigInteger(exponent);
+
+ // (modulus.ToByteArray().Length - 1) * 8
+ //modulus has 256 bytes multiplied by 8 bits equals 2048
+ var encryptedNumber = Pkcs1Pad2(message, (2048 + 7) >> 3);
+
+ // And now, the RSA encryption
+ encryptedNumber = BigInteger.ModPow(encryptedNumber, e, n);
+
+ //Reverse number and convert to base64
+ var encryptedString = Convert.ToBase64String(encryptedNumber.ToByteArray().Reverse().ToArray());
+
+ return encryptedString;
+ }
+
+ private static BigInteger HexToBigInteger(string hex)
+ {
+ return BigInteger.Parse("00" + hex, NumberStyles.AllowHexSpecifier);
+ }
+
+ private static BigInteger Pkcs1Pad2(string data, int keySize)
+ {
+ if (keySize < data.Length + 11)
+ return new 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 BigInteger(buffer);
+ }
#endregion
#region KDF