Is there a way to perform modinverse in C#? My data is in BigInteger format.
P : E61E05F338BC965421720C4128C33FDFC7BC3CE637A3BC92A114E79AC380C90387988639224FE5C578B601E505C85AF85EB86DAEC06413EA419187D1D2396C063CDA7DC805E47906E731F4A0B2C53521CAC812BE68044DBFA8E3DE4BE1E0D94F2E0CC9FC126D21E5AF7038FA0942D12700AFC4DE2D00FB3A1FA6A224D0FA0D7B
dP : 00000000000000000000000000010001
dP^-1 mod P
I've tried BigInteger.ModPow(dP, -1, P). But I cannot use negative exponent.
You have to implement Extended Euclidian Algorithm first:
public static BigInteger Egcd(BigInteger left,
BigInteger right,
out BigInteger leftFactor,
out BigInteger rightFactor) {
leftFactor = 0;
rightFactor = 1;
BigInteger u = 1;
BigInteger v = 0;
BigInteger gcd = 0;
while (left != 0) {
BigInteger q = right / left;
BigInteger r = right % left;
BigInteger m = leftFactor - u * q;
BigInteger n = rightFactor - v * q;
right = left;
left = r;
leftFactor = u;
rightFactor = v;
u = m;
v = n;
gcd = right;
}
return gcd;
}
And then
public static BigInteger ModInverse(BigInteger value, BigInteger modulo) {
BigInteger x, y;
if (1 != Egcd(value, modulo, out x, out y))
throw new ArgumentException("Invalid modulo", nameof(modulo));
if (x < 0)
x += modulo;
return x % modulo;
}
Related
As part of my school project, I've tried to create the RSA encryption algorithm. I've followed the pseudocode and added all the operations, however after encrypting and decryption, the program does not return the original plaintext.
using System;
using System.Collections.Generic;
using System.Numerics;
namespace ConsoleApp4
{
class Program
{
private static readonly int INTLIMIT = 2; //represents the max size in bit value
static void Main(string[] args)
{
BigInteger x = generate2048Integer();
BigInteger y = generate2048Integer();
Console.WriteLine(x);
Console.WriteLine(y);
BigInteger n = x * y;
BigInteger a = x - 1;
BigInteger b = y - 1;
BigInteger phi = BigInteger.Abs(a * b) / dgcd(a, b);
BigInteger e = 65537;
BigInteger d = newModInv(e, phi);
BigInteger key = RSAEncryption(77, e, n);
BigInteger text = RSADecryption(key, d, n);
Console.WriteLine(text);
}
public static BigInteger generate2048Integer()
{
Random r = new Random();
string s = "";
for (int i = 0; i < INTLIMIT; i++)
{
s += Convert.ToString(r.Next(0, 9));
}
return BigInteger.Parse(s);
}
public static BigInteger dgcd(BigInteger a, BigInteger b)
{
while (b != 0)
{
BigInteger t = b;
b = mod(a, b);
a = t;
}
return a;
}
public static BigInteger newModInv(BigInteger a, BigInteger b)
{
BigInteger t = 0;
BigInteger r = b;
BigInteger newt = 1;
BigInteger newr = a;
while(newr != 0)
{
BigInteger q = r / newr;
(t, newt) = (newt, t - q * newt);
(r, newr) = (newr, r - q * newr);
}
if (r > 1)
{
return 0;
}
if(t < 0)
{
t = t + b;
}
return t;
}
public static BigInteger mod(BigInteger x, BigInteger m)
{
return (x % m + m) % m;
}
public static BigInteger RSAEncryption(BigInteger plaintext, BigInteger pubD, BigInteger n)
{
BigInteger rtrn = mod(Pow(plaintext, pubD), n);
return rtrn;
}
public static BigInteger RSADecryption(BigInteger ciphertext, BigInteger privD, BigInteger n)
{
BigInteger rtrn = mod(Pow(ciphertext, privD), n);
return rtrn;
}
public static BigInteger Pow(BigInteger value, BigInteger exponent)
{
BigInteger originalValue = value;
while (exponent-- > 1)
value = BigInteger.Multiply(value, originalValue);
return value;
}
}
}
I'm not sure where I've gone wrong here, I believe it may be something to do with the Encryption though.
I'm having troubles solving modulo in c#. The example below
7^-1 modulo 26
when on Wolfram Alpha returns correct 15. In c# when I tried direct:
1/7 % 26
it returns unwanted 0.142857142857143 instead of desired 15.
But i'm not a master mathematician, so i'm probably missing something vital.
Your are looking for modular inversion: in case of
7**-1 modulo 26 = x
or
1 / 7 modulo 26 = x
you actually want to find out an x such that
(x * 7) modulo 26 = 1
In our case x == 15 since
15 * 7 == 105 == 26 * 4 + 1
For small modulo values (like 26) you can find the answer (15) with a help of naive for loop:
int modulo = 26;
int div = 7;
int result = 0;
for (int i = 1; i < modulo; ++i)
if ((i * div) % modulo == 1) {
result = i;
break;
}
Console.Write(result);
In general case, you can obtain the result with a help of Extended Euclid Algorithm. Often, when working with modulo arithmetics we face huge numbers, that's why let me show the code for BigInteger; if it's not your case you can turn BigInteger to good old int.
Code:
using System.Numerics;
...
private static (BigInteger LeftFactor,
BigInteger RightFactor,
BigInteger Gcd) Egcd(this BigInteger left, BigInteger right) {
BigInteger leftFactor = 0;
BigInteger rightFactor = 1;
BigInteger u = 1;
BigInteger v = 0;
BigInteger gcd = 0;
while (left != 0) {
BigInteger q = right / left;
BigInteger r = right % left;
BigInteger m = leftFactor - u * q;
BigInteger n = rightFactor - v * q;
right = left;
left = r;
leftFactor = u;
rightFactor = v;
u = m;
v = n;
gcd = right;
}
return (LeftFactor: leftFactor,
RightFactor: rightFactor,
Gcd: gcd);
}
The inversion itself will be
private static BigInteger ModInversion(BigInteger value, BigInteger modulo) {
var egcd = Egcd(value, modulo);
if (egcd.Gcd != 1)
throw new ArgumentException("Invalid modulo", nameof(modulo));
BigInteger result = egcd.LeftFactor;
if (result < 0)
result += modulo;
return result % modulo;
}
Demo:
using System.Numerics;
...
BigInteger result = ModInversion(7, 26);
Console.Write(result);
Outcome:
15
I tried this:
static int myPow(int x)
{
int power = x + 1;
int num = 0;
for (int i = 0; i < power; i++)
{
num = x * i;
x = x + num;
}
return num;
}
how can I factorize the int x by x+1 without using Math.Pow?
The idea is to multiply X by X in a loop by X+1 times.
Follow the steps:
find the power (x + 1)
start the variable result with the x value (result = x)
loop i from 1 to power and for each loop multiply result by x, witch means x * x * x * x power times.
static int myPow(int x) {
int power = x + 1;
int result = x;
for (int i = 1; i < power; i++)
{
result *= x;
}
return result;
}
Take a look on the implementation it did on rextester
FYI factorization in math is this. Just for fun, the result can be calculated with Exponentiation by squaring:
static int myPow(int x, int y)
{
if (y < 0) { throw new ArgumentException("y has to be nonnegative"); }
int result = 1;
while (y > 0)
{
if ((y & 1) == 1)
{
result *= x;
}
x = x * x;
y >>= 1;
}
return result;
}
You can use a technique called exponentiation by squaring, which is quite beautiful and is also faster, it takes O(lg k) time, where k is exponent:
static int square(int n){
return n * n;
}
static int pow(int n, int k){
if(k == 1) return n;
if(k % 2 == 1) return n * pow(n, k-1);
return square(pow(n, k/2));
}
then, if you want to get x^(x+1), you just need yo call pow(x, x+1).
small, fast and simple as that :)
Is there a built in function that would allow me to calculate the modular inverse of a(mod n)?
e.g. 19^-1 = 11 (mod 30), in this case the 19^-1 == -11==19;
Since .Net 4.0+ implements BigInteger with a special modular arithmetics function ModPow (which produces “X power Y modulo Z”), you don't need a third-party library to emulate ModInverse. If n is a prime, all you need to do is to compute:
a_inverse = BigInteger.ModPow(a, n - 2, n)
For more details, look in Wikipedia: Modular multiplicative inverse, section Using Euler's theorem, the special case “when m is a prime”. By the way, there is a more recent SO topic on this: 1/BigInteger in c#, with the same approach suggested by CodesInChaos.
int modInverse(int a, int n)
{
int i = n, v = 0, d = 1;
while (a>0) {
int t = i/a, x = a;
a = i % x;
i = x;
x = d;
d = v - t*x;
v = x;
}
v %= n;
if (v<0) v = (v+n)%n;
return v;
}
The BouncyCastle Crypto library has a BigInteger implementation that has most of the modular arithmetic functions. It's in the Org.BouncyCastle.Math namespace.
Here is a slightly more polished version of Samuel Allan's algorithm. The TryModInverse method returns a bool value, that indicates whether a modular multiplicative inverse exists for this number and modulo.
public static bool TryModInverse(int number, int modulo, out int result)
{
if (number < 1) throw new ArgumentOutOfRangeException(nameof(number));
if (modulo < 2) throw new ArgumentOutOfRangeException(nameof(modulo));
int n = number;
int m = modulo, v = 0, d = 1;
while (n > 0)
{
int t = m / n, x = n;
n = m % x;
m = x;
x = d;
d = checked(v - t * x); // Just in case
v = x;
}
result = v % modulo;
if (result < 0) result += modulo;
if ((long)number * result % modulo == 1L) return true;
result = default;
return false;
}
There is no library for getting inverse mod, but the following code can be used to get it.
// Given a and b->ax+by=d
long[] u = { a, 1, 0 };
long[] v = { b, 0, 1 };
long[] w = { 0, 0, 0 };
long temp = 0;
while (v[0] > 0)
{
double t = (u[0] / v[0]);
for (int i = 0; i < 3; i++)
{
w[i] = u[i] - ((int)(Math.Floor(t)) * v[i]);
u[i] = v[i];
v[i] = w[i];
}
}
// u[0] is gcd while u[1] gives x and u[2] gives y.
// if u[1] gives the inverse mod value and if it is negative then the following gives the first positive value
if (u[1] < 0)
{
while (u[1] < 0)
{
temp = u[1] + b;
u[1] = temp;
}
}
I have 3 byte arrays of length 128, 128, 3 bytes respectively. I don't know what it is, but I expect them to be Modulus, D, Exponent.
Now how can I use these arrays in C# to decrypt a byte array using RSA?
When I create an RSAParameters and assign the 3 byte arrays to Modulus, D, Exponent and try to use that RSAParameters in RSACryptoServiceProvider.ImportParameters, decryption fails stating corrupt keys. I guess the other entries also need to be filled DQ,DP,...etc...
How do I do that in C#? I don't have that values, is there an easy way to decrypt a byte array using only Modulus, D, Exponent in C#, as in other languages?
The Windows implementations seem to only be willing to do RSA via the CRT parameters, leaving D as a potentially ignored value. At the very least, the CRT parameters are required inputs.
First, we need to turn your arrays into BigInteger values. I'm assuming here that you have Big-Endian encoded values. If they're Little-Endian, don't call Array.Reverse() and change the copy-to index from 1 to 0.
private static BigInteger GetBigInteger(byte[] bytes)
{
byte[] signPadded = new byte[bytes.Length + 1];
Buffer.BlockCopy(bytes, 0, signPadded, 1, bytes.Length);
Array.Reverse(signPadded);
return new BigInteger(signPadded);
}
Adding the extra byte prevents numbers from being treated as negative. (One could avoid the allocation and memory copy by testing for the sign bit in the last byte, if one wanted).
So now you have three BigInteger values, n, e, d. Not sure which of n and d is which?
// Unless someone tried really hard to make this break it'll work.
if (n < d)
{
BigInteger tmp = n;
n = d;
d = tmp;
}
Now, using the algorithm from NIST Special Publication 800-56B Recommendation for Pair-Wise August 2009 Key Establishment Schemes Using Integer Factorization Cryptography, Appendix C (as shared in https://stackoverflow.com/a/28299742/6535399) we can calculate the BigInteger values. There's a tricky subtlety, though. RSAParameters values have to have a correct amount of padding, and RSACryptoServiceProvider doesn't do it for you.
private static RSAParameters RecoverRSAParameters(BigInteger n, BigInteger e, BigInteger d)
{
using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
{
BigInteger k = d * e - 1;
if (!k.IsEven)
{
throw new InvalidOperationException("d*e - 1 is odd");
}
BigInteger two = 2;
BigInteger t = BigInteger.One;
BigInteger r = k / two;
while (r.IsEven)
{
t++;
r /= two;
}
byte[] rndBuf = n.ToByteArray();
if (rndBuf[rndBuf.Length - 1] == 0)
{
rndBuf = new byte[rndBuf.Length - 1];
}
BigInteger nMinusOne = n - BigInteger.One;
bool cracked = false;
BigInteger y = BigInteger.Zero;
for (int i = 0; i < 100 && !cracked; i++)
{
BigInteger g;
do
{
rng.GetBytes(rndBuf);
g = GetBigInteger(rndBuf);
}
while (g >= n);
y = BigInteger.ModPow(g, r, n);
if (y.IsOne || y == nMinusOne)
{
i--;
continue;
}
for (BigInteger j = BigInteger.One; j < t; j++)
{
BigInteger x = BigInteger.ModPow(y, two, n);
if (x.IsOne)
{
cracked = true;
break;
}
if (x == nMinusOne)
{
break;
}
y = x;
}
}
if (!cracked)
{
throw new InvalidOperationException("Prime factors not found");
}
BigInteger p = BigInteger.GreatestCommonDivisor(y - BigInteger.One, n);
BigInteger q = n / p;
BigInteger dp = d % (p - BigInteger.One);
BigInteger dq = d % (q - BigInteger.One);
BigInteger inverseQ = ModInverse(q, p);
int modLen = rndBuf.Length;
int halfModLen = (modLen + 1) / 2;
return new RSAParameters
{
Modulus = GetBytes(n, modLen),
Exponent = GetBytes(e, -1),
D = GetBytes(d, modLen),
P = GetBytes(p, halfModLen),
Q = GetBytes(q, halfModLen),
DP = GetBytes(dp, halfModLen),
DQ = GetBytes(dq, halfModLen),
InverseQ = GetBytes(inverseQ, halfModLen),
};
}
}
With the "tricky" BigInteger-to-suitable-for-RSAParameters-byte[] method:
private static byte[] GetBytes(BigInteger value, int size)
{
byte[] bytes = value.ToByteArray();
if (size == -1)
{
size = bytes.Length;
}
if (bytes.Length > size + 1)
{
throw new InvalidOperationException($"Cannot squeeze value {value} to {size} bytes from {bytes.Length}.");
}
if (bytes.Length == size + 1 && bytes[bytes.Length - 1] != 0)
{
throw new InvalidOperationException($"Cannot squeeze value {value} to {size} bytes from {bytes.Length}.");
}
Array.Resize(ref bytes, size);
Array.Reverse(bytes);
return bytes;
}
And for computing InverseQ you need ModInverse:
private static BigInteger ModInverse(BigInteger e, BigInteger n)
{
BigInteger r = n;
BigInteger newR = e;
BigInteger t = 0;
BigInteger newT = 1;
while (newR != 0)
{
BigInteger quotient = r / newR;
BigInteger temp;
temp = t;
t = newT;
newT = temp - quotient * newT;
temp = r;
r = newR;
newR = temp - quotient * newR;
}
if (t < 0)
{
t = t + n;
}
return t;
}
On my computer I'm recovering P and Q from (n, e, d) in ~50ms for a 1024-bit key. ~2-4 seconds for a 4096-bit key.
Note to implementers who like unit tests: There's not really a defined order for P and Q (like a convention that P always be the larger), so your P and Q values may be backwards from an RSAParameters structure that you started with. DP and DQ will thus also be reversed.
You don't have enough when you just have Mod, D, and the exponent. (Well you might have enough) P and Q are VERY hard to calculate from the mod. I wouldn't know how to do that and there are almost certainly more primes than the right ones that multiplied end up with the same mod.
You need atleast P, Q and the public exponent.
P, Q and D are the building blocks
DP = D mod (p - 1)
DQ = D mod (q - 1)
InverseQ = Q^-1 mod p
Modulus = P * Q
so now we have
P Q and D.
and we can calulate DP, DQ, InverseQ and Modulus and Exponent (see below)
long gcd(long a, long b)
{
long temp;
while (b != 0)
{
temp = b;
b = a % b;
a = temp;
}
return a;
}
Exponent = gcd(1, (P - 1)*(Q - 1));