Now I am learning cryptograpgy. So, (for practice and for fun), I have decided to implement AES. I got stuck in one point (mixing columns here is my code):
typedef vector< vector<short> > vvector;
short mixBox[4][4] =
{
{0x02, 0x03, 0x01, 0x01},
{0x01, 0x02, 0x03, 0x01},
{0x01, 0x01, 0x02, 0x03},
{0x03, 0x01, 0x01, 0x02}
};
short gfMultiply(short h1, short h2)
{
//h1 can 0x01, 0x02 or 0x03
}
void mixColumns(vvector & v)
{
vvector res(v.begin(), v.end());
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
v[i][j] = 0x00;
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
for(int k=0; k<4; k++)
v[i][j] = v[i][j] ^ gfMultiply(mixBox[i][k], res[k][j]);
}
Theoretically, I understood multiplication gf(2^8), but for implementing algorithm, i have problems. I referred to this site. But either I can not understand some point or I am doing something wrong. In wikipedia I have read this:
"The multiplication operation is defined as: multiplication by 1 means
no change, multiplication by 2 means shifting to the left, and
multiplication by 3 means shifting to the left and then performing xor
with the initial unshifted value. After shifting, a conditional xor
with 0x1B should be performed if the shifted value is larger than
0xFF."
Assuming above I have implemented this:
short gfMultiply(short h1, short h2)
{
//h1 can 0x01, 0x02 or 0x03
short r;
if(h1==0x01)
return h2;
if(h1==0x02)
r = (h2<<1);
else
r = (h2<<1)^h2;
if(r>0xFF)
r = r^0x1b;
return r;
}
But results are incorrect, when I am testing. What I am doing wrong here?
Sorry, for bug. I have fixed it by myself, this is the correct one:
short gfMultiply(short h1, short h2)
{
//h1 can 0x01, 0x02 or 0x03
short r;
if(h1==0x01)
return h2;
if(h1==0x02)
{
r = (h2<<1);
if(r>0xFF)
r = r^0x11b;
}
else
{
r = (h2<<1);
if(r>0xFF)
r = r^0x11b;
r = r^h2;
}
return r;
}
Related
To represent this value, I am following the definition:
#define NUM_BITS 128
typedef unsigned char BigInt[NUM_BITS/8];
That is, a value of type BigInt must be represented by an array of bytes, interpreted as a single 128-bit integer, in two's complement and following the little-endian order.
For example, {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, which represents the integer value 1.
I've been thinking of doing a function like that:
void big_val (BigInt res, long val);
Which would be an attribution with extension. The big_val function assigns res the value provided by l (a signed long), correctly extended to 128 bits.
I was thinking of, for example, getting the most significant byte, getting the sign of the number, through y = val & 0xFF000000; and repeat this byte for another 8 times to form my array. But how could I get the bytes which represents the numbers without the signal?
That's what I've done so far:
void big_val(BigInt res, long val){
long y;
y = val&0xFF000000;
for(int i = 8; i < 16; i++){
res[i] = y;
}
}
(To anyone who has seen this post some minutes ago, I accidentally deleted it instead of editing, sorry)
Assign byte by byte, one byte at a time.
void BigInt_init_from_long(BigInt res, long val){
size_t i;
bool negative = val < 0;
for (i = 0; i < sizeof(long); ++i) {
res[i] = val & 0xff;
val >>= 8;
}
for (; i < NUM_BITS/8; ++i) {
res[i] = negative ? 0xff : 0; // sign extension
}
}
let's say I have an array:
uint16 my_uint16_Array[6] = {0x1A20, 0x1A35, 0X1AEC, 0x1AB8, 0x1A5D, 0x1AF3}
I want to convert this array to an byte array in order to have:
uint8 my_uint8_Array[12] = {0x1A, 0x20, 0x1A, 0x35, 0X1A, 0xEC, 0x1A, 0xB8, 0x1A, 0x5D, 0x1A, 0xF3}
What is the fastest way to do it in c?
Well memcpy will not sufficient for this task on little endian machine. In that case I would do this. Although I not guarantee this is the fastest way.
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t my_uint16_Array[6] = {0x1A20, 0x1A35, 0X1AEC, 0x1AB8, 0x1A5D, 0x1AF3};
uint8_t my_uint8_Array[12];
for (int i = 0; i < 6; i++)
{
my_uint8_Array[i << 1] = my_uint16_Array[i] >> 8;
my_uint8_Array[(i << 1) + 1] = my_uint16_Array[i] & 0xFF;
}
for (int i = 0; i < 12; i++)
printf("0x%x ", my_uint8_Array[i]);
return 0;
}
Output
0x1a 0x20 0x1a 0x35 0x1a 0xec 0x1a 0xb8 0x1a 0x5d 0x1a 0xf3
Another version which seem to produce less assembly instruction with MSP430 architecture with gcc 6.2.1 and -O3 flag. Also this is somewhat closer what x86 will actually do after optimization with the above code.
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t my_uint16_Array[6] = {0x1A20, 0x1A35, 0X1AEC, 0x1AB8, 0x1A5D, 0x1AF3};
uint8_t my_uint8_Array[12];
uint8_t *highBytePtr = (uint8_t*) my_uint16_Array;
uint8_t *lowBytePtr = (uint8_t*) my_uint16_Array;
highBytePtr++;
for (int i = 0; i < 12; i += 2, highBytePtr += 2, lowBytePtr += 2)
{
my_uint8_Array[i] = *highBytePtr;
my_uint8_Array[i + 1] = *lowBytePtr;
}
for (int i = 0; i < 12; i++)
printf("0x%x ", my_uint8_Array[i]);
return 0;
}
you can declare a uint8_t pointer and just "reinterpret" the data as a uint8_t array. But beware of endianness! the ordering may not in the way you expect it to be:
uint8_t *bytePointer = (uint8_t*) my_uint16_Array;
for(uint8_t i=0; i< sizeof(my_uint16_Array); i++) {
printf("%02X, ", bytePointer[i]);
}
On a little endian machine you get this output:
20, 1A, 35, 1A, EC, 1A, B8, 1A, 5D, 1A, F3, 1A
On a big endian machine, all value pairs are flipped:
1A, 20, 1A 35, 1A, EC, 1AB8, 1A, 5D, 1A, F3
I have my data field as follows DATA = 0x02 0x01 0x02 0x03 0x04 0x05 0x06 0x07 Now I want to concatenate this data as follows DATA = 0x01020304050607. How can I do it using C program. I found a program in C for concatenation of data in an array and the program is as follows:
#include<stdio.h>
int main(void)
{
int num[3]={1, 2, 3}, n1, n2, new_num;
n1 = num[0] * 100;
n2 = num[1] * 10;
new_num = n1 + n2 + num[2];
printf("%d \n", new_num);
return 0;
}
For the hexadecimal data in the array how can I manipulate the above program to concatenate the hexadecimal data?
You need a 64 bit variable num as result, instead of 10 as factor you need 16, and instead of 100 as factor, you need 256.
But if your data is provided as an array of bytes, then you can simply insert complete bytes, i.e. repeatedly shifting by 8 bits (meaning a factor of 256):
int main(void)
{
uint8_t data[8] = { 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
unsigned long long num = 0;
for (int i=0; i<8; i++) {
num <<=8; // shift by a complete byte, equal to num *= 256
num |= data[i]; // write the respective byte
}
printf("num is %016llx\n",num);
return 0;
}
Output:
num is 0201020304050607
Lest say you have input like
int DATA[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
If you want output like 0x0001020304050607, to store this resultant output you need one variable of unsigned long long type. For e.g
int main(void) {
int DATA[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
int ele = sizeof(DATA)/sizeof(DATA[0]);
unsigned long long mask = 0x00;
for(int row = 0; row < ele; row++) {
mask = mask << 8;/* every time left shifted by 8(0x01-> 0000 0001) times */
mask = DATA[row] | mask; /* put at correct location */
}
printf("%016llx\n",mask);
return 0;
}
Here's some kind of hack that writes your data directly into an integer, without any bitwise operators:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
uint64_t numberize(const uint8_t from[8]) {
uint64_t r = 0;
uint8_t *p = &r;
#if '01' == 0x4849 // big endian
memcpy(p, from, 8);
#else // little endian
for (int i=7; i >= 0; --i)
*p++ = from[i];
#endif
return r;
}
int main() {
const uint8_t data[8] = { 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
printf("result is %016llx\n", numberize(data));
return 0;
}
This does work and outputs this independently of the endianness of your machine:
result is 0201020304050607
The compile-time endianness test was taken from this SO answer.
void OPC_N2_data_read()
{
unsigned int32 iobyte[3][4] = {0x00, };
int32 PM_int[3] = {0x00, };
float PM[3] = {0x00, };
int8 i,j,k;
int8 mask = 0x80;
const int16 mask1 = 0x0001;
const int16 mask0 = 0x0000;
int8 trash_byte = 0x32;
output_bit(ss,1);
output_bit(PM_CLOCK_pin,0);
delay_us (1);
output_bit(ss,0);
delay_us (2);
for( i = 0 ; i < 3 ; i ++ )
{
for ( j = 0 ; j < 4 ; j ++ )
{
for (k = 0 ; k < 8 ; k ++ )
{
output_bit(PM_CLOCK_pin,1);
iobyte[i][j] = iobyte[i][j] << 1;
if ( input ( PM_MISO_pin))
{
iobyte[i][j] |= mask1;
}
else
{
iobyte[i][j] |= mask0;
}
if ((trash_byte & mask) >0)
{
output_high(PM_MOSI_pin);
}
else
{
output_bit(PM_MOSI_pin,0);
}
delay_us(1);
output_bit(PM_CLOCK_pin,0);
delay_us(5);
mask = mask >>1;
}
}
}
delay_us(3);
output_high(ss);
for(i = 0; i<3; i++)
{
PM_int[i] = ((iobyte[i][0]<<24)|(iobyte[i][1]<<16)|(iobyte[i][2]<<8)|(iobyte[i][3]));
PM[i] = *(float*)&PM_int;
}
printf ("%x%x%x%x\r\n",iobyte[0][0],iobyte[0][1],iobyte[0][2],iobyte[0][3]);
printf ("%x%x%x%x\r\n",iobyte[1][0],iobyte[1][1],iobyte[1][2],iobyte[1][3]);
printf ("%x%x%x%x\r\n",iobyte[2][0],iobyte[2][1],iobyte[2][2],iobyte[2][3]);
printf ("%lx,%lx,%lx\r\n", PM_int[0],PM_int[1],PM_int[2]);
printf ("%3.5f,%3.5f,%3.5f\r\n", PM[0],PM[1],PM[2]);
}
I receive data from a 4-byte array.
This data is a float value.
I check through the computer, I see the following.
e911bd41 d867e641 8084e941 e911bd41,d867e641,8084e941 0.00000,0.00000,0.00000
Making the four data into one INT value works fine. PM_int[0],PM_int[1],PM_int[2]
However, if you try to convert this to a float value, only 0.00000 is displayed.
I do not know where the problem is.
Looking on your source code shows that you are assuming that the received iobyte[i][0] to iobyte[i][3] shall be assumed as a float when ordering in big-endian format:
PM_int[i] = ((iobyte[i][0]<<24)|(iobyte[i][1]<<16)|(iobyte[i][2]<<8)|(iobyte[i][3]));
But if you want to convert correctly a 32bits floating-point value, you have to know if the source CPU and the destination CPU are both big-endian or little-endian. Otherwise, it is necessary to reverse the byte order before trying to convert values. So, if your target has a different endianness, replace the above code by the following:
PM_int[i] = ((iobyte[i][3]<<24)|(iobyte[i][2]<<16)|(iobyte[i][1]<<8)|(iobyte[i][0]));
In your source code, an error of the cast formatting between the float PM[i] and the 32bits integer PM_int[i] compute a bad result. The cast must be performed to the good element of the array PM_int[i].
PM[i] = *((float*)&(PM_int[i]));
Instead of:
PM[i] = *(float*)&PM_int;
With the 3 received float values {0xe9, 0x11, 0xbd, 0x41 }, {0xd8, 0x67, 0xe6, 0x41 }, {0x80, 0x84, 0xe9, 0x41 }, the output becomes:
e911bd41
d867e641
8084e941
41bd11e9,41e667d8,41e98480
23.63375,28.80070,29.18970
I have some unsigned char array. I want to represent a big number and add a number to this big number.
So for example I have these six elements:
0x00, 0x00, 0x00, 0x00, 0x00, 0xdf
I want to add 0x11 and get
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0
So, if I add 0x10 after, I should have
0x00, 0x00, 0x00, 0x01, 0x00
Could I do it with binary operations or something another but without loops? My array could be much larger than six elements.
You sum each pair of bytes from the source arrays and if the result is larger then 0xFF you carry 1 to the next byte. A loop is required.
//Adds B to A, Len is the amount of bytes that will be added.
//Make sure that Len <= size of A
void Add(unsigned char *A, unsigned char *B, int Len)
{
int Carry = 0;
//Work backwards because the high byte of your array holds the least significant byte.
for (int i = Len - 1; i >= 0; i--)
{
int Temp = (int) A[i] + B[i];
A[i] = (Temp + Carry) & 0xFF;
if ((Temp + Carry) > 0xFF)
Carry = 1;
else
Carry = 0;
}
}