C bit manipulation DES permute - c

I was having trouble with implementing the DES algorithm in Python, so I thought I'd switch to C. But I've ran into an issue, which I haven't been able to fix in hours, hopefully you can help me. Here's the source:
int PI[64] = {58,50,42,34,26,18,10,2,
60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,
64,56,48,40,32,24,16,8,
57,49,41,33,25,17,9,1,
59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,
63,55,47,39,31,23,15,7};
unsigned long getBit(unsigned long mot, unsigned long position)
{
unsigned long temp = mot >> position;
return temp & 0x1;
}
void setBit(unsigned long* mot, int position, unsigned long value)
{
unsigned long code = *mot;
code ^= (-value ^ code) & (1 << position);
*mot = code;
}
void permute( unsigned long * mot, int * ordre, int taille )
{
unsigned long res;
int i = 0;
unsigned long bit;
for (i = 0; i < taille; i++)
{ setBit(&res, i, getBit(*mot, ordre[i] - 1)); }
*mot = res;
}
int main(int argc, char *argv[])
{
unsigned long bloc = 0x0123456789ABCDEF;
permute(&bloc, PI, 64);
printf(" end %lx\n", bloc);
return 1;
}
I made this permutation manually and with my Python program, and the result of this permutation should be 0xcc00ccfff0aaf0aa but I get 0xffffffffcc00ccff (which is, somehow, half correct and half broken). What is going on? How to fix this?

I added UL at the end of my hex word, and I used uint64_t instead of unsigned long int. When I changed -value, I got either fffffffffffffff or 0, but with UL and uint64_t I'm getting the correct result, which probably means, as you guys suggested, that my unsigned longs were not 64-bit longs. Thanks !

Related

Converting a string of chars into its decimal value then back to its character valus

unsigned long long int power(int base, unsigned int exponent)
{
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
I am working on a program where I need to take in a string of 8 characters (e.g. "I want t") then convert this into a long long int in the pack function. I have the pack function working fine.
unsigned long long int pack(char unpack[])
{
/*converting string to long long int here
didn't post code because its large*/
}
After I enter "I want t" I get "Value in Decimal = 5269342824372117620" and then I send the decimal to the unpack function. So I need to convert 5269342824372117620 back into "I want t". I tried bit manipulation which was unsuccessful any help would be greatly appreciated.
void unpack(long long int pack)
{
long long int bin;
char convert[100];
for(int i = 63, j = 0, k = 0; i >= 0; i--,j++)
{
if((pack & (1 << i)) != 0)
bin += power(2,j);
if(j % 8 == 0)
{
convert[k] = (char)bin;
bin = 0;
k++;
j = -1;
}
}
printf("String: %s\n", convert);
}
A simple solution for your problem is to consider the characters in the string to be digits in a large base that encompasses all possible values. For example base64 encoding can convert strings of 8 characters to 48-bit numbers, but you can only use a subset of at most 64 different characters in the source string.
To convert any 8 byte string into a number, you must use a base of at least 256.
Given your extra input, After I enter "I want t" I get "Value in Decimal = 5269342824372117620", and since 5269342824372117620 == 0x492077616e742074, you do indeed use base 256, big-endian order and ASCII encoding for the characters.
Here is a simple portable pack function for this method:
unsigned long long pack(const char *s) {
unsigned long long x = 0;
int i;
for (i = 0; i < 8; i++) {
x = x * 256 + (unsigned char)s[i];
}
return x;
}
The unpack function is easy to derive: compute the remainders of divisions in the reverse order:
char *unpack(char *dest, unsigned long long x) {
/* dest is assumed to have a length of at least 9 */
int i;
for (i = 8; i-- > 0; ) {
s[i] = x % 256;
x = x / 256;
}
s[8] = '\0'; /* set the null terminator */
return s;
}
For a potentially faster but less portable solution, you could use this, but you would get a different conversion on little-endian systems such as current Macs and PCs:
#include <string.h>
unsigned long long pack(const char *s) {
unsigned long long x;
memcpy(&x, s, 8);
return x;
}
char *unpack(char *s, unsigned long long x) {
memcpy(s, &x, 8);
s[8] = '\0';
return s;
}

Is there any alternative to strtoull() function in C?

I need to convert char* to unsigned long long int and there is a function called strtoull() in the C standard library but it takes to much time. I need to quick conversion between char* to unsigned long long int. How can I write my own conversion function which is faster than the standard one?
Shortest/fastest code I can think of right now:
unsigned long long strtoull_simple(const char *s) {
unsigned long long sum = 0;
while (*s) {
sum = sum*10 + (*s++ - '0');
}
return sum;
}
No error checking. Profile to find if it improves performance. YMMV.
After accept: Tried a variation that does the initial calculation as unsigned before continuing on to unsigned long long. Marginal to negative improvements on my 64-bit machine depending on number set. Suspect it will be faster on machines where unsigned long long operations are expensive.
unsigned long long strtoull_simple2(const char *s) {
unsigned sumu = 0;
while (*s) {
sumu = sumu*10 + (*s++ - '0');
if (sumu >= (UINT_MAX-10)/10) break; // Break if next loop may overflow
}
unsigned long long sum = sumu;
while (*s) {
sum = sum*10 + (*s++ - '0');
}
return sum;
}
If code knows the length of the string then the following had some performance improvements (5%)
unsigned long long strtoull_2d(const char *s, unsigned len) {
unsigned sumu = 0;
#define INT_MAX_POWER_10 9
if (len > INT_MAX_POWER_10) {
len = INT_MAX_POWER_10;
}
while (len--) {
sumu = sumu * 10 + (*s++ - '0');
}
unsigned long long sum = sumu;
while (*s) {
sum = sum * 10 + (*s++ - '0');
}
return sum;
}
Conclusion: Improvements (I tried 7) on the simple original solution could yield small incremental speed efficiencies, but they become more and more platform and data set dependent. Suggest that programing talent is better applied to the higher level code improvements.
Answer from #soerium modified to use unsigned long long give better performance than strtoull().
unsigned long long fast_atoull(const char *str)
{
unsigned long long val = 0;
while(*str)
{
val = (val << 1) + (val << 3) + (*(str++) - 48);
}
return val;
}

Finding how to remove largest and second largest in array in c

The assignment is as followed and is coded in Keil which is an ide for c.
unsigned short data[100] = {
58473, 33594, 38638, 26741, 13018, 29262, 16377, 12354, 46079,
57240, 48949, 34054, 16212, 58485, 6198, 38678, 22525, 51012,
43489, 8861, 54291, 21524, 7166, 22698, 39899, 27113, 30443,
14888, 27935, 40035, 48710, 18067, 36008, 12644, 56319, 15852,
54685, 61789, 57030, 4763, 10655, 24656, 60363, 23712, 28474,
31274, 39647, 56166, 8219, 47413, 22201, 3129, 25630, 36027,
4499, 56525, 32743, 9380, 22102, 51009, 16309, 16589, 26322,
65279, 22780, 26002, 41101, 26082, 13389, 59504, 15784, 33416,
57970, 8519, 57819, 34406, 40864, 31575, 52154, 60214, 39910,
43107, 64825, 40284, 60148, 27287, 38245, 49930, 54062, 50668,
30553, 27904, 38960, 49407, 10508, 62147, 33019, 3047, 33750, 18024};
Write functions to preform the following operations on the array. You must pass the array to functions in order to receive full credit.
Find the index of the largest number, FindInexOfLargest().
Remove a specified entry, given an index, in the array, RemoveEntry(). Note that data appearing in the array after the removed entry is to be shifted to the left, so that data[i] becomes data[i+1].
Remove the largest entry in an array, RemoveLargestEntry(). The array is mutated to remove the largest entry. The value of the largest entry is returned by the function.
Remove the second largest entry in an array, RemoveSecondLargestEntry(). The function should return the numerical value of the second largest entry in an array, and remove that value.
The functions written for 3 and 4 should use the functions written in 1 and 2. For full credit, no loops should appear in the functions written in part 3 and 4.
This is my code that isn't working right and I can't find out where the mistake is. It's a logical error somewhere I just don't know where.
unsigned short int data[100] = {
58473, 33594, 38638, 26741, 13018, 29262, 16377, 12354, 46079,
57240, 48949, 34054, 16212, 58485, 6198, 38678, 22525, 51012,
43489, 8861, 54291, 21524, 7166, 22698, 39899, 27113, 30443,
14888, 27935, 40035, 48710, 18067, 36008, 12644, 56319, 15852,
54685, 61789, 57030, 4763, 10655, 24656, 60363, 23712, 28474,
31274, 39647, 56166, 8219, 47413, 22201, 3129, 25630, 36027,
4499, 56525, 32743, 9380, 22102, 51009, 16309, 16589, 26322,
65279, 22780, 26002, 41101, 26082, 13389, 59504, 15784, 33416,
57970, 8519, 57819, 34406, 40864, 31575, 52154, 60214, 39910,
43107, 64825, 40284, 60148, 27287, 38245, 49930, 54062, 50668,
30553, 27904, 38960, 49407, 10508, 62147, 33019, 3047, 33750, 18024};
// ***** 2. Global Declarations Section *****
// FUNCTION PROTOTYPES: Each subroutine defined
unsigned short int FindIndexOfLargest(unsigned short int class[], unsigned short int start, unsigned short int end);
unsigned short int RemoveEntry(unsigned short int class[], unsigned short int size, int position);
unsigned short int RemoveLargestEntry(unsigned short int class[], unsigned short int size);
unsigned short int RemoveSecondLargest(unsigned short int class[], unsigned short int start, unsigned short int end);
// ***** 3. Subroutines Section *****
int main (void) {
printf("Largest: %u\n", FindIndexOfLargest(data, 0, 100));
printf("Removing: %u\n", RemoveEntry(data, 100, 7));
printf("Removing Largest: %u\n", RemoveLargestEntry(data, 100));
printf("Removing Second Largest: %u\n", RemoveSecondLargest(data, 0, 100));
}
unsigned short int FindIndexOfLargest(unsigned short int class[],unsigned short int start, unsigned short int end){
unsigned short int largest,i;
largest = 0; // smallest possible value
for(i=0; i<end; i++){
if(class[i] > largest){
largest = class[i]; // new maximum
}
}
return (class[i]);
}
unsigned short int RemoveEntry(unsigned short int class[], unsigned short int size, int position) {
unsigned short int c;
for (c = (position - 1) ; c < (size - 1) ; c++ ) {
class[c] = class[c+1];
}
return class[c];
}
unsigned short int RemoveLargestEntry(unsigned short int class[], unsigned short int size) {
return RemoveEntry(class, size, FindIndexOfLargest(class, 0, 100));
}
unsigned short int RemoveSecondLargest(unsigned short int class[], unsigned short int start, unsigned short int end) {
unsigned short int Largest = FindIndexOfLargest(class, start, end);
unsigned short int firstLarge = FindIndexOfLargest(class, start, (Largest-1));
unsigned short int secondLarge = FindIndexOfLargest(class, (Largest+1), end);
if (firstLarge > secondLarge) {
return RemoveEntry(class, end, firstLarge);
}
else {
return RemoveEntry(class, end, secondLarge);
}
}
There is one mistake in FindIndexOfLargest function Change it to:
unsigned short int FindIndexOfLargest(unsigned short int class[],unsigned short int start, unsigned short int end){
unsigned short int largest,i;
largest = 0; // smallest possible value
for(i=0; i<end; i++){
if(class[i] > largest){
largest = class[i]; // new maximum
}
}
return (largest); //NOTE CHANGE HERE:Return largest number
}
As the function name suggest if you want to return the index of largest number then change it to:
unsigned short int FindIndexOfLargest(unsigned short int class[],unsigned short int start, unsigned short int end){
unsigned short int largest,i;
largest = 0; // smallest possible value
for(i=0; i<end; i++){
if(class[i] > largest){
largest = i; // NOTE CHANGE HERE:new maximum index
}
}
return (largest); //NOTE CHANGE HERE:Return largest index
}
As pointed out by Vagish There is a mistake in the function FindIndexOfLargest you are doing this
unsigned short int FindIndexOfLargest(unsigned short int class[],unsigned short int start, unsigned short int end){
unsigned short int largest,i;
largest = 0; // smallest possible value
for(i=0; i<end; i++){
if(class[i] > largest){
largest = class[i]; // new maximum
}
}
return (largest); // This is returning the largest no rather than returning the index
}
so do it like this
unsigned short int FindIndexOfLargest(unsigned short int class[],unsigned short int start, unsigned short int end){
unsigned short int largest,i,index;
largest = 0; // smallest possible value
for(i=0; i<end; i++){
if(class[i] > largest){
largest = class[i]; // new maximum
index=i;
}
}
return (index); //This is returning the index of the largest
}
There is also the problem in the Remove Entry function do it like this
unsigned short int RemoveEntry(unsigned short int class[], unsigned short int size, int position) {
unsigned short int c;
for (c =position; c <size;++c ) {
class[c] = class[c+1];
}
size-=1;
return size; //Return size of new array after removing the data
}
Well then there remains the last function, please try to find the logical error there and if not able let us know :)
Hope these answer helps
unsigned short int FindIndexOfLargest(unsigned short int tempArr[],unsigned short int start, unsigned short int end){
unsigned short int largest,i;
largest = 0; // smallest possible value
for(i=0; i<end; i++){
if(tempArr[i] > tempArr[largest]){
largest = i; // new maximum
}
}
return (largest); //Change return value class[i] to largest;
}
void RemoveEntry(unsigned short int class[], unsigned short int size, int position) {
unsigned short int c;
for (c = (position - 1) ; c < (size - 1) ; c++ ) {
class[c] = class[c+1];
}
//return class[c]; <<< array pass by pointer,so no need to return; *change unsigned short int to void.
void RemoveLargestEntry(unsigned short int tempArr[], unsigned short int size) {
RemoveEntry(class, size, FindIndexOfLargest(tempArr, 0, 100)); // This is the same with RemoveEntry function;
}
unsigned short int RemoveSecondLargest(unsigned short int tempArr[],unsigned short int start, unsigned short int end) {
unsigned short int Largest,PositionLargest,SecondLargest,PositionSecondLargest;
Largest = tempArr[FindIndexOfLargest(tempArr[],0,end)];
RemoveLargestEntry(tempArr,end); /*Remove largest and sencond largest number in the Array */
SecondLargest = FindIndexOfLargest(tempArr,0,end);
RemoveLargestEntry(tempArr,end-1);
tempArr[99] = Largest; // Add number at the end of the array;
return(SecondLargest);
}
Function 4 is only for your provide array. If the situation where the number in the array is less than 100(e.g 30),function 4 will be useless.

conversion of BCD to unsigned char

I have a unsigned char array containing the following value : "\x00\x91\x12\x34\x56\x78\x90";
That is number being sent in Hexadecimal format.
Additionally, it is in BCD format : 00 in byte, 91 in another byte (8 bits)
On the other side I require to decode this value as 0091234567890.
I'm using the following code:
unsigned int conver_bcd(char *p,size_t length)
{
unsigned int convert =0;
while (length--)
{
convert = convert * 100 + (*p >> 4) * 10 + (*p & 15);
++p
}
return convert;
}
However, the result which I get is 1430637214.
What I understood was that I'm sending hexadecimal values (\x00\x91\x12\x34\x56\x78\x90) and my bcd conversion is acting upon the decimal values.
Can you please help me so that I can receive the output as 00911234567890 in Char
Regards
Karan
It looks like you are simply overflowing your unsigned int, which is presumably 32 bits on your system. Change:
unsigned int convert =0;
to:
uint64_t convert = 0;
in order to guarantee a 64 bit quantity for convert.
Make sure you add:
#include <stdint.h>
Cast char to unsigned char, then print it with %02x.
#include <stdio.h>
int main(void)
{
char array[] = "\x00\x91\x12\x34\x56\x78\x90";
int size = sizeof(array) - 1;
int i;
for(i = 0; i < size; i++){
printf("%02x", (unsigned char )array[i]);
}
return 0;
}
Change return type to unsigned long long to insure you have a large enough integer.
Change p type to an unsigned type.
Print value with leading zeros.
unsigned long long conver_bcd(const char *p, size_t length) {
const unsigned char *up = (const unsigned char*) p;
unsigned long long convert =0;
while (length--) {
convert = convert * 100 + (*up >> 4) * 10 + (*up & 15);
++up;
}
return convert;
}
const char *p = "\x00\x91\x12\x34\x56\x78\x90";
size_t length = 7;
printf( "%0*llu\n", (int) (length*2), conver_bcd(p, length));
// 00911234567890

Combine two 32bit efficiently? - C

I have a function which expects a 8 bytes long unsigned char.
void f1(unsigned char *octets)
{
unsigned char i;
for (i=0;i<8;i++)
printf("(%d)",octets[i]);
}
This is how I use it while I have one 64bit integer:
unsigned long long ull = 1;
f1((unsigned char *) &ull);
(it uses the machine's native endianness.)
My question is, if instead of having 1x64bit integer, I have 2x32bit integers - is there a way to combine them efficiently as an input for this specific function?
unsigned long int low = 1;
unsigned long int high = 0;
Does a union work portably? If so, it's a good approach...
union {
struct {
unsigned char CharArray[8];
} ub;
struct {
unsigned long int IntArray[2];
} ul;
unsigned long long ull;
} Foo;
You could just put them in an array:
unsigned long int lohi[2] = {1, 0};
f1((unsigned char *) lohi);
edit: Using existing variables:
unsigned long int lohi[2] = {lo, hi};
Typecast, bitshift and do bitwise or.
unsigned long int low = 1;
unsigned long int high = 0;
unsigned long long ull = (unsigned long long) high << 32 | low;
You can use a combination of union and struct to keep your namings and not using arrays.
union {
struct {
unsigned long int low = 0;
unsigned long int high = 1;
};
unsigned long long int ull;
};
Use low and high as you would do, and use ull when calling f1. But notice that writing it this way, you assume a little endian ordering.
Also note that on Linux anh other UNIXes, in 64 bits mode, both long int and long long int are 64 bits (only int is 32 bits). Of what I know, only Windows has long int as 32 bits in 64 bits mode.
Different way of looking at it:
void f1( unsigned char* octet )
{
f2( octet, octet + 4 );
}
void f2( unsigned char* quad1, unsigned char *quad2 )
{
unsigned char i;
for (i=0;i<4;i++)
printf("(%d)",quad1[i]);
for (i=0;i<4;i++)
printf("(%d)",quad2[i]);
}
Works better in C++ when both functions can have the same name.

Resources