Print a big integer stored as an unsigned long long array - c

I'm reviewing the security of an app for a University project, the app encrypts a file using RSA, specifically it uses this library: https://github.com/ilansmith/rsa (DO NOT use this, it has serious vulnerabilities).
(If you want to take a look, most of the operations between these numbers are implemented in the rsa_num.c file.)
This tool uses arrays of unsigned long long to store the big numbers needed for RSA (n, e and d):
typedef struct {
u64 arr[17]; //u64 is defined as unsigned long long
int top; //points to the last occupied slot of the array
} u1024_t;
The problem is that I don't understand how the numbers are stored in this format.
What I need is being able to print the real numbers in some way, or at least a way to recover the numbers from the components of the arrays.
I tried just concatenating them like strings, but it doesn't seem right.
Thanks to whoever will be able to help!

Thank you #Matthieu! Your comment worked.
I needed to concatenate the unsigned long longs in reverse order and reversing their bytes due to endianness.
Following his solution, I implemented this function, which works perfectly:
void print_u1024(u1024_t number) {
int size = (number.top + 1) * sizeof(u64);
for (int i = size-1; i >= 0; i--) {
printf("%02x", ((unsigned char*)number.arr)[i]);
}
printf("\n");
}
Please note that this solution will probably only work on little-endian systems (most PCs).

Related

C - Is there a way to leave a variable unchanged outside of the loop?

I've tried searching for the answer to this question, which is a little tricky when you don't know exactly what you're searching for, but here goes.
I'm making my way through CS50 at the moment (very new at this - I know a bit of HTML/CSS and my day job is in marketing). I'm on the final problem of week 1 - I'm making it tricky for myself by doing the harder problems as well as the easy ones, but I'm keen to learn. So far we haven't talked about arrays, which I suspect might be the answer to this question, but without more knowledge I can't be sure.
I'm working on a credit card validator, where I have to do things like get the length of the card number to validate, add different digits etc. Where I'm struggling, is that if I alter a variable inside a loop in some way, when I go to use that variable again, it has the new value in it - not the original one.
How do I store the original value somewhere so it can be accessed without me having to create dozens of new variables to act as placeholders? (Note - the below is just a tiny snippet of my code as an example - I didn't want to include the whole thing)
e.g.
long long credit; // credit card number
long long len; // used to work out len of card number - feeds into count
// validate length of credit card number and get length of card
len = credit;
while (len > 0)
{
len /= 10;
count ++;
}
In the above example, if I want to use len again further down in my code, it's value will be 0. How do I ensure the original value stays somewhere for me to access in future loops?
I suspect I need to somehow use an array, but so far we've only covered off data types, Booleans, operators, conditional statements and loops (plus printf). All of the info I've found online about arrays talks about needing to specify the array size (the point is I don't know in this example - the values can vary between 13 and 16 digits) and seem more complex than this problem calls for.
I'm pretty sure I'm missing something really simple - I just don't know what it is!
EDIT: Thanks everyone who contributed answers to my very first question! While there may be "better" solutions, it seems that given the constraints I have with my solution specification that I was doing ok and was just overthinking it really. I took the advice from people to copy variables and finally got everything working a few minutes ago.
If anybody would like to see it (although I'm sure my code could do with improvements), my solution is here.
The original specification that I had to meet, was here.
Once again, really appreciated the feedback - I appreciate that this isn't a tutorial site - but sometimes it can be hard to work out what you don't know. Thanks for the help!
You may be looking for the declaration of additional blocks as in
#include<stdio.h>
int main() {
int i=1;
printf("before %d\n",i);
{
int i=0;
printf("within %d\n",i);
}
printf("after %d\n",i);
return(0);
}
which when executed yields
before 1
within 0
after 1
From the comment I grasp that a function invocation may be preferable which may be like
#include<stdio.h>
int div_10_count(long long val) {
int count=0;
while(val>0) {
val /= 10;
count++;
}
return(count);
}
int main() {
long long val=10000000000L;
printf("Before: val=%lld\n",val);
printf("Returned: %d\n",div_10_count(val));
printf("After: val=%lld\n",val);
return(0);
}
shows
Before: val=10000000000
Returned: 11
After: val=10000000000
so the variable val remains unchanged even though the function works with it. This would be different when passing the parameter by reference, i.e. as indicated with the "&".
Whats wrong with using a temporary variable?
You can just make two variables
long long len;
long long lenWork;
len = yourValue;
lenWork = len;
/* Work with lenWork */
lenWork = len;
/* Once again */
lenWork = len;
/* etc... */
You might have forgotten to initialize the count variable to 0.
Use more explicit variable names:
unsigned long long credit; // credit card number
// get length of the credit card number
int count = 0;
for (unsigned long long tmp = credit; tmp > 0; tmp /= 10) {
count++;
}
Here is a more direct method:
if (snprintf(NULL, 0, "%llu", credit) == 16) {
/* credit card number has 16 digits */
}
You could also use a much simpler but less readable method:
if (credit >= 1000000000000000 && credit < 10000000000000000) {
/* credit has 16 digits */
}

Hash table with singly linked list implementation C [duplicate]

I have a long list of English words and I would like to hash them. What would be a good hashing function? So far my hashing function sums the ASCII values of the letters then modulo the table size. I'm looking for something efficient and simple.
To simply sum the letters is not a good strategy because a permutation gives the same result.
This one (djb2) is quite popular and works nicely with ASCII strings.
unsigned long hashstring(unsigned char *str)
{
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
More info here.
If you need more alternatives and some perfomance measures, read here.
Added: These are general hashing functions, where the input domain is not known in advance (except perhaps some very general assumptions: eg the above works slightly better with ascii input), which is the most usual scenario. If you have a known restricted domain (set of inputs fixed) you can do better, see Fionn's answer.
Maybe something like this would help you: http://www.gnu.org/s/gperf/
It generates a optimized hashing function for the input domain.
If you don't need it be cryptographically secure, I would suggest the Murmur Hash. It's extremely fast and has high diffusion. Easy to use.
http://en.wikipedia.org/wiki/MurmurHash
http://code.google.com/p/smhasher/wiki/MurmurHash3
If you do need a cryptographically secure hash, then I suggest SHA1 via OpenSSL.
http://www.openssl.org/docs/crypto/sha.html
A bit late, but here is a hashing function with an extremely low collision rate for 64-bit version below, and ~almost~ as good for the 32-bit version:
uint64_t slash_hash(const char *s)
//uint32_t slash_hash(const char *s)
{
union { uint64_t h; uint8_t u[8]; } uu;
int i=0; uu.h=strlen(s);
while (*s) { uu.u[i%8] += *s + i + (*s >> ((uu.h/(i+1)) % 5)); s++; i++; }
return uu.h; //64-bit
//return (uu.h+(uu.h>>32)); //32-bit
}
The hash-numbers are also very evenly spread across the possible range, with no clumping that I could detect - this was checked using the random strings only.
[edit]Also tested against words extracted from local text-files combined with LibreOffice dictionary/thesaurus words (English and French - more than 97000 words and constructs) with 0 collisions in 64-bit and 1 collision in 32-bit :)
(Also compared with FNV1A_Hash_Yorikke, djb2 and MurmurHash2 on same sets: Yorikke & djb2 did not do well; slash_hash did slightly better than MurmurHash2 in all the tests)

Compare two strings and if they are equal backwards

Lets say we got two inputs. One being 123 and one being 321. Now, these two should return True.
Another eg. 543 with 345.
This is how far I've gotten:
int a,i=0;
printf("condition value");
scanf("%d",&i);
printf("comparison value");
scanf("%d",&a);
a=a%10;
i=a/10;
if(a==i){
printf("\nTrue");
}
Has anyone got any ideas on how to solve this?
If you want to know whether one string matches the reverse of another string, just compare character-by-character. Even if it's guaranteed that all the characters are digits, it's easier to solve the problem in the string domain.
Even if there's some number-theory trickery that would give you a closed-form solution for fixed-size integers, parsing strings into int in the first place will be slower than just a character-compare loop.
Often you can make your code simpler by taking advantage of limitations on the input, but it looks like this isn't one of those cases.
Given OP wants to check integers based on this comment
Simply reverse the digits of one of the numbers
Remove the least-significant digit from x, one at a time. Use that value to build up the reverse of x. Note that the range of the "reverse of x" is wider than the range of unsigned.
Use unsigned to avoid sign issues.
unsigned long long unsigned_rev(unsigned x) {
unsigned long long rev = 0;
while (x) {
rev = rev*10 + x%10;
x /= 10;
}
return rev;
}

MQTT callback handling

I am trying to convert a byte* parameter passed into an mqtt callback function to an int for comparison and I can't seem to get it working. Any help would be welcomed.
int fsrReading;
void callback(char* topic, byte* payload, unsigned int length) {
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]); // This works well
fsrReading = int((char)payload[i]);
if (fsrReading < 0){
...
The correct way to do this depends on exactly what representation of a number is being used.
I suspect the message is a string representation of a number: "1234", which is being received as an array of ascii byte values.
If that is the case, you can rebuild a String object and convert it to an int:
int fsrReading;
void callback(char* topic, byte* payload, unsigned int length) {
String value = "";
for (int i=0;i<length;i++) {
value += (char)payload[i];
}
fsrReading = value.toInt();
...
There is an example of converting a String to an Int in the arduino tutorials here: https://www.arduino.cc/en/Tutorial/StringToIntExample
EDIT: original answer part before explanation:
Depends on compiler, compiler options etc char can be signed or unsigned, cast via (char) can work different than You expect.
Example:
payload[i] is 0x81
unsigned char -> 129, then >0
signed char -> -127, then <0
Your cast via (char) is redundant (and unstable like i said)
I don't give sample code because I don't understand Your goal. Code has contradictions.
Disclaimer: Your byte seems non standard type. I belive that is unsigned char a such type NEVER is <0 .
What is main sense of this variable? In deep, it is signed or unsigned? You can cast (unigned char) but is never<0 or (signed char) - up to You
EDIT:
after comment of asker, and interpretation from knolleary hot to interpret length (important: change of loop sense, maybe you understand author correctly) I give pure C conversion
int val = 0;
for (int i=0; i<length; i++) {
val = val*10 + payload[i]-'0';
}
// If someone know end of number is marked in different way, need implement break of `for`
fsrReading =val;
I believe my is few CPU cycles/RAM better.
EDIT2: I have read few materials from Arduino community, problem with loop concatenation into String is like in many languages: many, many small allocations (while concatenation is totally not required here). Many good Arduino programmers are critical to overuse of String. It isn't "secret knowledge", it is general rule in programming.
http://forum.arduino.cc/index.php?topic=185469.0
http://www.gammon.com.au/concat

converting data types in c

Let me start by saying that I openly admit this is for a homework assignment, but what I am asking is not related to the purpose of the assignment, just something I don't understand in C. This is just a very small part of a large program.
So my issue is, I have a set of data that consists various data types as follows:
[16 bit number][16 but number][16 bit number][char[234]][128 bit number]
where each block represents a variable from elsewhere in the program.
I need to send that data 8bytes at a time into a function that accepts uint32_t[2] as an input. How do I convert my 234byte char array into uint32_t without losing the char values?
In other words, I need to be able to convert back from the uint32_t version to the original char array later on. I know a char is 1byte, and the value can also be represented as a number in relation to its ascii value, but not sure how to convert between the two since some letters have a 3 digit ascii value and others have 2.
I tried to use sprintf to grab 8byte blocks from the data set, and store that value in a uint32_t[2] variable. It works, but then I lose the original char array because I can't figure out way to go back/undo it.
I know there has to be a relatively simple way to do this, i'm just lacking enough skill in C to make it happen.
Your question is very confusing, but I am guessing you are preparing some data structure for encryption by a function that requires 8 bytes or 2 uint32_t's.
You can convert a char array to uint32_t as follows
#define NELEM 234
char a[NELEM];
uint64_t b[(NELEM+sizeof(uint64_t)-1)/sizeof(uint64_t)]; // this rounds up to nearest modulo 4
memcpy(b,a,NELEM);
for(i .. ) {
encryption_thing(b[i]);
}
or
If you need to change endianess or something, that is more complicated.
#include <stdint.h>
void f(uint32_t a[2]) {}
int main() {
char data[234]; /* GCC can explicitly align with this: __attribute__ ((aligned (8))) */
int i = 0;
int stride = 8;
for (; i < 234 - stride; i += stride) {
f((uint32_t*)&data[i]); }
return 0; }
I need to send that data 8bytes at a time into a function that accepts
uint32_t[2] as an input. How do I convert my 234byte char array into
uint32_t without losing the char values?
you could use a union for this
typedef union
{
unsigned char arr[128]; // use unsigned char
uint32_t uints[16]; // 128/8
} myvaluetype;
myvaluetype value;
memcpy(value.arr, your_array, sizeof(value.arr));
say the prototype that you want to feed 2 uint32_t at a time is something like
foo(uint32_t* p);
you can now send the data 8 bytes at the time by
for (int i = 0; i < 16; i += 2)
{
foo(myvaluetype.uints + i);
}
then use the same struct to convert back.
of course some care must be taken about padding/alignment you also don't mention if it is sent over a network etc so there are other factors to consider.

Resources