0

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.

Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
  • 3
    Ciphers don't encrypt "numbers" or "strings" or "pictures". They encode raw data. – Mat Nov 10 '12 at 12:22
  • Thinking I could create a custom floating point format, whereby I place the exponent in byte 0, then the mantissa in bytes 1,2,3 ... – user1814428 Nov 10 '12 at 14:08
  • That's a matter of encoding, not encryption. Encryption doesn't care about the interpretation of the bytes. – Mat Nov 10 '12 at 14:10

3 Answers3

0

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);
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    Your solution contravenes so-called “strict aliasing rules”. http://stackoverflow.com/questions/2958633/gcc-strict-aliasing-and-horror-stories – Pascal Cuoq Nov 10 '12 at 12:32
0

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;
LSerni
  • 55,617
  • 10
  • 65
  • 107
0

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);

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256