Search code examples
cparallel-processingaesmpiipc

How to fix decryption of AES in C using MPI


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;

Solution

  • 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.