Blowfish floating point - c

I have some floating point data e.g. "3.9389005e-01" which I want to cipher with Blowfish.
strtod is used to get a float from the string.
But Blowfish only encrypts integers.
So my plan is to encrypt each FP value as two integers, a mantisaa and an exponent. Then store as two separate encrypted values.
Decryption will return the mantissa and exponent enabling re-constitution of the original FP number.
is there a neater solution ?
Some demo code for blowfish is here.

You can access any pointer as any other pointer. The data may not be meaningful as another data-type, but it's possible:
double value = 123.456;
int *ptr = (int *) &value;
Now you have a pointer to a memory area of sizeof(double) bytes (or sizeof(double) / sizeof(int) integers) that can be encrypted.
To get back the double after decryption, you can do e.g.:
double new_value = *((double *) ptr);

Declare an union between the double you need to encrypt, and a uint8_t array of the same size.
To encrypt, fill in the double, encrypt the bytes. To decrypt, decrypt the bytes and read off the double.
This approach can be extended to any non-byte data type, provided the cypher you use outputs same-size messages.
In case of padding, the faster approach of "get a uint8_t * to whatever your data iswill sometimes work, sometimes not; AES-256 will work with adoubleof size 8, but block implementations are liable to crash or corrupt data when working with afloatof size 4 (they will attempt to read 8 bytes, and write 8 bytes; where only four are actually available). Due to platform and compiler quirks, this may *still* work because after thefloat` there might be some "memory padding" available.
To be safe, if for example the cypher is padded to 256 bits (32 bytes), you will have to fix the length of the byte array to be likewise padded. One not-so-clean way of doing this is to increase byte count by a whole padding count:
#include <stdio.h>
typedef struct {
double a;
long v;
// Whatever else.
// ...
} payload_t;
union {
payload_t payload;
unsigned char bytes[sizeof(payload_t)+32]; // 256 bits of margin
} data;
int main(void)
{
data.payload.a = 3.14159;
data.payload.v = 123456789;
...
// Encrypt data.bytes, for a length integer multiple of 32 bytes
size_t length = ((sizeof(payload_t)+31)/32)*32;

Should code want to convert the FP value to a string, then encrypt the string and later want to get the exact FP value back, then the FP number needs to be converted with sufficient precision. Use "%.*e" and DBL_DECIMAL_DIG (or DBL_DIG + 3 if unavailable).
#include <float.h>
// sign digit . fraction e sign expo \0 CYA
#define FP_BUF_SIZE (1+1+1+ (DBL_DECIMAL_DIG-1) + 1 + 1 + 4 + 1 + 10)
double x;
char buf[FP_BUF_SIZE];
sprintf(buf, "%.*e", DBL_DECIMAL_DIG - 1, x);
Encode(buf);
Ref Printf width specifier to maintain precision of floating-point value
Alternatively, code could use sprintf(buf, "%a", x);

Related

How to convert to integer a char[4] of "hexadecimal" numbers [C/Linux]

So I'm working with system calls in Linux. I'm using "lseek" to navigate through the file and "read" to read. I'm also using Midnight Commander to see the file in hexadecimal. The next 4 bytes I have to read are in little-endian , and look like this : "2A 00 00 00". But of course, the bytes can be something like "2A 5F B3 00". I have to convert those bytes to an integer. How do I approach this? My initial thought was to read them into a vector of 4 chars, and then to build my integer from there, but I don't know how. Any ideas?
Let me give you an example of what I've tried. I have the following bytes in file "44 00". I have to convert that into the value 68 (4 + 4*16):
char value[2];
read(fd, value, 2);
int i = (value[0] << 8) | value[1];
The variable i is 17480 insead of 68.
UPDATE: Nvm. I solved it. I mixed the indexes when I shift. It shoud've been value[1] << 8 ... | value[0]
General considerations
There seem to be several pieces to the question -- at least how to read the data, what data type to use to hold the intermediate result, and how to perform the conversion. If indeed you are assuming that the on-file representation consists of the bytes of a 32-bit integer in little-endian order, with all bits significant, then I probably would not use a char[] as the intermediate, but rather a uint32_t or an int32_t. If you know or assume that the endianness of the data is the same as the machine's native endianness, then you don't need any other.
Determining native endianness
If you need to compute the host machine's native endianness, then this will do it:
static const uint32_t test = 1;
_Bool host_is_little_endian = *(char *)&test;
It is worthwhile doing that, because it may well be the case that you don't need to do any conversion at all.
Reading the data
I would read the data into a uint32_t (or possibly an int32_t), not into a char array. Possibly I would read it into an array of uint8_t.
uint32_t data;
int num_read = fread(&data, 4, 1, my_file);
if (num_read != 1) { /* ... handle error ... */ }
Converting the data
It is worthwhile knowing whether the on-file representation matches the host's endianness, because if it does, you don't need to do any transformation (that is, you're done at this point in that case). If you do need to swap endianness, however, then you can use ntohl() or htonl():
if (!host_is_little_endian) {
data = ntohl(data);
}
(This assumes that little- and big-endian are the only host byte orders you need to be concerned with. Historically, there have been others, which is why the byte-reorder functions come in pairs, but you are extremely unlikely ever to see one of the others.)
Signed integers
If you need a signed instead of unsigned integer, then you can do the same, but use a union:
union {
uint32_t unsigned;
int32_t signed;
} data;
In all of the preceding, use data.unsigned in place of plain data, and at the end, read out the signed result from data.signed.
Suppose you point into your buffer:
unsigned char *p = &buf[20];
and you want to see the next 4 bytes as an integer and assign them to your integer, then you can cast it:
int i;
i = *(int *)p;
You just said that p is now a pointer to an int, you de-referenced that pointer and assigned it to i.
However, this depends on the endianness of your platform. If your platform has a different endianness, you may first have to reverse-copy the bytes to a small buffer and then use this technique. For example:
unsigned char ibuf[4];
for (i=3; i>=0; i--) ibuf[i]= *p++;
i = *(int *)ibuf;
EDIT
The suggestions and comments of Andrew Henle and Bodo could give:
unsigned char *p = &buf[20];
int i, j;
unsigned char *pi= &(unsigned char)i;
for (j=3; j>=0; j--) *pi++= *p++;
// and the other endian:
int i, j;
unsigned char *pi= (&(unsigned char)i)+3;
for (j=3; j>=0; j--) *pi--= *p++;

8 Byte Number as Hex in C

I have given a number, for example n = 10, and I want to calculate its length in hex with big endian and save it in a 8 byte char pointer. In this example I would like to get the following string:
"\x00\x00\x00\x00\x00\x00\x00\x50".
How do I do that automatically in C with for example sprintf?
I am not even able to get "\x50" in a char pointer:
char tmp[1];
sprintf(tmp, "\x%x", 50); // version 1
sprintf(tmp, "\\x%x", 50); // version 2
Version 1 and 2 don't work.
I have given a number, for example n = 10, and I want to calculate its length in hex
Repeatedly divide by 16 to find the number of hexadecimal digits. A do ... while insures the result is 1 when n==0.
int hex_length = 0;
do {
hex_length++;
} while (number /= 16);
save it in a 8 byte char pointer.
C cannot force your system to use 8-byte pointer. So if you system uses 4 byte char pointer, we are out of luck. Let us assume OP's system uses 8-byte pointer. Yet integers may be assigned to pointers. This may or may not result in valid pointer.
assert(sizeof (char*) == 8);
char *char_pointer = n;
printf("%p\n", (void *) char_pointer);
In this example I would like to get the following string: "\x00\x00\x00\x00\x00\x00\x00\x50".
In C, a string includes the various characters up to an including a null character. "\x00\x00\x00\x00\x00\x00\x00\x50" is not a valid C string, yet is a valid string literal. Code cannot construct string literals at run time, that is a part of source code. Further the relationship between n==10 and "\x00...\x00\x50" is unclear. Instead perhaps the goal is to store n into a 8-byte array (big endian).
char buf[8];
for (int i=8; i>=0; i--) {
buf[i] = (char) n;
n /= 256;
}
OP's code certainly will fail as it attempts to store a string which is too small. Further "\x%x" is not valid code as \x begins an invalid escape sequence.
char tmp[1];
sprintf(tmp, "\x%x", 50); // version 1
Just do:
int i;
...
int length = round(ceil(log(i) / log(16)));
This will give you (in length) the number of hexadecimal digits needed to represent i (without 0x of course).
log(i) / log(base) is the log-base of i. The log16 of i gives you the exponent.
To make clear what we're doing here: When rising 16 to the power of the found exponent, we get back i: 16^log16(i) = i.
By rounding up this exponent using ceil(), you get the number of digits.

how can split integers into bytes without using arithmetic in c?

I am implementing four basic arithmetic functions(add, sub, division, multiplication) in C.
the basic structure of these functions I imagined is
the program gets two operands by user using scanf,
and the program split these values into bytes and compute!
I've completed addition and subtraction,
but I forgot that I shouldn't use arithmetic functions,
so when splitting integer into single bytes,
I wrote codes like
while(quotient!=0){
bin[i]=quotient%2;
quotient=quotient/2;
i++;
}
but since there is arithmetic functions that i shouldn't use..
so i have to rewrite that splitting parts,
but i really have no idea how can i split integer into single byte without using
% or /.
To access the bytes of a variable type punning can be used.
According to the Standard C (C99 and C11), only unsigned char brings certainty to perform this operation in a safe way.
This could be done in the following way:
typedef unsigned int myint_t;
myint_t x = 1234;
union {
myint_t val;
unsigned char byte[sizeof(myint_t)];
} u;
Now, you can of course access to the bytes of x in this way:
u.val = x;
for (int j = 0; j < sizeof(myint_t); j++)
printf("%d ",u.byte[j]);
However, as WhozCrag has pointed out, there are issues with endianness.
It cannot be assumed that the bytes are in determined order.
So, before doing any computation with bytes, your program needs to check how the endianness works.
#include <limits.h> /* To use UCHAR_MAX */
unsigned long int ByteFactor = 1u + UCHAR_MAX; /* 256 almost everywhere */
u.val = 0;
for (int j = sizeof(myint_t) - 1; j >= 0 ; j--)
u.val = u.val * ByteFactor + j;
Now, when you print the values of u.byte[], you will see the order in that bytes are arranged for the type myint_t.
The less significant byte will have value 0.
I assume 32 bit integers (if not the case then just change the sizes) there are more approaches:
BYTE pointer
#include<stdio.h>
int x; // your integer or whatever else data type
BYTE *p=(BYTE*)&x;
x=0x11223344;
printf("%x\n",p[0]);
printf("%x\n",p[1]);
printf("%x\n",p[2]);
printf("%x\n",p[3]);
just get the address of your data as BYTE pointer
and access the bytes directly via 1D array
union
#include<stdio.h>
union
{
int x; // your integer or whatever else data type
BYTE p[4];
} a;
a.x=0x11223344;
printf("%x\n",a.p[0]);
printf("%x\n",a.p[1]);
printf("%x\n",a.p[2]);
printf("%x\n",a.p[3]);
and access the bytes directly via 1D array
[notes]
if you do not have BYTE defined then change it for unsigned char
with ALU you can use not only %,/ but also >>,& which is way faster but still use arithmetics
now depending on the platform endianness the output can be 11,22,33,44 of 44,33,22,11 so you need to take that in mind (especially for code used in multiple platforms)
you need to handle sign of number, for unsigned integers there is no problem
but for signed the C uses 2'os complement so it is better to separate the sign before spliting like:
int s;
if (x<0) { s=-1; x=-x; } else s=+1;
// now split ...
[edit2] logical/bit operations
x<<n,x>>n - is bit shift left and right of x by n bits
x&y - is bitwise logical and (perform logical AND on each bit separately)
so when you have for example 32 bit unsigned int (called DWORD) yu can split it to BYTES like this:
DWORD x; // input 32 bit unsigned int
BYTE a0,a1,a2,a3; // output BYTES a0 is the least significant a3 is the most significant
x=0x11223344;
a0=DWORD((x )&255); // should be 0x44
a1=DWORD((x>> 8)&255); // should be 0x33
a2=DWORD((x>>16)&255); // should be 0x22
a3=DWORD((x>>24)&255); // should be 0x11
this approach is not affected by endianness
but it uses ALU
the point is shift the bits you want to position of 0..7 bit and mask out the rest
the &255 and DWORD() overtyping is not needed on all compilers but some do weird stuff without them especially on signed variables like char or int
x>>n is the same as x/(pow(2,n))=x/(1<<n)
x&((1<<n)-1) is the same as x%(pow(2,n))=x%(1<<n)
so (x>>8)=x/256 and (x&255)=x%256

Concat 4 integers into one integer

Hi i am trying to concatinate 4 integers one integer. I used the concatinate function found here :
https://stackoverflow.com/a/12700533/2016977
My code:
unsigned concatenate(unsigned x, unsigned y) {
unsigned pow = 10;
while(y >= pow)
pow *= 10;
return x * pow + y;
}
void stringtoint(){
struct router *ptr;
ptr=start;
while(ptr!=NULL){
int a;
int b;
int c;
int d;
sscanf(ptr->ip, "%d.%d.%d.%d", &a, &b, &c, &d);
int num1 = concatenate(a,b);
int num2 = concatenate(c,d);
int num3 = concatenate(num1,num2);
printf("%d\n",num3);
ptr=ptr->next;
};
}
The problem:
I am dealing with IP address numbers e.g. 198.32.141.140 i am breaking them down to 4 integers and concatenate them to form 19832141140, however my concatenate function is doing maths on the larger number like 198.32.141.140 (becomes) - >-1642695340
but it is concatenating the IP which are small numbers e.g. 164.78.104.1 becomes 164781041 (which is correct)
How should i solve the problem, basically i am trying to make a string of IP e.g. 198.32.141.140 into an integer number 19832141140
Your proposed approach is likely a very big mistake. How do you distinguish 127.0.1.1 from 127.0.0.11?
It's much better to treat IP addresses as exactly what they are. Namely, a.b.c.d represents
a * 256^3 + b * 256^2 + c * 256^1 + d * 256^0
and done in this way you can not possibly run into the issue I just described. Moreover, the implementation is trivial:
unsigned int number;
number = (a << 24) + (b << 16) + (c << 8) + d
You may read a line, and then use inet_aton(). Otherwise, you can do as Jason says, but you'd need to check each integers value to be within 0 ... 255 (those 4 x 8 bits represent the 32bit integer containing an IPv4 address). inet_aton() would support hex, dec and octal notation of IPv4 addresses.
/**
** You DO NOT want to do this usually...
**/
#include <stdint.h>
uint_fast64_t
concatIPv4Addr(uint_fast16_t parts[])
{
uint_fast64_t n = 0;
for (int i = 0; i < 3; ++i) {
n += parts[i];
n *= 1000;
}
return (n += parts[3]);
}
I used the "fast" integer types for speed purposes, but if you have a storage requirement, use the corresponding "least" types instead. Of course this assumes you have a C99 compiler or a C89 compiler with extensions. Otherwise you're stuck with the primitive types where a char could even be 32-bit according to the C standard. Since I don't know your target environment, I made no assumptions. Feel free to change to the appropriate primitive types as you see fit.
I used a 16-bit value (minimum) because an 8-bit number can only represent 0-255, meaning if 358 was entered accidentally, it would be interpreted as 102, which is still valid. If you have a type able to store more than 8 bits and less than 16 bits, you can obviously use that, but the type must be able to store more than 8 bits.
That aside, you will need at least a 38-bit type:
4294967295 (32-bit unsigned max)
255255255255 (255.255.255.255 converted to the integer you want)
274877906944 (38-bit unsigned max)
The function above will convert 127.0.1.1 and 127.0.0.11 to 127000001001 and 127000000011 respectively:
127.0.1.1 ->
127.000.001.001 ->
127000001001
127.0.0.11 ->
127.000.000.011 ->
127000000011
Why so many zeros? Because otherwise you can't tell the difference between them! As others have said, you could confuse 127.0.1.1 and 127.0.0.11. Using the function above or something more appropriate that actually converts an IPv4 address to its real decimal representation, you won't have such a problem.
Lastly, I did no validation on the IPv4 address passed to the function. I assume you already ensure the address is valid before calling any functions that save or use the IPv4 address. BTW, if you wanted to do this same thing for IPv6, you can't so easily because that would require a string or conversion to decimal of each of the 8 parts, each of which is at most 16-bit, yielding 5 decimal digits per part, or 40 digits. To store that, you'd need a minimum of 133 bits, rather than the 128 bits required for the IPv6 address, just as you'd need 38 bits to store an IPv4 address instead of the 32 bits required.
Still not too bad, right? How about a theoretical IPv8 where there are 16 parts, each of which are 32-bit in size? The equivalent function to the one above would require 580 bits, instead of the proper mathematical requirement: 512 bits. While not a problem today, I'm simply pointing out the error in doing anything with an IPv4 address represented by concatenating the decimal values of each part. It scales absolutely terribly.

What is the minimum buffer size for sprintf with %g?

The problem is to statically allocate a buffer large enough to fit a printed double, formatted with %g at maximum precision. This seems like a simple enough task, bu I'm having trouble. The best I have come up with (assuming the number to be printed is x) is
char buf[1 + DBL_DIG + DBL_DIG + 1 + 1 + 1 + DBL_DIG + 1];
int len = sprintf(buf, "%.*g", DBL_DIG, x);
The DBL_DIG macro is from float.h, and apparently it is supposed to indicate the maximum precision for the type double. We need:
1 byte for a negative sign
enough bytes to capture the significant digits
at most one 'separator' char (comma, etc.) per digit
1 byte for a decimal point
1 byte for 'e'
1 byte for the sign on the exponent
some bytes for the exponent
1 byte for the trailing null written by sprintf.
I'm using the number of significant digits as an upper bound on the number of digits in the exponent. Have I made any errors? Is there a better solution? Should I just allocate 64, 128, or 256 bytes and hope for the best?
You cannot pre-calculate the size at compile time. The %g formatter takes the locale into account (for the 1000's separator etc.)
See http://linux.die.net/man/3/sprintf for a description on how to calculate the size safely.
Use snprintf() to find out how many characters you need:
#include <float.h> /* DBL_DIG */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
double x = rand() / (double)RAND_MAX;
char find_len[1];
int need_len;
char *buf;
need_len = snprintf(find_len, 1, "%.*g", DBL_DIG, x);
buf = malloc(need_len + 1);
if (buf) {
int used = sprintf(buf, "%.*g", DBL_DIG, x);
printf("need: %d; buf:[%s]; used:%d\n", need_len, buf, used);
free(buf);
}
return 0;
}
You need a C99 compiler for snprintf().
snprintf() was defined by the C99 standard. A C89 implementation is not required to have snprintf() defined, and if it has as an extension, it is not required to "work" as described by the C99 Standard.
Instead of using sprintf, you could use asprintf. This allocates a buffer of the correct size to fit your string.
Two things: %g does not show all of the representable digits, %g shows a nice-for-humans rounded result. You can specify the precision using %f or %e if you would like a different result.
Never use sprintf() rather than using snprintf(). In your case:
int len = snprintf(buf, dimensionof(buf), "%.*f", DBL_DIG, x);
Should I just round up to 64, 128, or
256 and hope for the best?
Yes, just do that -.-

Resources