复制openssl BIGNUM时memcpy和strcpy的区别是什么原因

问题描述

这个问题在我编程的时候困扰了我一个小时,但是解决之后还是不知道原来方法错误

void generate_r_vector(char (*r_vector)[17],char *random_r) {
    BIGNUM* vector[127];
    char r_v[128][17];
    char flag[17];
    memset(flag,sizeof(flag));
    int bits = 128;
    int top = 0;
    int bottom = 0;
    for (int i = 0; i < 127; i++) {
        vector[i] = BN_new();
        BN_rand(vector[i],bits,top,bottom);
        memset(r_v[i],sizeof(r_v[i]));
        BN_bn2bin(vector[i],r_v[i]);
    }
    memset(r_v[127],sizeof(r_v[127]));
    for (int i = 0; i < 127; i++) {
        for (int j = 0; j < 16; j++) {
            flag[j] = flag[j] ^ r_v[i][j];
        }
    }
    for (int i = 0; i < 16; i++) {
        r_v[127][i] = flag[i] ^ random_r[i];
    }
    
    
    for (int i = 0; i < 128; i++) {
        memcpy(r_vector[i],r_v[i],17);
    }
}

使用memcpy复制这些数组,在main函数中进行异或时,可以得到原始字符串random_r。 但是在主函数XOR中使用strcpy函数复制这些数组,无法得到原来的random_r。

我对OpenSSL的了解:这里,将一个128位的大数转成二进制,然后每4位转成一个十进制,存放在char数组中。 memcpy 按字节复制,而strcpy 只能复制字符串。

我不明白为什么这两种复制方法都存储在char数组中时XOR结果不同。

我的英文水平不好,希望各位程序员能看懂我的表达。我真诚地希望你能回答我的问题。谢谢

========================2021/2/21 更新================== ==================== 我提供了一个可以直接运行的程序,希望能缓解我表达不清的问题。

int main() {
    char* random_r="1234567891234567";//长度16 算上'\0'17
    char r_vector[128][17];
    BIGNUM* vector[127];
    char r_v[128][17];
    char flag[17];//判断是否一致
    memset(flag,sizeof(r_v[127]));
    for (int i = 0; i < 127; i++) {
        for (int j = 0; j < 16; j++) {
            flag[j] = flag[j] ^ r_v[i][j];
        }
    }
    for (int i = 0; i < 16; i++) {
        r_v[127][i] = flag[i] ^ random_r[i];
    }
    //至此生成了128个向量,这些向量的异或之和正好是random_r的值,ans可以验证这个结论
    char ans[17];
    memset(ans,sizeof(ans));
    for (int i = 0; i < 128; i++) {
        for (int j = 0; j < 16; j++) {
            ans[j] = ans[j] ^ r_v[i][j];
        }
    }
    printf("the target XOR result is:%s\n",ans);//
    //下面使用memcpy的形式拷贝并求异或值
    for (int i = 0; i < 128; i++) {
        memcpy(r_vector[i],17);//逐字节拷贝解决问题strcpy会出现问题,原因未知
    }
    memset(ans,sizeof(ans));
    for (int i = 0; i < 128; i++) {
        for (int j = 0; j < 16; j++) {
            ans[j] = ans[j] ^ r_vector[i][j];
        }
    }
    printf("using memcpy copying and the result is:%s\n",ans);//这是正确的结果
    
    
    memset(r_vector,sizeof(r_vector));
    for (int i = 0; i < 128; i++) {
        strcpy(r_vector[i],r_v[i]);//strcpy会出现问题,原因未知
    }
    memset(ans,sizeof(ans));
    for (int i = 0; i < 128; i++) {
        for (int j = 0; j < 16; j++) {
            ans[j] = ans[j] ^ r_vector[i][j];
        }
    }
    printf("using strcpy copying and the result is:%s\n",ans);
    int err_count = 0;
    for (int i = 0; i < 128; i++) {
        if (strcmp(r_vector[i],r_v[i]) != 0) err_count++;
    }
    printf("after using strcpy() each vector using strcmp() with orignal r_v,the different vector nums:%d\n",err_count);

    system("pause");
    return 0;
}

vs2019 运行结果

the target XOR result is:1234567891234567
using memcpy copying and the result is:1234567891234567
using strcpy copying and the result is:12eH⊙碡?H-c纫
after using strcpy() each vector using strcmp() with orignal r_v,the different vector nums:0

解决方法

memcpy 和 strcpy 复制 openssl BIGNUM 的区别是什么原因

注释“BIGNUM 值不是 C 字符串,因此 strcpy() 不起作用。”可能不足以启发你。
BIGNUM 值可以包含一个所有位都设置为 0 的 字节,称为 空字符 并且由于 用于终止字符串strcpy() 停在那里,不会复制 BIGNUM 值的其余部分。

,

即使 strcpy 和 memcpy 都用于 char 数组,它们的作用也不尽相同。 memcpy 复制固定数量的字节,您将其作为第三个参数提供。 strcpy 不只是从一个字符数组或指向另一个字符数组的指针进行复制,它还计算以完全不同的方式复制多少,即通过检查要复制的字符中的 0 值。

即使 r_vector 指向 char 数组,它们也不一定是字符串:如果它们不是以 0 结尾的或在其他位置有 0 值,那么事情的行为将与字符串不同。