问题描述
这个问题在我编程的时候困扰了我一个小时,但是解决之后还是不知道原来方法的错误。
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 值,那么事情的行为将与字符串不同。