randombit / botan

Cryptography Toolkit

Home Page:https://botan.randombit.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

secp112r2 blinded_var_point_multiply incorrect result

guidovranken opened this issue · comments

#include <botan/system_rng.h>
#include <botan/ecdsa.h>
#include <iostream>
#include <vector>

int main(void)
{
    Botan::System_RNG rng;

    const Botan::BigInt P("4451685225093714772084598273548427");

    {
        const Botan::OID secp112r2_oid("1.3.132.0.7");
        const Botan::EC_Group secp112r2(
                P,
                Botan::BigInt("1970543761890640310119143205433388"),
                Botan::BigInt("1660538572255285715897238774208265"),
                Botan::BigInt("1534098225527667214992304222930499"),
                Botan::BigInt("3525120595527770847583704454622871"),
                Botan::BigInt("1112921306273428674967732714786891"),
                4,
                secp112r2_oid);
        Botan::OID::register_oid(secp112r2_oid, "secp112r2");

        if ( !secp112r2.verify_group(rng) ) {
            abort();
        }
    }

    Botan::EC_Group group("secp112r2");

    const Botan::BigInt x("3225931648031205307486810278534413");
    const Botan::BigInt y("1220423137799363804926043977846677");
    const Botan::BigInt scalar("10000000600000379007");

    const Botan::PointGFp point = group.point(x, y);

    std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
    const Botan::PointGFp res =  group.blinded_var_point_multiply(point, scalar, rng, ws);

    /* Regular scalar multiplication */
    //const Botan::PointGFp res = point * scalar;

    std::cout << res.get_affine_x().to_dec_string() << std::endl;
    std::cout << res.get_affine_y().to_dec_string() << std::endl;

    return 0;
}

This will sometimes print:

2197327064432923199574773159375907
1438700446997857257741718818607422

but it should print:

1054952879406896583239639924747045
2135042385550538484966259261096670

Maybe secp112r2/custom curves are not compatible with blinded_var_point_multiply? Though ideally it should throw an exception then.

I suppose this is related to #3723. But should a point being part of the prime order
subgroup be a requisite for correct multiplication?

I think mathematically multiplication with a torsion factor (ie a point that is outside the prime order subgroup) is well defined, but we likely assume that the points order is exactly that of the subgroup.

Specifically, for this routine we actually perform a multiplication of p*x by computing p*(x + m * r) where m is a random integer and r is the prime order subgroup. If p is of order r (== is in the prime subgroup) then p * (m * r) is just the identity element. But if p is not of order r then I'd imagine we could get different results, depending on what is chosen for m.

What other implementations are you testing that produce a consistent result here?

OpenSSL, wolfSSL, libecc, Crypto++ as well as Botan's regular scalar multiplication (* operator) seem to produce consistent results.

PS: secp112r2 and secp128r2 have special points which cause Botan to throw Botan::Invalid_State from blinded_var_point_multiply. This isn't really a bug since the input point is technically invalid but it might be useful to integrate these points into the tests.

The points:

X = 3610075134545239076002374364665933, Y = 0 for secp112r2
X = 311198077076599516590082177721943503641, Y = 0 secp128r2

More information here: https://github.com/libecc/libecc/blob/b9329e2826f4d622dbb9ffdd9316e98fda7a023f/src/curves/prj_pt.c#L1038

Hi,

Actually regarding the blinding of composite points (i.e. points that are not in the prime order subgroup), the order of the curve must be used and not the prime order (as indeed as pointed by @randombit the scalar multiplication by this prime order will not be the identity).

libecc performs such blinding with the explanation here: https://github.com/libecc/libecc/blob/b9329e2826f4d622dbb9ffdd9316e98fda7a023f/src/curves/prj_pt.c#L1784

Regards,

commented

What's the value of supporting such curves? They're too big for toy problems that you'd give students, and too weak cryptographically to be of practical use.

These curves can indeed be considered weak, but other curves with non 1 cofactors such as Wei25519 or Wei448 will exhibit the same issue while being considered "secure".

@guidovranken Should be fixed now, I'll leave this open until you can confirm.

Confirmed fixed.