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

Add sm2p256v1 pcurves optimizations #4240

Merged
merged 3 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 135 additions & 4 deletions src/lib/math/pcurves/pcurves_sm2p256v1/pcurves_sm2p256v1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,108 @@

#include <botan/internal/pcurves_instance.h>

#include <botan/internal/pcurves_solinas.h>
#include <botan/internal/pcurves_wrap.h>

namespace Botan::PCurve {

namespace {

// clang-format off
namespace sm2p256v1 {

template <typename Params>
class Sm2p256v1Rep final {
public:
static constexpr auto P = Params::P;
static constexpr size_t N = Params::N;
typedef typename Params::W W;

constexpr static std::array<W, N> redc(const std::array<W, 2 * N>& z) {
const int64_t X00 = get_uint32(z.data(), 0);
const int64_t X01 = get_uint32(z.data(), 1);
const int64_t X02 = get_uint32(z.data(), 2);
const int64_t X03 = get_uint32(z.data(), 3);
const int64_t X04 = get_uint32(z.data(), 4);
const int64_t X05 = get_uint32(z.data(), 5);
const int64_t X06 = get_uint32(z.data(), 6);
const int64_t X07 = get_uint32(z.data(), 7);
const int64_t X08 = get_uint32(z.data(), 8);
const int64_t X09 = get_uint32(z.data(), 9);
const int64_t X10 = get_uint32(z.data(), 10);
const int64_t X11 = get_uint32(z.data(), 11);
const int64_t X12 = get_uint32(z.data(), 12);
const int64_t X13 = get_uint32(z.data(), 13);
const int64_t X14 = get_uint32(z.data(), 14);
const int64_t X15 = get_uint32(z.data(), 15);

const int64_t S0 = X00 + X08 + X09 + X10 + X11 + X12 + 2 * (X13 + X14 + X15);
const int64_t S1 = X01 + X09 + X10 + X11 + X12 + X13 + 2 * (X14 + X15);
const int64_t S2 = X02 - (X08 + X09 + X13 + X14);
const int64_t S3 = X03 + X08 + X11 + X12 + 2 * X13 + X14 + X15;
const int64_t S4 = X04 + X09 + X12 + X13 + 2 * X14 + X15;
const int64_t S5 = X05 + X10 + X13 + X14 + 2 * X15;
const int64_t S6 = X06 + X11 + X14 + X15;
const int64_t S7 = X07 + X08 + X09 + X10 + X11 + 2 * (X12 + X13 + X14 + X15) + X15;

std::array<W, N> r = {};

SolinasAccum sum(r);

sum.accum(S0);
sum.accum(S1);
sum.accum(S2);
sum.accum(S3);
sum.accum(S4);
sum.accum(S5);
sum.accum(S6);
sum.accum(S7);
const auto S = sum.final_carry(0);

const auto correction = sm2_mul_mod_256(S);
W borrow = bigint_sub2(r.data(), N, correction.data(), N);

bigint_cnd_add(borrow, r.data(), N, P.data(), N);

return r;
}

constexpr static std::array<W, N> one() { return std::array<W, N>{1}; }

constexpr static std::array<W, N> to_rep(const std::array<W, N>& x) { return x; }

constexpr static std::array<W, N> wide_to_rep(const std::array<W, 2 * N>& x) { return redc(x); }

constexpr static std::array<W, N> from_rep(const std::array<W, N>& z) { return z; }

private:
// Return (i*P) % 2**256
//
// Assumes i is small
constexpr static std::array<W, N> sm2_mul_mod_256(W i) {
static_assert(WordInfo<W>::bits == 32 || WordInfo<W>::bits == 64);

// For small i, multiples of P have a simple structure so it's faster to
// compute the value directly vs a (constant time) table lookup

auto r = P;
if constexpr(WordInfo<W>::bits == 32) {
r[7] -= i;
r[3] -= i;
r[2] += i;
r[0] -= i;
} else {
const uint64_t i32 = static_cast<uint64_t>(i) << 32;
r[3] -= i32;
r[1] -= i32;
r[1] += i;
r[0] -= i;
}
return r;
}
};

// clang-format off

class Params final : public EllipticCurveParameters<
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
Expand All @@ -24,11 +117,49 @@ class Params final : public EllipticCurveParameters<
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"> {
};

class Curve final : public EllipticCurve<Params> {};
// clang-format on

}
class Curve final : public EllipticCurve<Params, Sm2p256v1Rep> {
public:
// Return the square of the inverse of x
static FieldElement fe_invert2(const FieldElement& x) {
// Generated by https://github.com/mmcloughlin/addchain
auto z = x.square();
auto t0 = x * z;
z = t0.square();
z *= x;
auto t1 = z;
t1.square_n(3);
t1 *= z;
auto t2 = t1.square();
z = t2 * x;
t2.square_n(5);
t1 *= t2;
t2 = t1;
t2.square_n(12);
t1 *= t2;
t1.square_n(7);
z *= t1;
t2 = z;
t2.square_n(2);
t1 = t2;
t1.square_n(29);
z *= t1;
t1.square_n(2);
t2 *= t1;
t0 *= t2;
t1.square_n(32);
t1 *= t0;
t1.square_n(64);
t0 *= t1;
t0.square_n(94);
z *= t0;
z.square_n(2);
return z;
}
};

// clang-format on
} // namespace sm2p256v1

} // namespace

Expand Down
194 changes: 194 additions & 0 deletions src/tests/data/pubkey/ecc_base_point_mul.vec
Original file line number Diff line number Diff line change
Expand Up @@ -1136,3 +1136,197 @@ P = 048EB2D128495074CC7149E19DB2A5CA5A04960EC735A8A6FB77EBC74B2A6BBBD5E623CA71BF

k = 770D841A416DDE3072ED0CE570BFF4065643DFF53C4ED38809100EFE479F46D1
P = 04891DC951F8F41D80A124A6675058D305BB97F70E3BB2C13BA8056EDD15323006428DF0068E6BB7DF3B03AA7765B45422995F9AEE89CA2CA1EC400B99A4C331EC

[sm2p256v1]

k = 0000000000000000000000000000000000000000000000000000000000000001
P = 0432C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0

k = 0000000000000000000000000000000000000000000000000000000000000002
P = 0456CEFD60D7C87C000D58EF57FA73BA4D9C0DFA08C08A7331495C2E1DA3F2BD5231B7E7E6CC8189F668535CE0F8EAF1BD6DE84C182F6C8E716F780D3A970A23C3

k = 0000000000000000000000000000000000000000000000000000000000000003
P = 04A97F7CD4B3C993B4BE2DAA8CDB41E24CA13F6BD945302244E26918F1D0509EBF530B5DD88C688EF5CCC5CEC08A72150F7C400EE5CD045292AAACDD037458F6E6

k = 0000000000000000000000000000000000000000000000000000000000000004
P = 04C239507105C683242A81052FF641ED69009A084AD5CC937DB21646CD34A0CED5B1BF7EC4080F3C8735F1294AC0DB19686BEE2E96AB8C71FB7A253666CB66E009

k = 0000000000000000000000000000000000000000000000000000000000000005
P = 04C749061668652E26040E008FDD5EB77A344A417B7FCE19DBA575DA57CC372A9EF2DF5DB2D144E9454504C622B51CF38F5006206EB579FF7DA6976EFF5FBE6480

k = 0000000000000000000000000000000000000000000000000000000000000006
P = 040927AFB57D93483BBB17C93E71F22A3105FF8856A66016892C8B1A1A3C4B0D30150C6B1AB4D1FC7EAC1C0EF6EBF2664581ADF1F0855A064DD572103000088F63

k = 0000000000000000000000000000000000000000000000000000000000000007
P = 04DDF092555409C19DFDBE86A75C139906A80198337744EE78CD27E384D9FCAF15847D18FFB38E87065CD6B6E9C12D2922037937707D6A49A2223B949657E52BC1

k = 0000000000000000000000000000000000000000000000000000000000000008
P = 04B9C3FAEB4B1610713DB4333D4E860E64D4EA35D60C1C29BB675D822DED0BB916C519B309ECF7269C2491D2DE9ACCF2BE0366A8A03024B3E03C286DA2CFD31A3E

k = 0000000000000000000000000000000000000000000000000000000000000009
P = 04A27233F3A59595080B4A2444A46A74C5FE8D59CB43619E4F173472A58CCA247E379E72F63722C924768F7689B210F45FC3A8433140D1EBCA85227940922C02E9

k = 000000000000000000000000000000000000000000000000000000000000000A
P = 04D3F94862519621C121666061F65C3E32B2D0D065CD219E3284A04814DB5227564B9030CF676F6A742EBD57D146DCA428F6B743F64D1482D147D46FB2BAB82A14

k = 000000000000000000000000000000000000000000000000000000000000000B
P = 0404B3CB10C9C6D8E27C1AAB770F67F543125DCDD589C2FF82668C74D78CE20ACE63516355287E39FE4918E5C02E2B0B930C94816E63C4BC72739A8FD805174A4B

k = 000000000000000000000000000000000000000000000000000000000000000C
P = 04BFC2DF6BB17F971AD89058CA059BE46E5F7B516C5BDADDAD9C9F042D0279270AB145513F59636106CEF696B67939BD7B73C9FC6FD150AAAAB5FBF87B64AF3C26

k = 000000000000000000000000000000000000000000000000000000000000000D
P = 04952072D6FF9C65BDFA804513275F58AA7BEA65C6421E189E2B834F1D509B9CD0E6BB9804458BB70F1A473F8D9748F23858D1434AE934BA7503891E105E009B00

k = 000000000000000000000000000000000000000000000000000000000000000E
P = 0483B4A4DE96A4D70F4AAF81826982D748EF22EA28BE9D44DE0A44248A36BB0A07E481C0D9EE8A98D4EEB6D6C6D7E74F8E3E707C8A438529492E663CD4373A2F24

k = 000000000000000000000000000000000000000000000000000000000000000F
P = 04F73B839F13912C1A3291676C38D393243B424F35F0ECCE4C461B1BBCB80F829C32EC7722695DC7CF5EE9FAB985C12455DC2E788FB170AA144C3533771DB0955E

k = 0000000000000000000000000000000000000000000000000000000000000010
P = 0435648233F554AE51BBCE44EF5DB3E419EA133CD248A93E2555645BBC8704FB6804D7AC60F6D975EF6117BCA9CE885DD6154B1870A6A651664411A9A30ECA2046

k = 0000000000000000000000000000000000000000000000000000000000000011
P = 04DD18AA4AEC26EAC41C993F01115C57F7BF5113AB85B5ED4436969F8B77125E6A161E5851969DA8223361493F76FAC50F6CCE6001D7C0B853E0180D54D4AE2221

k = 0000000000000000000000000000000000000000000000000000000000000012
P = 0469FDF8A436FD8E5D221EA8657781CE71A3448557A24554DB427E33AE8ED9C317BAA856D1CAD68AF36B0A9658B33B347BEB7B1AD657C155F571E35709341FDCAB

k = 0000000000000000000000000000000000000000000000000000000000000013
P = 04A68B2EC49D1921D0E2E0586BB5DC9419F7C96C55940A47261323F252E493952A96F361A23B3DEB99933EF442FCA7A734B95F2DE69200269EFD4520A63F5CC585

k = 0000000000000000000000000000000000000000000000000000000000000014
P = 0408314765E44847EB7575E3CB2FA9092DABBB1EA1417F958D0588FDD88ABDEE94DF922344FA592A986B443AB4360953787DE3A53937E8A75F5EEB0E99C2EB61E9

k = 0000000000000000000000000000000000000000000000000000000000000015
P = 046407BE639BC5B738137CBF4E8AA505355B551C86A8976933E1DE5F100950C8AB141CAEE612E7AB0712A9423FD80DEA5460FCFD988FFF6DECF945321148E90344

k = 0000000000000000000000000000000000000000000000000000000000000016
P = 04E61120569974C0BC1835A4D0F3E5E2993E7307F46FA550D10755A352DAFA1E1DCFE30AA2C3877E52D08FC10E5056E4BC02855E18D12379B43B86CC142850B0F3

k = 0000000000000000000000000000000000000000000000000000000000000017
P = 04AC8DF677299E828815C07A8C04226FE3BB570A9F430EA7F64DBB2FCD069D45DBAEF82CF361DB1C7130C43BE69B23CC140E9B9643D766DA337BD8B7C847718CE5

k = 0000000000000000000000000000000000000000000000000000000000000018
P = 04DF8A74F904D1715E314FA6C814C7BDA8EC268911CCB79283D7240A35D1F4FFED0FED448A3F2639187A7606EF148AA5FBE1C80E7752BD6499BCB60A9E82017C30

k = 0000000000000000000000000000000000000000000000000000000000000019
P = 04178D1F6BD584AFCCCE1564C3DF7D67EA7E8581FBBCF5DE010263B20D539E4139F575F34E5F6C63C653DA45CEC1CAADA17021AAFC29AC8E869B499A7DA7820BF9

k = 000000000000000000000000000000000000000000000000000000000000001A
P = 04A0A1A4FBEB476576BCF26FE238A102C273783EF304251E748E6A9E4FDF8952908DFDD7CD150D25640D09C3F281D4C41CEC73068587361B34E54F7F3A4896D9D3

k = 000000000000000000000000000000000000000000000000000000000000001B
P = 04EC6F34CEACAA73A0D7A1F169475B4DDF02A85A7410754529CE37E84FC9541B4B3C85CF62A744817E6F251C63FBBD2927E607F33BE20135EA73306A0FF0485872

k = 000000000000000000000000000000000000000000000000000000000000001C
P = 0491CB72DC55F8434694ED53ED581D191D36F0DFE49113C16E6CB2F058C747D33F1957AD4CFFFD491EF7EFB07682931F88F4C600E8B5DFE8113EA6AACE93921F31

k = 000000000000000000000000000000000000000000000000000000000000001D
P = 0428221C36398C4C3A625773CAE69BBE05C9816BE068BE66DB9DD4EF421635B9DC3B4D172D6963510BAB2012C41627CD8164C77A81858D4CA12995225E66B162BA

k = 000000000000000000000000000000000000000000000000000000000000001E
P = 0417A5F74D533AE724C315796922BF13438B1AC02E98D543CEFD23EA021DA51C9D498470EC6752B2ECB9038823D9AD0D5F7BEFA4DB8C8D3EFF57D2E81DBB945DFE

k = 000000000000000000000000000000000000000000000000000000000000001F
P = 0408DAAE840B2A43EBD6B48259B69E853027D053C0F150FE10AC995C5066BDAAA580CC0A980495AF87C1B8E58150DA662DF7DC310560BBE83A2458B9E3C73BF657

k = 0000000000000000000000000000000000000000000000000000000000000020
P = 0425D3DEBD0950D180A6D5C2B5817F2329791734CD03E5565CA32641E56024666C92D99A70679D61EFB938C406DD5CB0E10458895120E208B4D39E100303FA10A2

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54122
P = 0432C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C743C8C95C0B098863A642311C9496DEAC2F56788239D5B8C0FD20CD1ADEC60F5F

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54121
P = 0456CEFD60D7C87C000D58EF57FA73BA4D9C0DFA08C08A7331495C2E1DA3F2BD52CE481818337E760997ACA31F07150E429217B3E6D093718F9087F2C568F5DC3C

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54120
P = 04A97F7CD4B3C993B4BE2DAA8CDB41E24CA13F6BD945302244E26918F1D0509EBFACF4A2267397710A333A313F758DEAF083BFF11932FBAD6E555322FC8BA70919

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5411F
P = 04C239507105C683242A81052FF641ED69009A084AD5CC937DB21646CD34A0CED54E40813AF7F0C378CA0ED6B53F24E6979411D16854738E0585DAC99934991FF6

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5411E
P = 04C749061668652E26040E008FDD5EB77A344A417B7FCE19DBA575DA57CC372A9E0D20A24C2EBB16BABAFB39DD4AE30C70AFF9DF904A86008359689100A0419B7F

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5411D
P = 040927AFB57D93483BBB17C93E71F22A3105FF8856A66016892C8B1A1A3C4B0D30EAF394E44B2E038153E3F109140D99BA7E520E0E7AA5F9B32A8DEFCFFFF7709C

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5411C
P = 04DDF092555409C19DFDBE86A75C139906A80198337744EE78CD27E384D9FCAF157B82E6FF4C7178F9A32949163ED2D6DDFC86C88E8295B65EDDC46B69A81AD43E

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5411B
P = 04B9C3FAEB4B1610713DB4333D4E860E64D4EA35D60C1C29BB675D822DED0BB9163AE64CF51308D963DB6E2D2165330D41FC99575ECFDB4C20C3D7925D302CE5C1

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5411A
P = 04A27233F3A59595080B4A2444A46A74C5FE8D59CB43619E4F173472A58CCA247EC8618D08C8DD36DB897089764DEF0BA03C57BCCDBF2E14367ADD86BF6DD3FD16

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54119
P = 04D3F94862519621C121666061F65C3E32B2D0D065CD219E3284A04814DB522756B46FCF2F9890958BD142A82EB9235BD70948BC08B2EB7D2FB82B904D4547D5EB

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54118
P = 0404B3CB10C9C6D8E27C1AAB770F67F543125DCDD589C2FF82668C74D78CE20ACE9CAE9CA9D781C601B6E71A3FD1D4F46CF36B7E909C3B438E8C657027FAE8B5B4

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54117
P = 04BFC2DF6BB17F971AD89058CA059BE46E5F7B516C5BDADDAD9C9F042D0279270A4EBAAEBFA69C9EF93109694986C642848C36038F2EAF55564A0407849B50C3D9

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54116
P = 04952072D6FF9C65BDFA804513275F58AA7BEA65C6421E189E2B834F1D509B9CD0194467FABA7448F0E5B8C07268B70DC7A72EBCB416CB458BFC76E1EFA1FF64FF

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54115
P = 0483B4A4DE96A4D70F4AAF81826982D748EF22EA28BE9D44DE0A44248A36BB0A071B7E3F251175672B114929392818B071C18F8374BC7AD6B7D199C32BC8C5D0DB

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54114
P = 04F73B839F13912C1A3291676C38D393243B424F35F0ECCE4C461B1BBCB80F829CCD1388DC96A23830A11605467A3EDBAA23D1876F4E8F55ECB3CACC88E24F6AA1

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54113
P = 0435648233F554AE51BBCE44EF5DB3E419EA133CD248A93E2555645BBC8704FB68FB28539E09268A109EE843563177A229EAB4E78E5959AE9ABBEE565CF135DFB9

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54112
P = 04DD18AA4AEC26EAC41C993F01115C57F7BF5113AB85B5ED4436969F8B77125E6AE9E1A7AD696257DDCC9EB6C089053AF093319FFD283F47AD1FE7F2AB2B51DDDE

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54111
P = 0469FDF8A436FD8E5D221EA8657781CE71A3448557A24554DB427E33AE8ED9C3174557A92D3529750C94F569A74CC4CB841484E528A83EAA0B8E1CA8F6CBE02354

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54110
P = 04A68B2EC49D1921D0E2E0586BB5DC9419F7C96C55940A47261323F252E493952A690C9E5CC4C214666CC10BBD035858CB46A0D2186DFFD96202BADF59C0A33A7A

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5410F
P = 0408314765E44847EB7575E3CB2FA9092DABBB1EA1417F958D0588FDD88ABDEE94206DDCBA05A6D56794BBC54BC9F6AC87821C5AC5C81758A1A114F1663D149E16

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5410E
P = 046407BE639BC5B738137CBF4E8AA505355B551C86A8976933E1DE5F100950C8ABEBE35118ED1854F8ED56BDC027F215AB9F0302667000921406BACDEEB716FCBB

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5410D
P = 04E61120569974C0BC1835A4D0F3E5E2993E7307F46FA550D10755A352DAFA1E1D301CF55C3C7881AD2F703EF1AFA91B43FD7AA1E62EDC864CC47933EBD7AF4F0C

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5410C
P = 04AC8DF677299E828815C07A8C04226FE3BB570A9F430EA7F64DBB2FCD069D45DB5107D30B9E24E38ECF3BC41964DC33EBF16469BB289925CD84274837B88E731A

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5410B
P = 04DF8A74F904D1715E314FA6C814C7BDA8EC268911CCB79283D7240A35D1F4FFEDF012BB74C0D9C6E78589F910EB755A041E37F187AD429B674349F5617DFE83CF

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D5410A
P = 04178D1F6BD584AFCCCE1564C3DF7D67EA7E8581FBBCF5DE010263B20D539E41390A8A0CB0A0939C39AC25BA313E35525E8FDE5502D653717A64B66582587DF406

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54109
P = 04A0A1A4FBEB476576BCF26FE238A102C273783EF304251E748E6A9E4FDF89529072022831EAF2DA9BF2F63C0D7E2B3BE3138CF97978C9E4CC1AB080C5B769262C

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54108
P = 04EC6F34CEACAA73A0D7A1F169475B4DDF02A85A7410754529CE37E84FC9541B4BC37A309C58BB7E8190DAE39C0442D6D819F80CC31DFECA168CCF95F00FB7A78D

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54107
P = 0491CB72DC55F8434694ED53ED581D191D36F0DFE49113C16E6CB2F058C747D33FE6A852B20002B6E108104F897D6CE0770B39FF164A2017EFC15955316C6DE0CE

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54106
P = 0428221C36398C4C3A625773CAE69BBE05C9816BE068BE66DB9DD4EF421635B9DCC4B2E8D1969CAEF454DFED3BE9D8327E9B38857D7A72B35FD66ADDA1994E9D45

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54105
P = 0417A5F74D533AE724C315796922BF13438B1AC02E98D543CEFD23EA021DA51C9DB67B8F1298AD4D1346FC77DC2652F2A084105B237372C101A82D17E2446BA201

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54104
P = 0408DAAE840B2A43EBD6B48259B69E853027D053C0F150FE10AC995C5066BDAAA57F33F566FB6A50783E471A7EAF2599D20823CEF99F4417C6DBA7461C38C409A8

k = FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54103
P = 0425D3DEBD0950D180A6D5C2B5817F2329791734CD03E5565CA32641E56024666C6D26658E98629E1046C73BF922A34F1EFBA776ADDF1DF74C2C61EFFCFC05EF5D
Loading