C - RSA Cryptosystem Decryption Issue (unsigned long long not big enough?) - c

I'm working on an assignment where I have to build an RSA Cryptosystem. I was able to encrypt the cipher key no problem however I'm having trouble decrypting it due to the result of the exponent being so large. I've tried using unsigned long long int but I'm still getting an output of 0.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//Unsigned long long int power function
unsigned long long getPower(unsigned long long int base, int exponent){
unsigned long long result = 1;
int count = 0;
while(count != exponent){
result *= base;
count++;
}
return result;
}
int decryptFile(int cipherInt, int n, int d){
int plainInt;
unsigned long long int cipherIntLong = cipherInt;
unsigned long long int power = getPower(cipherIntLong, d);
printf("%llu\n", power);
return (int) plainInt;
}
int main(){
decryptFile(1394, 3127, 2011);
}
I should add that the professor made no mention of using a big number library so I'm sure we are most likely not supposed to use one for this assignment.

The maximum value of an unsigned 64-bit integer is 18,446,744,073,709,551,615
However, 1394^2011 is more around 1.296 x 10^6323. That is 7.02 x 10^6303 times larger than the maximum value of an unsigned 64-bit integer.
TL;DR: Use a BigInteger library, a really big one.
Seriously though, the main reason RSA can compute such large powers is because RSA operates under a modulus, so if we use Modular Exponentiation, we require far less computational power to reach the result. Calculating the result by raising the plaintext to the exponent and then applying the modulus at the end isn't computationally feasible.

Related

Unable to calculate factorial , getting output as 0 in C

Tried calculating factorial of 65, got correct output. Anything greater than 65 results in output of 0. Shocking since I'm using unsigned long int. What is amiss ?
Code:
#include <stdio.h>
void factorial(int unsigned long);
int main()
{
int unsigned long num, result;
printf("\nEnter number to obtain factorial : ");
scanf("%ld", &num);
factorial(num);
}
void factorial (int unsigned long x)
{
register int unsigned long f = 1;
register int unsigned long i;
for (i=x;i>=1;i--)
f= f*i;
printf("\nFactorial of %lu = %lu\n",x,f);
}
You certainly did not get the correct result for 65! log2(65!) is just over 302 bits (Google it), so you'd need a long int of at least 303 bits to calculate that correctly. There is no computer in the world where long int is over 300 bits (let's see how this answer ages!).
The largest factorial you can compute in 64 bits is 20! (which is about 2.4e18).
Adding on to #JohnZwinck, the maximum value for a variable of type unsigned long long (ULLONG_MAX) is 18446744073709551615. So all the values greater than 20! are going to have a garbage value
You can refer to this for more information.

Pow is not working for two double digit numbers

I have made a code to read two long integers (A and B) from standard input and output (to standard output) A to the power of B.
It works for 1^some huge number, 3^3 etc.
But not for 13^16.
I've tried to put long int ans to solve it, it gave me a different value but not the right one.
#include <stdio.h>
#include <math.h>
int main()
{
int x, n;
long int ans;
scanf("%d \n %d",&x, &n);
ans = pow(x,n);
printf("%d", ans);
return 0;
}
pow(1,anything) is always 1. pow(3, 3) is 27. These are both quite small numbers and easily fit into a 32 bit integer. pow(13,16) is (approximately) 6.65 x 1017. This is too big for a 32 bit integer to contain. It will go into a 64 bit integer (although pow(14, 17) will not). It's likely that your compiler treats a long as a 32 bit value, which is not uncommon. You could try long long which is likely to be 64 bits or int64_t which is explicitly 64 bits long.
Note though that the prototype for pow() is
double pow(double x, double y);
which means that it is returning a double precision floating point number and then coercing it into the type of your variable. double (a 64 bit floating point number) only has 53 bits of precision in its mantissa, which means you are not going to get the exact number when you cast it back to even a 64 bit integer. You could use powl() whose prototype is
long double powl(long double x, long double y);
But long double might be defined as 80 bits or 128 bits or even only 64 bits (Microsoft). It might give you the precision you need, but such is the nature of power operations, your input numbers won't have to get much bigger to overflow the precision of even the longest long double.
If you really need to raise large numbers to large powers, you are going to need a big integer library.
Rather than use floating point pow() and friends with their potential limited precision for an integer problem within 64 bits (1316 needs 60 bits), use an integer power function.
unsigned long long upow(unsigned x, unsigned y) {
unsigned long long z = 1;
unsigned long long xx = x;
while (y) {
if (y % 2) {
z *= xx;
}
y /= 2;
xx *= xx;
}
return z;
}
int main() {
printf("%llu\n", upow(3, 3));
printf("%llu\n", upow(13, 16));
}
Output
27
665416609183179841
If code needs to handle answers more the 64 bits, consider long double (with potential loss of precision) or big_integer libraries.
You have defined "ans" as long int then you are trying to print it as int (%d - Take the next argument and print it as an int ) So change printf("%d", ans) to printf("%ld",ans) . your code would look something like this :
#include <stdio.h>
#include <math.h>
int main()
{
int x, n;
long int ans;
scanf("%d \n %d",&x, &n);
ans = pow(x,n);
printf("%ld", ans);
return 0;
}

I've got an incorrect output for 13 factorial,how do i fix this?

My output
13!=1932053504
Expected output
13!=6227020800
I tried using int,long int but still the output remains the same
long int fact(long int num);
int main(){
long int n;
printf("Enter a number to find factorial: ");
scanf("%ld",&n);
printf("%ld!= %ld",n,fact(n));
}
long int fact(long int n){
if(n>=1)
return n*fact(n-1);
else
return 1;
}
Output:
13!=1932053504
The expected value exceeds 32 bits, what you get is the actual result trimmed to 32 bits:
1932053504 equals (6227020800 & 0xFFFFFFFF)
You'll have to verify capacity of int and long int in your environment, e.g. with print-ing their sizeof.
You should use long long int to make calculations on 64 bits. If you break that barrier also, you need to do more complicated stuff.
Note: use long twice, it is not a mistake - provided that the compiler supports 64-bit architectures.
If you are not interested in negative numbers, you can use unsigned long long int for some extra "comfort".

Printing a long in binary 64-bit representation

I'm trying to print the binary representation of a long in order to practice bit manipulation and setting various bits in the long for a project I am working on. I successfully can print the bits on ints but whenever I try to print 64 bits of a long the output is screwy.
Here is my code:
#include <stdio.h>
void printbits(unsigned long n){
unsigned long i;
i = 1<<(sizeof(n)*4-1);
while(i>0){
if(n&1)
printf("1");
else
printf("0");
i >>= 1;
}
int main(){
unsigned long n=10;
printbits(n);
printf("\n");
}
My output is 0000000000000000000000000000111111111111111111111111111111111110.
Thanks for help!
4 isn’t the right number of bits in a byte
Even though you’re assigning it to an unsigned long, 1 << … is an int, so you need 1UL
n&1 should be n&i
There’s a missing closing brace
Fixes only:
#include <limits.h>
#include <stdio.h>
void printbits(unsigned long n){
unsigned long i;
i = 1UL<<(sizeof(n)*CHAR_BIT-1);
while(i>0){
if(n&i)
printf("1");
else
printf("0");
i >>= 1;
}
}
int main(){
unsigned long n=10;
printbits(n);
printf("\n");
}
And if you want to print a 64-bit number specifically, I would hard-code 64 and use uint_least64_t.
The problem is that i = 1<<(sizeof(n)*4-1) is not correct for a number of reasons.
sizeof(n)*4 is 32, not 64. you probably want sizeof(n)*8
1<<63 may give you overflow because 1 may be 32-bits by default. You should use 1ULL<<(sizeof(n)*8-1)
unsigned long is not necessarily 64 bits. You should use unsigned long long
If you want to be extra thorough, use sizeof(n) * CHAR_BIT (defined in <limits.h>).
In general, you should use stdint defines (e.g. uint64_t) whenever possible.
The following should do what you want:
#include <stdio.h>
void printbits(unsigned long number, unsigned int num_bits_to_print)
{
if (number || num_bits_to_print > 0) {
printbits(number >> 1, num_bits_to_print - 1);
printf("%d", number & 1);
}
}
We keep calling the function recursively until either we've printed enough bits, or we've printed the whole number, whichever takes more bits.
wrapping this in another function directly does exactly what you want:
void printbits64(unsigned long number) {
printbits(number, 64);
}

Multiplication and Division unsigned integers

In my program , I have to perform arithmetic operations on unsigned integers.
The variable a has a range from 0 to 4294967295.
The variable b has a range from 0 to 32.
When I check the boundary condition by taking the maximun values for a and b,I am getting 0 as the answer since overflow occurs when I try to multiply a and MAX_NS.Ideally I should get 7 as the answer.How could I write the program such that overflow is taken care of and I get 7 as the answer and hopefully it works for other valid value range for a and b.Thanks.
#include "stdio.h"
#define MAX_NS 1000000000
int main()
{
unsigned int a = 4294967295;
unsigned int b = 32 ;
unsigned int c = ((b * MAX_NS)/a);
printf("%d",c);
}
**Edit:**Please note that I can't use unsigned long long.I can use only unsigned int for the variables.
Here is solution as Weather Vane suggested
#include "stdio.h"
#define MAX_NS 1000000000
int main()
{
unsigned long long a = 4294967295;
unsigned long long b = 32;
unsigned long long c = ((b * MAX_NS) / a);
printf("%llu", c);
}
The key is that the product b * MAX_NS must be computed using wide enough math.
Make certain at least one of the * operands is unsigned long long.
With large enough b and small enough a, the quotient will need a wider type to avoid overflow;
#include "stdio.h"
// #define MAX_NS 1000000000
#define MAX_NS 1000000000LLU
int main(void) {
unsigned int a = 4294967295; // type may remain unsigned
unsigned int b = 32 ; // type may remain unsigned
unsigned long long c = ((b * MAX_NS)/a);
printf("%llu",c);
}
Alternatively, coax the multiplication gently by multiplying by 1ull. In general avoid casting as in (unsigned long long) b * MAX_NS. Rampant practice of casting surprisingly sometimes narrows the math which could happen here at a later date with uintmax_t b.
#define MAX_NS 1000000000
int main(void) {
unsigned int a = 4294967295; // type may remain unsigned
unsigned int b = 32 ; // type may remain unsigned
unsigned long long c = ((1ull * b * MAX_NS)/a);
printf("%llu",c);
}

Resources