ftu/blst/map_to_g2.c
2022-09-09 02:47:49 -04:00

445 lines
19 KiB
C

/*
* Copyright Supranational LLC
* Licensed under the Apache License, Version 2.0, see LICENSE for details.
* SPDX-License-Identifier: Apache-2.0
*/
#include "point.h"
#include "fields.h"
/*
* y^2 = x^3 + A'*x + B', isogenous one
*/
static const vec384x Aprime_E2 = { /* 240*i */
{ 0 },
{ TO_LIMB_T(0xe53a000003135242), TO_LIMB_T(0x01080c0fdef80285),
TO_LIMB_T(0xe7889edbe340f6bd), TO_LIMB_T(0x0b51375126310601),
TO_LIMB_T(0x02d6985717c744ab), TO_LIMB_T(0x1220b4e979ea5467) }
};
static const vec384x Bprime_E2 = { /* 1012 + 1012*i */
{ TO_LIMB_T(0x22ea00000cf89db2), TO_LIMB_T(0x6ec832df71380aa4),
TO_LIMB_T(0x6e1b94403db5a66e), TO_LIMB_T(0x75bf3c53a79473ba),
TO_LIMB_T(0x3dd3a569412c0a34), TO_LIMB_T(0x125cdb5e74dc4fd1) },
{ TO_LIMB_T(0x22ea00000cf89db2), TO_LIMB_T(0x6ec832df71380aa4),
TO_LIMB_T(0x6e1b94403db5a66e), TO_LIMB_T(0x75bf3c53a79473ba),
TO_LIMB_T(0x3dd3a569412c0a34), TO_LIMB_T(0x125cdb5e74dc4fd1) }
};
static void map_fp2_times_Zz(vec384x map[], const vec384x isogeny_map[],
const vec384x Zz_powers[], size_t n)
{
while (n--)
mul_fp2(map[n], isogeny_map[n], Zz_powers[n]);
}
static void map_fp2(vec384x acc, const vec384x x, const vec384x map[], size_t n)
{
while (n--) {
mul_fp2(acc, acc, x);
add_fp2(acc, acc, map[n]);
}
}
static void isogeny_map_to_E2(POINTonE2 *out, const POINTonE2 *p)
{
/*
* x = x_num / x_den, where
* x_num = k_(1,3) * x'^3 + k_(1,2) * x'^2 + k_(1,1) * x' + k_(1,0)
* ...
*/
static const vec384x isogeny_map_x_num[] = { /* (k_(1,*)<<384) % P */
{{ TO_LIMB_T(0x47f671c71ce05e62), TO_LIMB_T(0x06dd57071206393e),
TO_LIMB_T(0x7c80cd2af3fd71a2), TO_LIMB_T(0x048103ea9e6cd062),
TO_LIMB_T(0xc54516acc8d037f6), TO_LIMB_T(0x13808f550920ea41) },
{ TO_LIMB_T(0x47f671c71ce05e62), TO_LIMB_T(0x06dd57071206393e),
TO_LIMB_T(0x7c80cd2af3fd71a2), TO_LIMB_T(0x048103ea9e6cd062),
TO_LIMB_T(0xc54516acc8d037f6), TO_LIMB_T(0x13808f550920ea41) }},
{{ 0 },
{ TO_LIMB_T(0x5fe55555554c71d0), TO_LIMB_T(0x873fffdd236aaaa3),
TO_LIMB_T(0x6a6b4619b26ef918), TO_LIMB_T(0x21c2888408874945),
TO_LIMB_T(0x2836cda7028cabc5), TO_LIMB_T(0x0ac73310a7fd5abd) }},
{{ TO_LIMB_T(0x0a0c5555555971c3), TO_LIMB_T(0xdb0c00101f9eaaae),
TO_LIMB_T(0xb1fb2f941d797997), TO_LIMB_T(0xd3960742ef416e1c),
TO_LIMB_T(0xb70040e2c20556f4), TO_LIMB_T(0x149d7861e581393b) },
{ TO_LIMB_T(0xaff2aaaaaaa638e8), TO_LIMB_T(0x439fffee91b55551),
TO_LIMB_T(0xb535a30cd9377c8c), TO_LIMB_T(0x90e144420443a4a2),
TO_LIMB_T(0x941b66d3814655e2), TO_LIMB_T(0x0563998853fead5e) }},
{{ TO_LIMB_T(0x40aac71c71c725ed), TO_LIMB_T(0x190955557a84e38e),
TO_LIMB_T(0xd817050a8f41abc3), TO_LIMB_T(0xd86485d4c87f6fb1),
TO_LIMB_T(0x696eb479f885d059), TO_LIMB_T(0x198e1a74328002d2) },
{ 0 }}
};
/* ...
* x_den = x'^2 + k_(2,1) * x' + k_(2,0)
*/
static const vec384x isogeny_map_x_den[] = { /* (k_(2,*)<<384) % P */
{{ 0 },
{ TO_LIMB_T(0x1f3affffff13ab97), TO_LIMB_T(0xf25bfc611da3ff3e),
TO_LIMB_T(0xca3757cb3819b208), TO_LIMB_T(0x3e6427366f8cec18),
TO_LIMB_T(0x03977bc86095b089), TO_LIMB_T(0x04f69db13f39a952) }},
{{ TO_LIMB_T(0x447600000027552e), TO_LIMB_T(0xdcb8009a43480020),
TO_LIMB_T(0x6f7ee9ce4a6e8b59), TO_LIMB_T(0xb10330b7c0a95bc6),
TO_LIMB_T(0x6140b1fcfb1e54b7), TO_LIMB_T(0x0381be097f0bb4e1) },
{ TO_LIMB_T(0x7588ffffffd8557d), TO_LIMB_T(0x41f3ff646e0bffdf),
TO_LIMB_T(0xf7b1e8d2ac426aca), TO_LIMB_T(0xb3741acd32dbb6f8),
TO_LIMB_T(0xe9daf5b9482d581f), TO_LIMB_T(0x167f53e0ba7431b8) }}
};
/*
* y = y' * y_num / y_den, where
* y_num = k_(3,3) * x'^3 + k_(3,2) * x'^2 + k_(3,1) * x' + k_(3,0)
* ...
*/
static const vec384x isogeny_map_y_num[] = { /* (k_(3,*)<<384) % P */
{{ TO_LIMB_T(0x96d8f684bdfc77be), TO_LIMB_T(0xb530e4f43b66d0e2),
TO_LIMB_T(0x184a88ff379652fd), TO_LIMB_T(0x57cb23ecfae804e1),
TO_LIMB_T(0x0fd2e39eada3eba9), TO_LIMB_T(0x08c8055e31c5d5c3) },
{ TO_LIMB_T(0x96d8f684bdfc77be), TO_LIMB_T(0xb530e4f43b66d0e2),
TO_LIMB_T(0x184a88ff379652fd), TO_LIMB_T(0x57cb23ecfae804e1),
TO_LIMB_T(0x0fd2e39eada3eba9), TO_LIMB_T(0x08c8055e31c5d5c3) }},
{{ 0 },
{ TO_LIMB_T(0xbf0a71c71c91b406), TO_LIMB_T(0x4d6d55d28b7638fd),
TO_LIMB_T(0x9d82f98e5f205aee), TO_LIMB_T(0xa27aa27b1d1a18d5),
TO_LIMB_T(0x02c3b2b2d2938e86), TO_LIMB_T(0x0c7d13420b09807f) }},
{{ TO_LIMB_T(0xd7f9555555531c74), TO_LIMB_T(0x21cffff748daaaa8),
TO_LIMB_T(0x5a9ad1866c9bbe46), TO_LIMB_T(0x4870a2210221d251),
TO_LIMB_T(0x4a0db369c0a32af1), TO_LIMB_T(0x02b1ccc429ff56af) },
{ TO_LIMB_T(0xe205aaaaaaac8e37), TO_LIMB_T(0xfcdc000768795556),
TO_LIMB_T(0x0c96011a8a1537dd), TO_LIMB_T(0x1c06a963f163406e),
TO_LIMB_T(0x010df44c82a881e6), TO_LIMB_T(0x174f45260f808feb) }},
{{ TO_LIMB_T(0xa470bda12f67f35c), TO_LIMB_T(0xc0fe38e23327b425),
TO_LIMB_T(0xc9d3d0f2c6f0678d), TO_LIMB_T(0x1c55c9935b5a982e),
TO_LIMB_T(0x27f6c0e2f0746764), TO_LIMB_T(0x117c5e6e28aa9054) },
{ 0 }}
};
/* ...
* y_den = x'^3 + k_(4,2) * x'^2 + k_(4,1) * x' + k_(4,0)
*/
static const vec384x isogeny_map_y_den[] = { /* (k_(4,*)<<384) % P */
{{ TO_LIMB_T(0x0162fffffa765adf), TO_LIMB_T(0x8f7bea480083fb75),
TO_LIMB_T(0x561b3c2259e93611), TO_LIMB_T(0x11e19fc1a9c875d5),
TO_LIMB_T(0xca713efc00367660), TO_LIMB_T(0x03c6a03d41da1151) },
{ TO_LIMB_T(0x0162fffffa765adf), TO_LIMB_T(0x8f7bea480083fb75),
TO_LIMB_T(0x561b3c2259e93611), TO_LIMB_T(0x11e19fc1a9c875d5),
TO_LIMB_T(0xca713efc00367660), TO_LIMB_T(0x03c6a03d41da1151) }},
{{ 0 },
{ TO_LIMB_T(0x5db0fffffd3b02c5), TO_LIMB_T(0xd713f52358ebfdba),
TO_LIMB_T(0x5ea60761a84d161a), TO_LIMB_T(0xbb2c75a34ea6c44a),
TO_LIMB_T(0x0ac6735921c1119b), TO_LIMB_T(0x0ee3d913bdacfbf6) }},
{{ TO_LIMB_T(0x66b10000003affc5), TO_LIMB_T(0xcb1400e764ec0030),
TO_LIMB_T(0xa73e5eb56fa5d106), TO_LIMB_T(0x8984c913a0fe09a9),
TO_LIMB_T(0x11e10afb78ad7f13), TO_LIMB_T(0x05429d0e3e918f52) },
{ TO_LIMB_T(0x534dffffffc4aae6), TO_LIMB_T(0x5397ff174c67ffcf),
TO_LIMB_T(0xbff273eb870b251d), TO_LIMB_T(0xdaf2827152870915),
TO_LIMB_T(0x393a9cbaca9e2dc3), TO_LIMB_T(0x14be74dbfaee5748) }}
};
vec384x Zz_powers[3], map[3], xn, xd, yn, yd;
/* lay down Z^2 powers in descending order */
sqr_fp2(Zz_powers[2], p->Z); /* ZZ^1 */
sqr_fp2(Zz_powers[1], Zz_powers[2]); /* ZZ^2 1+1 */
mul_fp2(Zz_powers[0], Zz_powers[2], Zz_powers[1]); /* ZZ^3 2+1 */
map_fp2_times_Zz(map, isogeny_map_x_num, Zz_powers, 3);
mul_fp2(xn, p->X, isogeny_map_x_num[3]);
add_fp2(xn, xn, map[2]);
map_fp2(xn, p->X, map, 2);
map_fp2_times_Zz(map, isogeny_map_x_den, Zz_powers + 1, 2);
add_fp2(xd, p->X, map[1]);
map_fp2(xd, p->X, map, 1);
mul_fp2(xd, xd, Zz_powers[2]); /* xd *= Z^2 */
map_fp2_times_Zz(map, isogeny_map_y_num, Zz_powers, 3);
mul_fp2(yn, p->X, isogeny_map_y_num[3]);
add_fp2(yn, yn, map[2]);
map_fp2(yn, p->X, map, 2);
mul_fp2(yn, yn, p->Y); /* yn *= Y */
map_fp2_times_Zz(map, isogeny_map_y_den, Zz_powers, 3);
add_fp2(yd, p->X, map[2]);
map_fp2(yd, p->X, map, 2);
mul_fp2(Zz_powers[2], Zz_powers[2], p->Z);
mul_fp2(yd, yd, Zz_powers[2]); /* yd *= Z^3 */
/* convert (xn, xd, yn, yd) to Jacobian coordinates */
mul_fp2(out->Z, xd, yd); /* Z = xd * yd */
mul_fp2(out->X, xn, yd);
mul_fp2(out->X, out->X, out->Z); /* X = xn * xd * yd^2 */
sqr_fp2(out->Y, out->Z);
mul_fp2(out->Y, out->Y, xd);
mul_fp2(out->Y, out->Y, yn); /* Y = yn * xd^3 * yd^2 */
}
static void map_to_isogenous_E2(POINTonE2 *p, const vec384x u)
{
static const vec384x minus_A = {
{ 0 },
{ TO_LIMB_T(0xd4c4fffffcec5869), TO_LIMB_T(0x1da3f3eed25bfd79),
TO_LIMB_T(0x7fa833c5136fff67), TO_LIMB_T(0x59261433cd540cbd),
TO_LIMB_T(0x48450f5f2b84682c), TO_LIMB_T(0x07e05d00bf959233) }
};
static const vec384x Z = { /* -2 - i */
{ TO_LIMB_T(0x87ebfffffff9555c), TO_LIMB_T(0x656fffe5da8ffffa),
TO_LIMB_T(0x0fd0749345d33ad2), TO_LIMB_T(0xd951e663066576f4),
TO_LIMB_T(0xde291a3d41e980d3), TO_LIMB_T(0x0815664c7dfe040d) },
{ TO_LIMB_T(0x43f5fffffffcaaae), TO_LIMB_T(0x32b7fff2ed47fffd),
TO_LIMB_T(0x07e83a49a2e99d69), TO_LIMB_T(0xeca8f3318332bb7a),
TO_LIMB_T(0xef148d1ea0f4c069), TO_LIMB_T(0x040ab3263eff0206) }
};
static const vec384x recip_ZZZ = { /* 1/(Z^3) */
{ TO_LIMB_T(0x65018f5c28f598eb), TO_LIMB_T(0xe6020417f022d916),
TO_LIMB_T(0xd6327313288369c7), TO_LIMB_T(0x622ded8eb447156f),
TO_LIMB_T(0xe52a2aee72c2a01f), TO_LIMB_T(0x089812fb8481ffe4) },
{ TO_LIMB_T(0x2574eb851eb8619f), TO_LIMB_T(0xdba2e97912925604),
TO_LIMB_T(0x67e495a909e7a18e), TO_LIMB_T(0xdf2da23b8145b8f7),
TO_LIMB_T(0xcf5d3728310ebf6d), TO_LIMB_T(0x11be446236f4c116) }
};
static const vec384x magic_ZZZ = { /* 1/Z^3 = a + b*i */
/* a^2 + b^2 */
{ TO_LIMB_T(0xaa7eb851eb8508e0), TO_LIMB_T(0x1c54fdf360989374),
TO_LIMB_T(0xc87f2fc6e716c62e), TO_LIMB_T(0x0124aefb1f9efea7),
TO_LIMB_T(0xb2f8be63e844865c), TO_LIMB_T(0x08b47f775a7ef35a) },
/* (a^2 + b^2)^((P-3)/4) */
{ TO_LIMB_T(0xe4132bbd838cf70a), TO_LIMB_T(0x01d769ac83772c19),
TO_LIMB_T(0xa83dd6e974c22e45), TO_LIMB_T(0xbc8ec3e777b08dff),
TO_LIMB_T(0xc035c2042ecf5da3), TO_LIMB_T(0x073929e97f0850bf) }
};
static const vec384x ZxA = { /* 240 - 480*i */
{ TO_LIMB_T(0xe53a000003135242), TO_LIMB_T(0x01080c0fdef80285),
TO_LIMB_T(0xe7889edbe340f6bd), TO_LIMB_T(0x0b51375126310601),
TO_LIMB_T(0x02d6985717c744ab), TO_LIMB_T(0x1220b4e979ea5467) },
{ TO_LIMB_T(0xa989fffff9d8b0d2), TO_LIMB_T(0x3b47e7dda4b7faf3),
TO_LIMB_T(0xff50678a26dffece), TO_LIMB_T(0xb24c28679aa8197a),
TO_LIMB_T(0x908a1ebe5708d058), TO_LIMB_T(0x0fc0ba017f2b2466) }
};
vec384x uu, tv2, tv4, x2n, gx1, gxd, y2;
#if 0
vec384x xn, x1n, xd, y, y1, Zuu;
#else
# define xn p->X
# define y p->Y
# define xd p->Z
# define x1n xn
# define y1 y
# define Zuu x2n
#endif
#define sgn0_fp2(a) (sgn0_pty_mont_384x((a), BLS12_381_P, p0) & 1)
bool_t e1, e2;
/*
* as per map_to_curve() from poc/sswu_opt.sage at
* https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve
* with 9mod16 twists...
*/
/* x numerator variants */
sqr_fp2(uu, u); /* uu = u^2 */
mul_fp2(Zuu, Z, uu); /* Zuu = Z * uu */
sqr_fp2(tv2, Zuu); /* tv2 = Zuu^2 */
add_fp2(tv2, tv2, Zuu); /* tv2 = tv2 + Zuu */
add_fp2(x1n, tv2, BLS12_381_Rx.p2); /* x1n = tv2 + 1 */
mul_fp2(x1n, x1n, Bprime_E2); /* x1n = x1n * B */
mul_fp2(x2n, Zuu, x1n); /* x2n = Zuu * x1n */
/* x denumenator */
mul_fp2(xd, minus_A, tv2); /* xd = -A * tv2 */
e1 = vec_is_zero(xd, sizeof(xd)); /* e1 = xd == 0 */
vec_select(xd, ZxA, xd, sizeof(xd), e1); /* # If xd == 0, set xd = Z*A */
/* y numerators variants */
sqr_fp2(tv2, xd); /* tv2 = xd^2 */
mul_fp2(gxd, xd, tv2); /* gxd = xd^3 */
mul_fp2(tv2, Aprime_E2, tv2); /* tv2 = A * tv2 */
sqr_fp2(gx1, x1n); /* gx1 = x1n^2 */
add_fp2(gx1, gx1, tv2); /* gx1 = gx1 + tv2 # x1n^2 + A*xd^2 */
mul_fp2(gx1, gx1, x1n); /* gx1 = gx1 * x1n # x1n^3 + A*x1n*xd^2 */
mul_fp2(tv2, Bprime_E2, gxd); /* tv2 = B * gxd */
add_fp2(gx1, gx1, tv2); /* gx1 = gx1 + tv2 # x1^3 + A*x1*xd^2 + B*xd^3 */
sqr_fp2(tv4, gxd); /* tv4 = gxd^2 */
mul_fp2(tv2, gx1, gxd); /* tv2 = gx1 * gxd */
mul_fp2(tv4, tv4, tv2); /* tv4 = tv4 * tv2 # gx1*gxd^3 */
e2 = recip_sqrt_fp2(y1, tv4, /* y1 = tv4^c1 # (gx1*gxd^3)^((p^2-9)/16) */
recip_ZZZ, magic_ZZZ);
mul_fp2(y1, y1, tv2); /* y1 = y1 * tv2 # gx1*gxd*y1 */
mul_fp2(y2, y1, uu); /* y2 = y1 * uu */
mul_fp2(y2, y2, u); /* y2 = y2 * u */
/* choose numerators */
vec_select(xn, x1n, x2n, sizeof(xn), e2); /* xn = e2 ? x1n : x2n */
vec_select(y, y1, y2, sizeof(y), e2); /* y = e2 ? y1 : y2 */
e1 = sgn0_fp2(u);
e2 = sgn0_fp2(y);
cneg_fp2(y, y, e1^e2); /* fix sign of y */
/* return (xn, xd, y, 1) */
/* convert (xn, xd, y, 1) to Jacobian projective coordinates */
mul_fp2(p->X, xn, xd); /* X = xn * xd */
mul_fp2(p->Y, y, gxd); /* Y = y * xd^3 */
#ifndef xd
vec_copy(p->Z, xd, sizeof(xd)); /* Z = xd */
#else
# undef xn
# undef y
# undef xd
# undef x1n
# undef y1
# undef Zuu
# undef tv4
#endif
#undef sgn0_fp2
}
#if 0
static const byte h_eff[] = {
TO_BYTES(0xe8020005aaa95551), TO_BYTES(0x59894c0adebbf6b4),
TO_BYTES(0xe954cbc06689f6a3), TO_BYTES(0x2ec0ec69d7477c1a),
TO_BYTES(0x6d82bf015d1212b0), TO_BYTES(0x329c2f178731db95),
TO_BYTES(0x9986ff031508ffe1), TO_BYTES(0x88e2a8e9145ad768),
TO_BYTES(0x584c6a0ea91b3528), TO_BYTES(0x0bc69f08f2ee75b3)
};
static void clear_cofactor(POINTonE2 *out, const POINTonE2 *p)
{ POINTonE2_mult_w5(out, p, h_eff, 636); }
#else
/*
* As per suggestions in "7. Clearing the cofactor" at
* https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06
*/
static void POINTonE2_add_n_dbl(POINTonE2 *out, const POINTonE2 *p, size_t n)
{
POINTonE2_dadd(out, out, p, NULL);
while(n--)
POINTonE2_double(out, out);
}
static void POINTonE2_times_minus_z(POINTonE2 *out, const POINTonE2 *in)
{
POINTonE2_double(out, in); /* 1: 0x2 */
POINTonE2_add_n_dbl(out, in, 2); /* 2..4: 0x3..0xc */
POINTonE2_add_n_dbl(out, in, 3); /* 5..8: 0xd..0x68 */
POINTonE2_add_n_dbl(out, in, 9); /* 9..18: 0x69..0xd200 */
POINTonE2_add_n_dbl(out, in, 32); /* 19..51: ..0xd20100000000 */
POINTonE2_add_n_dbl(out, in, 16); /* 52..68: ..0xd201000000010000 */
}
static void psi(POINTonE2 *out, const POINTonE2 *in);
static void clear_cofactor(POINTonE2 *out, const POINTonE2 *p)
{
POINTonE2 t0, t1;
/* A.Budroni, F.Pintore, "Efficient hash maps to G2 on BLS curves" */
POINTonE2_double(out, p); /* out = 2P */
psi(out, out); /* out = Ψ(2P) */
psi(out, out); /* out = Ψ²(2P) */
vec_copy(&t0, p, sizeof(t0));
POINTonE2_cneg(&t0, 1); /* t0 = -P */
psi(&t1, &t0); /* t1 = -Ψ(P) */
POINTonE2_dadd(out, out, &t0, NULL);/* out = Ψ²(2P) - P */
POINTonE2_dadd(out, out, &t1, NULL);/* out = Ψ²(2P) - P - Ψ(P) */
POINTonE2_times_minus_z(&t0, p); /* t0 = [-z]P */
POINTonE2_dadd(&t0, &t0, p, NULL); /* t0 = [-z + 1]P */
POINTonE2_dadd(&t0, &t0, &t1, NULL);/* t0 = [-z + 1]P - Ψ(P) */
POINTonE2_times_minus_z(&t1, &t0); /* t1 = [z² - z]P + [z]Ψ(P) */
POINTonE2_dadd(out, out, &t1, NULL);/* out = [z² - z - 1]P */
/* + [z - 1]Ψ(P) */
/* + Ψ²(2P) */
}
#endif
/*
* |u|, |v| are expected to be in Montgomery representation
*/
static void map_to_g2(POINTonE2 *out, const vec384x u, const vec384x v)
{
POINTonE2 p;
map_to_isogenous_E2(&p, u);
if (v != NULL) {
map_to_isogenous_E2(out, v); /* borrow |out| */
POINTonE2_dadd(&p, &p, out, Aprime_E2);
}
isogeny_map_to_E2(&p, &p); /* sprinkle isogenous powder */
clear_cofactor(out, &p);
}
void blst_map_to_g2(POINTonE2 *out, const vec384x u, const vec384x v)
{ map_to_g2(out, u, v); }
static void Encode_to_G2(POINTonE2 *p, const unsigned char *msg, size_t msg_len,
const unsigned char *DST, size_t DST_len,
const unsigned char *aug, size_t aug_len)
{
vec384x u[1];
hash_to_field(u[0], 2, aug, aug_len, msg, msg_len, DST, DST_len);
map_to_g2(p, u[0], NULL);
}
void blst_encode_to_g2(POINTonE2 *p, const unsigned char *msg, size_t msg_len,
const unsigned char *DST, size_t DST_len,
const unsigned char *aug, size_t aug_len)
{ Encode_to_G2(p, msg, msg_len, DST, DST_len, aug, aug_len); }
static void Hash_to_G2(POINTonE2 *p, const unsigned char *msg, size_t msg_len,
const unsigned char *DST, size_t DST_len,
const unsigned char *aug, size_t aug_len)
{
vec384x u[2];
hash_to_field(u[0], 4, aug, aug_len, msg, msg_len, DST, DST_len);
map_to_g2(p, u[0], u[1]);
}
void blst_hash_to_g2(POINTonE2 *p, const unsigned char *msg, size_t msg_len,
const unsigned char *DST, size_t DST_len,
const unsigned char *aug, size_t aug_len)
{ Hash_to_G2(p, msg, msg_len, DST, DST_len, aug, aug_len); }
static bool_t POINTonE2_in_G2(const POINTonE2 *P)
{
#if 0
POINTonE2 t0, t1, t2;
/* Bowe, S., "Faster subgroup checks for BLS12-381" */
psi(&t0, P); /* Ψ(P) */
psi(&t0, &t0); /* Ψ²(P) */
psi(&t1, &t0); /* Ψ³(P) */
POINTonE2_times_minus_z(&t2, &t1);
POINTonE2_dadd(&t0, &t0, &t2, NULL);
POINTonE2_cneg(&t0, 1);
POINTonE2_dadd(&t0, &t0, P, NULL); /* [z]Ψ³(P) - Ψ²(P) + P */
return vec_is_zero(t0.Z, sizeof(t0.Z));
#else
POINTonE2 t0, t1;
/* Scott, M., https://eprint.iacr.org/2021/1130 */
psi(&t0, P); /* Ψ(P) */
POINTonE2_times_minus_z(&t1, P);
POINTonE2_cneg(&t1, 1); /* [z]P */
return POINTonE2_is_equal(&t0, &t1);
#endif
}
int blst_p2_in_g2(const POINTonE2 *p)
{ return (int)POINTonE2_in_G2(p); }
int blst_p2_affine_in_g2(const POINTonE2_affine *p)
{
POINTonE2 P;
vec_copy(P.X, p->X, 2*sizeof(P.X));
vec_select(P.Z, p->X, BLS12_381_Rx.p, sizeof(P.Z),
vec_is_zero(p, sizeof(*p)));
return (int)POINTonE2_in_G2(&P);
}