1

Currently I am trying to use MPI to pass a particular encrypted data from one processor to another using only 2 processor to just check if encryption or decryption is working. I have an int value which is converted to string for encryption and then sent to processor rank 1. I am receiving the string correctly in processor but when I call the decryption function it seems to not give me the plaintext. I have downloaded the AES code from https://github.com/kokke/tiny-AES-C

int size,rank;
MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);


int data = 532123;
uint8_t data_file[10];
uint8_t key[1] = {50};
int data_decrypt;
uint8_t iv[1] = {1};


struct AES_ctx ctx;

if (rank == 0) {

    sprintf((char *) data_file, "%d", data);
    AES_init_ctx_iv(&ctx, key, iv);
    AES_CTR_xcrypt_buffer(&ctx, data_file, strlen((char *) data_file));

    printf("Sending in 0: %s\n",(char*) data_file);
    MPI_Send(data_file,10,MPI_UINT8_T,1,0,MPI_COMM_WORLD);

}else{

    MPI_Recv(data_file,10,MPI_UINT8_T,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
    printf("Recieved in 1: %s\n",(char*)data_file);

    AES_init_ctx_iv(&ctx, key, iv);
    AES_CTR_xcrypt_buffer(&ctx, data_file, strlen((char*)data_file));
    printf("DEC at Rank 1: %s\n",(char*) data_file);

}
MPI_Finalize();
return 0;

1 Answers1

0

First of all we must install requirements. see this link

After successfully install the requirements we run simple hello world MPI.

Hello World!

#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {
    // Initialize the MPI environment
    MPI_Init(NULL, NULL);

    // Get the number of processes
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);

    // Get the rank of the process
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

    // Get the name of the processor
    char processor_name[MPI_MAX_PROCESSOR_NAME];
    int name_len;
    MPI_Get_processor_name(processor_name, &name_len);

    // Print off a hello world message
    printf("Hello world from processor %s, rank %d out of %d processors\n",
           processor_name, world_rank, world_size);

    // Finalize the MPI environment.
    MPI_Finalize();
}

source of above code

Compile and Run

$ mpicc mhello.c -o mhello
$ mpirun -np #numberOfProcess ./mhello

After successful run this code you can go further.


And return to original Question.

I think your usage of AES part of project is wrong.

By performing some changes and use

AES_ECB_decrypt(&ctx, data_file);

AES_ECB_encrypt(&ctx, data_file);

works.

GitHub page of project say how to use Enc and Dec function see

Second important change to use struct AES_ctx ctx; above main to only one time execution.


This is working version of code.

mpi-hello.c

#include <stdio.h>
#include <string.h>
#include <mpi.h>
#include "aes.h"

/*
 * compile
 * mpicc mpi-hello.c aes.c -o mpi-hello
 * 
 * Run
 * mpirun -np 2  executable
 * 
 * 
 *
 * */

struct AES_ctx ctx;

unsigned long ToUInt(char* str)
{
    unsigned long mult = 1;
    unsigned long re = 0;
    int len = strlen(str);
    for(int i = len -1 ; i >= 0 ; i--)
    {
        re = re + ((int)str[i] -48)*mult;
        mult = mult*10;
    }
    return re;
}


int main(int argc, char** argv) {

    int size,rank=0;

    MPI_Init(NULL, NULL);

    // Get the number of processes
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    // Get the rank of the process
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int data = 532123;
    uint8_t data_file[10];

    printf("this is in main\n");

    if (rank == 0) {
        printf("data rank: 0: %d\n", data);
        //convert in to string
        sprintf( data_file, "%d", data);
        //string
        printf("data rank: 0: %s\n", data_file);

        //encrypt data
        AES_ECB_encrypt(&ctx, data_file);

        printf("Sending in 0 after crypt: %s\n", data_file);
        printf("strlen send: %d\n", strlen(data_file));

        MPI_Send(data_file,16,MPI_UINT8_T,1,0,MPI_COMM_WORLD);

    }else{

        MPI_Recv(data_file,16,MPI_UINT8_T,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
        printf("Recieved in 1 before: %s\n",data_file);
        printf("strlen recv: %d\n", strlen(data_file));

        AES_ECB_decrypt(&ctx, data_file);

        printf("DEC at Rank 1 string: %s\n", data_file);
        printf("DEC at Rank 1 int: %u\n", ToUInt(data_file));
    }


    MPI_Finalize();
}

Important notes

  • Place aes.c source file in same folder of original source i.e: mpi-hello.c
  • compile the code with mpicc mpi-hello.c aes.c -o mpi-hello

  • run with: mpirun -np 2 ./mpi-hello

  • I find that second argument of MPI_Send must be changed to 16, But why?

PS.

  • Installing from repository on Debian based system not works and i have to build it from source.

  • Original source of convert string to int I know this may not best solution but works.

  • How to run MPI.

  • A fast MPI C tutorial

Edit 1

#include <stdio.h>
#include <string.h>
#include <mpi.h>
#include "aes.h"

/*
 * compile
 * mpicc mpi-hello.c aes.c -o mpi-hello
 * 
 * Run
 * mpirun -np 2  executable
 * 
 * 
 *
 * */

struct AES_ctx ctx;

unsigned long ToUInt(char* str)
{
    unsigned long mult = 1;
    unsigned long re = 0;
    int len = strlen(str);
    for(int i = len -1 ; i >= 0 ; i--)
    {
        re = re + ((int)str[i] -48)*mult;
        mult = mult*10;
    }
    return re;
}


int main(int argc, char** argv) {

    int size,rank=0;

    MPI_Init(NULL, NULL);

    // Get the number of processes
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    // Get the rank of the process
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int data = 532123;
    uint8_t data_file[10];

    printf("this is in main\n");

    if (rank == 0) {
        printf("data rank: 0: %d\n", data);
        //convert in to string
        sprintf( data_file, "%d", data);
        //string
        printf("data rank: 0: %s\n", data_file);

        //encrypt data
        //AES_ECB_encrypt(&ctx, data_file);
        AES_CTR_xcrypt_buffer(&ctx, data_file, strlen(data_file));
        printf("Sending in 0 after crypt: %s\n", data_file);
        printf("strlen send: %d\n", strlen(data_file));

        MPI_Send(data_file,10,MPI_UINT8_T,1,0,MPI_COMM_WORLD);

    }else{

        MPI_Recv(data_file,10,MPI_UINT8_T,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
        printf("Recieved in 1 before: %s\n",data_file);
        printf("strlen recv: %d\n", strlen(data_file));


        //AES_ECB_decrypt(&ctx, data_file);

        AES_CTR_xcrypt_buffer(&ctx, data_file, strlen(data_file));  

        printf("DEC at Rank 1 string: %s\n", data_file);
        printf("DEC at Rank 1 int: %u\n", ToUInt(data_file));
    }


    MPI_Finalize();
}

Edit 2

Apply request in comment.

#include <stdio.h>
#include <string.h>
#include <mpi.h>
#include "aes.h"

/*
 * compile
 * mpicc mpi-hello.c aes.c -o mpi-hello
 * 
 * Run
 * mpirun -np 2  executable
 * 
 * 
 * */


unsigned long ToUInt(char* str)
{
    unsigned long mult = 1;
    unsigned long re = 0;
    int len = strlen(str);
    for(int i = len -1 ; i >= 0 ; i--)
    {
        re = re + ((int)str[i] -48)*mult;
        mult = mult*10;
    }
    return re;
}


int main(int argc, char** argv) {

    int size,rank=0;

    MPI_Init(NULL, NULL);

    // Get the number of processes
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    // Get the rank of the process
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int data = 532123;
    uint8_t data_file[10];


     //start Crypto Section

    //~ key and iv
    ///

    uint8_t key[32] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
                        0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 
    };

    uint8_t iv[16]  = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
    };
    ///    

    struct AES_ctx ctx;


    printf("this is in main\n");

    if (rank == 0) {
        printf("data rank: 0: %d\n", data);
        //convert in to string
        sprintf( data_file, "%d", data);
        //string
        printf("data rank: 0: %s\n", data_file);

        ///Enc

        //set
        AES_init_ctx_iv(&ctx, key, iv); 

        //enc
        AES_CTR_xcrypt_buffer(&ctx, data_file, strlen(data_file));


        printf("Sending in 0 after crypt: %s\n", data_file);
        printf("strlen send: %d\n", strlen(data_file));

        MPI_Send(data_file,10,MPI_UINT8_T,1,0,MPI_COMM_WORLD);

    }else{

        MPI_Recv(data_file,10,MPI_UINT8_T,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
        printf("Recieved in 1 before: %s\n",data_file);
        printf("strlen recv: %d\n", strlen(data_file));

        ///Dec
        //set
        AES_init_ctx_iv(&ctx, key, iv); 

        //dec
        AES_CTR_xcrypt_buffer(&ctx, data_file, strlen(data_file));  

        printf("DEC at Rank 1 string: %s\n", data_file);
        printf("DEC at Rank 1 int: %u\n", ToUInt(data_file));
    }


    MPI_Finalize();
}

Edit 3

Place key and iv in if else section.

if (rank == 0) {
    printf("data rank: 0: %d\n", data);
    //convert in to string
    sprintf( data_file, "%d", data);
    //string
    printf("data rank: 0: %s\n", data_file);

    //~ key and iv
    ///

    uint8_t key[32] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
                        0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 
    };

    uint8_t iv[16]  = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
    };
    ///    
    ///Enc

    //set
    AES_init_ctx_iv(&ctx, key, iv); 

    //enc
    AES_CTR_xcrypt_buffer(&ctx, data_file, strlen(data_file));


    printf("Sending in 0 after crypt: %s\n", data_file);
    printf("strlen send: %d\n", strlen(data_file));

    MPI_Send(data_file,10,MPI_UINT8_T,1,0,MPI_COMM_WORLD);

}else{

    MPI_Recv(data_file,10,MPI_UINT8_T,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
    printf("Recieved in 1 before: %s\n",data_file);
    printf("strlen recv: %d\n", strlen(data_file));



    //~ key and iv
    ///

    uint8_t key[32] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
                        0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 
    };

    uint8_t iv[16]  = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
    };
    ///    
    ///Dec
    //set
    AES_init_ctx_iv(&ctx, key, iv); 

    //dec
    AES_CTR_xcrypt_buffer(&ctx, data_file, strlen(data_file));  

    printf("DEC at Rank 1 string: %s\n", data_file);
    printf("DEC at Rank 1 int: %u\n", ToUInt(data_file));
}

For example You can change first element of key i.e: 0x60 -> 0x61 in either if or else not both, then recompile and run the program to see if receiver haven't correct key he/she cant decode your encrypted data.

[ToDo]

  • Add some more explanation on AES.
EsmaeelE
  • 2,331
  • 6
  • 22
  • 31
  • Hey there seems to me all that was changed was the method of encryption i orginally was doing CTR one and the one that is working for you is the ECB. Why is it different because in the github it says the same CTR function can be used for both encryption and decryption. And also the second argument of MPI send and recv was changed to 16 from 10 what could be the reason since the second parameter is basically telling mpi the count of whatever thing is being sent or recieved which in this case is the datafile which is of size 10??? – Jayed Ar Rabbi Oct 03 '19 at 16:41
  • I Update the answer. – EsmaeelE Oct 03 '19 at 17:02
  • Oh thank you alot for your kind reply i very much appreciate it and also one more thing. I see that in ur implementation u did not use any key or iv why is that? Like shouldnt i be able to use a key which i generate and encrypt and can pass on others so that they decrypt. – Jayed Ar Rabbi Oct 03 '19 at 17:26
  • Thank you again so much for your help I did not realise the size of the key and IV mattered. Thank you, you're the best! – Jayed Ar Rabbi Oct 04 '19 at 04:52
  • @JayedArRabbi I have used standard key and iv values in original aes.c file. see gitHub project. – EsmaeelE Oct 04 '19 at 20:35