如何使用 MPI 修复 C 中 AES 的解密

How to fix decryption of AES in C using MPI

目前我正在尝试使用 MPI 将特定的加密数据从一个处理器传递到另一个处理器,仅使用 2 个处理器来检查加密或解密是否有效。我有一个 int 值,它被转换为字符串进行加密,然后发送到处理器等级 1。 我在处理器中正确接收到字符串,但是当我调用解密函数时,它似乎没有给我明文。 我已经从 https://github.com/kokke/tiny-AES-C

下载了 AES 代码
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;

首先我们必须安装要求。 see this link

成功安装要求后我们运行简单的hello world MPI。

你好世界!

#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

编译并运行

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

成功后运行这段代码可以更进一步


和 return 到原始问题。

我认为您对项目 AES 部分的使用是错误的。

通过执行一些更改并使用

AES_ECB_decrypt(&ctx, data_file);

AES_ECB_encrypt(&ctx, data_file);

有效。

GitHub 项目页面说明如何使用 Enc 和 Dec 函数 see

使用的第二个重要变化struct AES_ctx ctx; 以上 main 只执行一次。


这是代码的工作版本。

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

重要提示

  • aes.c 源文件放在与原始源相同的文件夹中,即:mpi-hello.c
  • mpicc mpi-hello.c aes.c -o mpi-hello

  • 编译代码
  • 运行 与:mpirun -np 2 ./mpi-hello

  • 我发现 MPI_Send 的第二个参数必须更改为 16,但是为什么?

PS.

  • 在基于 Debian 的系统上从存储库安装不起作用,我必须从源代码构建它。

  • convert string to int 的原始来源我知道这可能不是最佳解决方案,但很有效。

  • 如何运行.

  • 快速 MPI C tutorial

编辑 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();
}

编辑 2

在评论中应用请求。

#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();
}

编辑 3

将 key 和 iv 放在 if else 部分。

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

例如,您可以更改密钥的第一个元素,即:0x60 -> 0x61 在 if 或 else not both 中,然后重新编译和 运行 程序以查看接收方是否没有正确的密钥 he/she 无法解码您的加密数据。

[待办事项]

  • 添加更多关于 AES 的解释。