在C语言中向结构体数组添加元素

3

我们正在实现使用SRA协议的Mental Poker加密算法。在此过程中,我们将使用BIGNUM的openSSL库http://www.openssl.org/docs/crypto/bn.html,但是我在将加密卡添加到BIGNUM结构数组时遇到了问题。

#include <openssl/bn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

BIGNUM* encryptedDeck[52];
BIGNUM* bobHand[5];
BIGNUM* aliceHand[5];

int main(int argc, char* argv[]){
    int lcv = 0;
    BIGNUM *P,*Q,*N,*alpha,*alphaPrime,*beta,*betaPrime,*temp,*Pminus;
    BN_CTX *ctx = BN_CTX_new();
    P = BN_new(); //same for all BIGNUM pointers

    BN_generate_prime(P,512,1,NULL,NULL,NULL,NULL);
    BN_generate_prime(Q,512,1,NULL,NULL,NULL,NULL);
    BN_generate_prime(alpha,128,1,NULL,NULL,NULL,NULL); //Alice's key [ gcd(alpha,P) = 1 ]
    BN_generate_prime(beta,128,1,NULL,NULL,NULL,NULL);  //Bob's key. Same rule as alice's

    BN_one(temp);  //set temp to be a BIGNUM equivalent to integer 1
    BN_sub(Pminus,P,temp);

    BN_mul(N,P,Q,ctx);

    temp = BN_new();
    BIGNUM *encryptedCard = BN_new();
    for(lcv; lcv < 52; lcv++){
        BN_bin2bn(deck[lcv],strlen(deck[lcv]),temp);
        BN_mod_exp(encryptedCard,temp,beta,P,ctx);    //encrypt temp, store in encryptedCard

        printf("ec: %s\n\n",BN_bn2dec(encryptedCard));  //prints *correct numbers

        encryptedDeck[lcv] = encryptedCard;  //store cards in the array of encrypted cards
    }

    printf("00: %s\n\n",BN_bn2dec(encryptedDeck[0]));
    printf("01: %s\n\n",BN_bn2dec(encryptedDeck[1]));
    //...
    printf("40: %s\n\n",BN_bn2dec(encryptedDeck[40]));
}

在 for 循环中的打印语句输出了 52 个不同的值(每张牌一个)。原本我希望这些值只是被简单地添加到数组 encryptedDeck 中,但是当我在循环结束后检查这些值时,它们全部等于第 52 张牌。出现了什么问题导致每个新牌的索引都被覆盖了呢?或者是其他奇怪的情况?
处理结构体数组时是否有一些显而易见的事情被忽略了?我能想到的唯一可能就是数组没有足够的空间被初始化。
我认为可以把 BIGNUM 值转换为 char* 并以这种方式存储到数组中,但我尝试避免这样做,因为我不知道指针需要多大,也无法猜测它们的范围。类似于:
char encryptedDeck[52][something ridiculous];

我省略了一些代码,但我相信这仍然可以编译(只要您有openssl库,并在编译时链接它),并为我没有初始化的所有其他BIGNUM指针填充BN_new()。


+1 给一个清晰的问题和格式良好的代码。很高兴能从 SO 的新手那里看到它。 - user529758
+1 同样的原因。即使代码没有编译,我仍然可以理解它,而且描述非常准确,清晰地表达了他的目标和观察到的问题。这对于一个新的 SO 发帖者来说是非常罕见的。 - WhozCraig
1个回答

2
在你的for循环上面:
BIGNUM *encryptedCard = BN_new();

您永远不会改变指向什么的内容,您只需将新数据放入同一张卡中,然后将该卡保存到for循环的当前位置即可。我的猜测是将这张卡片移动到循环内部。
for(lcv; lcv < 52; lcv++){
    BIGNUM *encryptedCard = BN_new();
    BN_bin2bn(deck[lcv],strlen(deck[lcv]),temp);
    BN_mod_exp(encryptedCard,temp,beta,P,ctx);
    printf("ec: %p: %s\n\n",encryptedCard, BN_bn2dec(encryptedCard));
    encryptedDeck[lcv] = encryptedCard;
}

注意:我没有使用这个加密库,所以无法告诉你循环中是否需要相同的局部变量temp,但似乎这可能是你的问题所在。


抱歉,我应该更明确一些。OpenSSL库中的两个函数是for循环中的前两个函数。它们处理从明文牌堆中取出一张牌,将其转换为BIGNUM,加密并存储到另一个BIGNUM中。BN_bin2bn(char* str, strlen(str), BIGNUM whereToStore) 和 BN_mod_exp(BIGNUM result, BIGNUM* a, BIGNUM* p, BIGNUM* m, ctx)因此,mod_exp的第一个参数是改变Card的参数,然后我将其放入数组中。 - AChrapko
@AChrapko 当然,所以打算在牌组的每个位置存储那个指针(相同的指针)吗?我之所以提出这个问题,是因为你提到循环结束后它们都是相同的卡片。检查一下牌组,看看它们是否都是相同的指针,如果是,那可能不正确。(或者,我真的需要走出去,使用openssl而不是BSAFE =))。 - WhozCraig
好的,好的,我知道你在说什么。真正让我困扰的是必须使用BIGNUM结构作为我的数组数据类型。当我第一次看到这篇文章时,我想:“啊,是一个52个char*的数组,memcpy将是我的好朋友”。所以,是的,我认为它们都是同一个指针。那么,在这里,我的memcpy等效操作是什么? - AChrapko
你可以使用BN_copy()来复制BIGNUMs,但是像WhozCraig所说的那样,将创建调用移动到循环内部似乎更容易。 - unwind
啊,是的,那解决了一切。谢谢@WhozCraig。我没有注意到循环内的创建调用不是针对我正在使用的相同指针。我在最初发布时省略了一些代码,并且有一些与标识符过于相似的小测试垃圾。 - AChrapko
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接