0

This problem bothered me for an hour when I was programming, but I still didn't know the error of the original method after solving it.

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

Using memcpy to copy these arrays, when XOR in the main function, you can get the original string random_r. But using the strcpy function to copy these arrays in the main function XOR, can not get the original random_r.

What I learned about OpenSSL:here, a 128 bit large number is converted into binary, and then every 4 bits are converted into a decimal, which is stored in the char array. Memcpy copies by byte, while strcpy can only copy strings.

I can't understand why the XOR results of the two copy methods are different when they are both stored in char arrays.

My English level is not good, I hope you programmers can understand my expression. I sincerely hope you can answer my question. thank you

=======================2021/2/21 updata===================================== I provide a program that can run directly, hoping to alleviate the problems caused by my unclear expression.

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

Running results in 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
mikami
  • 43
  • 4
  • It's not clear what you're asking here. – tadman Feb 20 '21 at 09:15
  • Are you saying "Why can't I use `strcpy()` to copy BIGNUM values?" If so the answer is "BIGNUM values are not C strings, so `strcpy()` won't work." If every 4 bits are converted, that's *hexadecimal*, not decimal. Unless this is specified as a NUL terminated string you can't use `strcpy()`. – tadman Feb 20 '21 at 09:18
  • thanks for your answers,Sorry, because my English ability makes this sentence ambiguous. I use a more accurate expression: every 4 bits are converted into a ten figures。Translation software may translate two digits (XX is like a two digit number like 67 54) into decimal – mikami Feb 21 '21 at 02:48
  • English can be a problem. That's why code helps a lot, like if you can show us what you use for inputs and your expected output we can usually understand better. – tadman Feb 21 '21 at 03:33
  • I hope this function can achieve such a function: input a 128bit string and return 128 128bit strings. The XOR value of the 128 strings is exactly the 128bit string input. – mikami Feb 21 '21 at 07:15

2 Answers2

1

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

The comment "BIGNUM values are not C strings, so strcpy() won't work." may be not enough to enlighten you.
BIGNUM values can contain a byte with all bits set to 0, called the null character, and since that is used to terminate a character string, strcpy() stops there and doesn't copy the rest of the BIGNUM value.

Armali
  • 18,255
  • 14
  • 57
  • 171
  • thanks for your reply.But when I use strcmp (), I don't return a value other than 0 – mikami Feb 21 '21 at 07:27
  • `strcmp()` also stops at the first null byte, hence you can't use `strcmp` to compare BIGNUM values neither. – Armali Feb 21 '21 at 09:15
  • 2
    Thank you very much for your repeated answers. I think your answers have solved my problems! – mikami Feb 22 '21 at 01:52
0

Even when strcpy and memcpy are both used for char arrays, they don't do exactly the same thing. memcpy copies a fixed number of bytes, which you give as the third argument. strcpy doesn't just copy from one char array or pointer to another, it figures out how much to copy in a completely different way, namely by checking for a 0 value in the chars to copy.

Even though r_vector points to char arrays, they don't have to be strings: If they are not 0-terminated or have 0 values at other positions things will behave differently than for a string.

Gnoom
  • 183
  • 6
  • Thank you for your reply. I used strcpy and memcpy to generate 256 strings (128 strings each). And use the StrCmp function to match one by one, they are all the same (use if to judge whether it is 0). But when I XOR the two groups of strings separately, I get different answers. If it is because of the ending character, whether it should be unequal when StrCmp matches. – mikami Feb 21 '21 at 02:51