memcpy 和 strcpy 在复制 openssl BIGNUM 时有什么区别

What causes the difference between memcpy and strcpy in copying openssl BIGNUM

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

void generate_r_vector(char (*r_vector)[17],char *random_r) {
    BIGNUM* vector[127];
    char r_v[128][17];
    char flag[17];
    memset(flag, 0, 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], 0, sizeof(r_v[i]));
        BN_bn2bin(vector[i], r_v[i]);
    }
    memset(r_v[127], 0, 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。 但是在主函数异或中使用strcpy函数复制这些数组,无法得到原来的random_r.

OpenSSL的小知识:这里把一个128位的大数转成二进制,然后每4位转成一个十进制,存入char大批。 memcpy按字节复制,而strcpy只能复制字符串。

无法理解为什么两种copy方法都存储在char数组中,异或结果不同

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

=======================2021/2/21更新数据================ ===================== 我提供一个可以直接运行的程序,希望能减轻我表达不清带来的问题

int main() {
    char* random_r="1234567891234567";//长度16 算上'[=11=]'17
    char r_vector[128][17];
    BIGNUM* vector[127];
    char r_v[128][17];
    char flag[17];//判断是否一致
    memset(flag, 0, 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], 0, sizeof(r_v[i]));
        BN_bn2bin(vector[i], r_v[i]);
    }
    memset(r_v[127], 0, 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, 0, 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], r_v[i], 17);//逐字节拷贝解决问题strcpy会出现问题,原因未知
    }
    memset(ans, 0, 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, 0, sizeof(r_vector));
    for (int i = 0; i < 128; i++) {
        strcpy(r_vector[i], r_v[i]);//strcpy会出现问题,原因未知
    }
    memset(ans, 0, 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

What causes the difference between memcpy and strcpy in copying openssl BIGNUM

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

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

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