Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

secp112r2 blinded_var_point_multiply incorrect result #3800

Closed
guidovranken opened this issue Nov 5, 2023 · 8 comments
Closed

secp112r2 blinded_var_point_multiply incorrect result #3800

guidovranken opened this issue Nov 5, 2023 · 8 comments

Comments

@guidovranken
Copy link

#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.

@guidovranken
Copy link
Author

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

@randombit
Copy link
Owner

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?

@guidovranken
Copy link
Author

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

@rben-dev
Copy link

rben-dev commented Nov 7, 2023

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,

@mouse07410
Copy link
Contributor

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.

@rben-dev
Copy link

rben-dev commented Nov 7, 2023

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".

randombit added a commit that referenced this issue Nov 7, 2023
This only matters in the case of performing a multiplication in
a curve that has a cofactor and the point is not in the prime order
subgroup.

See GH #3800
randombit added a commit that referenced this issue Nov 7, 2023
This only matters in the case of performing a multiplication in
a curve that has a cofactor and the point is not in the prime order
subgroup.

See GH #3800
@randombit
Copy link
Owner

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

@guidovranken
Copy link
Author

Confirmed fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants