Обмен секретами Шамира и интерполяция Лагранжа (OpenSSL BIGNUM)

Я уже публиковал подобные вопросы, поэтому заранее извиняюсь, но я просто не могу найти, где я ошибаюсь.

Я реализую обмен секретами Shamir, используя библиотеку OpenSSL BIGNUM на языке C.

После того, как я сделаю раунд интерполяции Лагранжа, я умножу key * numerator, а затем мне нужно разделить на знаменатель.

Поскольку функции BN_mod_div нет, вместо этого я использую BN_mod_inverse() в знаменателе, а затем умножаю, например:

(key * numerator) * (inverse of denominator)

Я заметил, что если я использую BN_mod_inverse(denom, denom, q, ctx);, то значение, которое должно быть инвертировано, остается прежним:

Round Key: 2E
Numerator: 14
Denominator: 6  **<---- ORIGINAL DENOMINATOR**
Multiply key with numerator: 398 (POSITIVE)
Invert Denominator: 6 (POSITIVE) **<---------- INVERSE IS THE SAME???**
(Key*Numerator)*inv.Denom: 3FC (POSITIVE)

Round Key: 562
Numerator: A
Denominator: -2
Multiply key with numerator: 118 (POSITIVE)
Invert Denominator: -2 (NEGATIVE)
(Key*Numerator)*inv.Denom: 3AC (POSITIVE)

Round Key: 5D1
Numerator: 8
Denominator: 3
Multiply key with numerator: 584 (POSITIVE)
Invert Denominator: 3 (POSITIVE)
(Key*Numerator)*inv.Denom: 4D4 (POSITIVE)
Recovered Key: C4 (POSITIVE)
Key should = 4D2

Если я изменю это на BN_mod_inverse(newBN, denom, q, ctx);, оно просто превратится в ноль:

Round Key: 2E
Numerator: 14
Denominator: 6 **<---- ORIGINAL DENOMINATOR**
Multiply key with numerator: 398 (POSITIVE)
Invert Denominator: 0 (NEGATIVE)  **<------------ DENOMINATOR IS NOW ZERO??**
(Key*Numerator)*inv.Denom: 0 (NEGATIVE)

Round Key: 562
Numerator: A
Denominator: -2
Multiply key with numerator: 118 (POSITIVE)
Invert Denominator: 0 (NEGATIVE)
(Key*Numerator)*inv.Denom: 0 (NEGATIVE)

Round Key: 5D1
Numerator: 8
Denominator: 3
Multiply key with numerator: 584 (POSITIVE)
Invert Denominator: 0 (NEGATIVE)
(Key*Numerator)*inv.Denom: 0 (NEGATIVE)
Recovered Key: 0 (NEGATIVE)
Key should = 4D2

В любом случае комбинированный ключ неверен. Что тут происходит? Есть ли обходной путь для этого?

Вот мой код:

BIGNUM *int2BN(int i)
{   
    BIGNUM *tmp = BN_new();
    BN_zero(tmp);

    int g;
    if(i < 0) { //If 'i' is negative
        for (g = 0; g > i; g--) {
            BN_sub(tmp, tmp, one);
        }
    } else { //If 'i' is positive
        for (g = 0; g < i; g++) {
            BN_add(tmp, tmp, one);
        }
    }
    return(tmp);
}   

static void
blah() {
int denomTmp, numTmp, numAccum, denomAccum;
int s, j;   
BIGNUM *accum[3], *bnNum, *bnDenom;
bnNum = BN_new();
bnDenom = BN_new();

/* Lagrange Interpolation */
for (s = 0; s < 3; s++) {
    numAccum = 1;
    denomAccum = 1;
    for (j = 0; j < 3; j++) {
        if(s == j) continue;
        else {
            /* 0 - i[k] = numTmp */
            numTmp = 0 - key[j].keynum;

            /* share - i[k] = denomTmp */
            denomTmp = key[s].keynum - key[j].keynum;

            /* Numerator accumulation: */
            numAccum *= numTmp;

            /* Denominator accumulation: */
            denomAccum *= denomTmp;
        }
    }
    accum[s] = BN_new();
    bnNum = int2BN(numAccum);
    bnDenom = int2BN(denomAccum);

    /* Multiply result by share */
    BN_mod_mul(accum[s], key[s].key, bnNum, q, ctx);

    /* Invert denominator */
    BN_mod_inverse(bnDenom, bnDenom, q, ctx);

    /* Multiply by inverted denominator */
    BN_mod_mul(accum[s], accum[s], bnDenom, q, ctx);

}

int a;
BIGNUM *total = BN_new();
BN_zero(total);
for(a = 0; a < 3; a++) { 
    BN_mod_add(total, total, accum[a], q, ctx);
}   

}

person Chris C    schedule 14.02.2013    source источник
comment
Это как если бы вы показывали нам результат работы программы — но не саму программу — и задавали нам вопросы о ней. Но это невозможно, не так ли? Все, что я могу сделать, это предложить вам изучить документы для BN_mod_inverse.   -  person President James K. Polk    schedule 15.02.2013
comment
Мой вопрос был более широким: может ли mod_inverse обрабатывать небольшие и/или отрицательные значения? (что не распространяется в документации), но я не совсем ясно это объяснил. Вставляю свой источник.   -  person Chris C    schedule 15.02.2013
comment
Где вы установили свой модуль q? Верно ли значение? Вы уже решили эту проблему?   -  person Chiara Hsieh    schedule 06.05.2013


Ответы (1)


Используйте 1_. Остаток по модулю. То есть rem = a % d.

int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, const BIGNUM *d, BN_CTX *ctx);

BN_div() divides a by d and places the result in dv and the remainder in rem
(dv=a/d, rem=a%d). Either of dv and rem may be NULL, in which case the respective
value is not returned. The result is rounded towards zero; thus if a is negative,
the remainder will be zero or negative. For division by powers of 2, use
BN_rshift(3). 
person jww    schedule 02.10.2013