public class SM9G2Point
extends java.lang.Object
SM9P256V1Curve (see SM9Curve.G1).| Modifier and Type | Method and Description |
|---|---|
SM9G2Point |
add(SM9G2Point o) |
static SM9G2Point |
decode(byte[] enc) |
boolean |
equals(java.lang.Object other) |
byte[] |
getEncoded()
Uncompressed encoding 0x04 || x || y, each F_p2 coordinate written high
dimension first (u-coefficient then constant), 32 bytes per F_p component;
129 bytes total.
|
int |
hashCode() |
boolean |
isInfinity() |
boolean |
isInSubgroup()
Whether this point lies in G2, the order-N subgroup of the twist curve -
that is, whether [N]P is the point at infinity.
|
SM9G2Point |
multiply(java.math.BigInteger k)
Scalar multiplication, returning [k]this.
|
public boolean isInfinity()
public SM9G2Point add(SM9G2Point o)
public SM9G2Point multiply(java.math.BigInteger k)
The KGC runs it on its secrets - [ks]P2 for a signature master key and [t2]P2 for each encryption user key it derives - so four things are done for it:
SM9Curve.blind(java.math.BigInteger)): the multiplication runs the same steps from the same leading bit
whatever k is, where a ladder over k itself stayed at the point at infinity, on cheaper
arithmetic, through k's leading zero bits.
P2 itself, the instance SM9Curve.P2 - the base of both - runs Lim and Lee's comb,
over a table of thirty-two multiples of P2 and their doubles that its first call makes and P2
keeps, 8 KB of points anyone can compute. The blinded scalar's bits fall into sixty-four
columns of five, column c holding bits c, c + 64, c + 128, c + 192 and c + 256, and entry d of
the table, for
d = d0 + 2d1 + 4d2 + 8d3 + 16d4, is [1 + d0 + d1 2^64 + d2 2^128 + d3 2^192 + d4 2^256]P2. From
the top column down, each column doubles the running point and adds the entry its bits pick
out, read out of the table in full, through lookup(int[], int, int, int, int[]). The 1 in each entry's multiple
makes entry 0 P2 rather than the point at infinity, which has no affine coordinates to hold;
the entries the columns add then carry [2^64 - 1]P2 as well, so the comb is run over the
blinded scalar less 2^64 - 1, which the blinding leaves positive. A call takes sixty-three
doublings and sixty-three additions, where the ladder takes 320 doublings and 319 additions;
the first also makes the table.
The entries are fixed points, whose coordinates would tell apart each column's entry as it is
read and added. So each call draws a random non-zero lambda of F_p2 and carries the entries
from (x, y) to (lambda^2 x, lambda^3 y), points of the twist y^2 = x^3 + lambda^6 5u, which that
map takes this one to, and runs the comb there: the doubling and the addition do not involve
the curve's constant, and a result (X, Y, Z) there is (X, Y, lambda Z) here. The copy of the
table the factor is applied to is erased when the call ends; the table itself holds only
multiples of P2. Each column's scan of the table starts at an entry drawn at random for it, one
byte each of a sixty-four-byte draw the call makes, and wraps round, and the value it reads
into is cleared first, so that the step of the scan that moves the column's entry into place
does not give the column's bits away - see lookup(int[], int, int, int, int[]). And the running point may be at
infinity, equal to the entry it adds, or its negation - for a small k such as 1 or 2 the
blinding makes one of the first two happen in about one call in thirty-two - so the table holds
each entry's double beside it, and the addition takes the double or the entry in place of the
sum under masks (see addEntry(int[], int[], int[], int[])), with no doubling but the column's.
Any other point runs a Montgomery ladder, maintaining the invariant r1 = r0 + this: one addition and one doubling per bit, from (x Z^2, y Z^3, Z) for a random non-zero Z drawn for the call, its two running points exchanged at each bit, or not, by a masked swap that reads and writes both either way, and updated in the same steps whichever it did.
public byte[] getEncoded()
public static SM9G2Point decode(byte[] enc)
public boolean isInSubgroup()
Being on the twist curve is not enough. E'(F_p2) has order N*h2 with
h2 = 2q - N, a 256-bit composite (13 divides it), so unlike G1 - whose
cofactor is 1, which is what lets on-curve-and-not-infinity settle membership
there - the twist carries points of other orders, and the pairing has no
bilinear meaning on them: e(P1, A + B) does not equal e(P1, A) * e(P1, B) for
an A outside G2, and the Miller loop can reach a degenerate division and raise
ArithmeticException. Every encoded G2 point that arrives from outside the
process is therefore checked here, and a caller that builds one through
add(org.bouncycastle.math.ec.sm9.SM9G2Point) or multiply(java.math.BigInteger) can check it the same way.
The test is [t + 1]P + pi([t]P) + pi^2([t]P) = pi^3([2t]P), for the BN parameter t and
pi(x, y) = (x^q gamma^-2, y^q gamma^-3), the q-power Frobenius carried to the twist and back,
which gives the pairing its point Q1 (see SM9Pairing): whether f(pi)P = O for
f(x) = (t + 1) + t x + t x^2 - 2t x^3. pi takes each point of G2 to its q-th multiple, and
q = N + 6t^2, so on G2 f(pi) is [f(6t^2)], and N divides f(6t^2): every point of G2 passes. And
pi satisfies pi^2 - tr pi + q = 0 on the whole twist, tr = 6t^2 + 1 being the trace of the
Frobenius of E, so f(pi) is a0 + a1 pi there, a0 + a1 x being the remainder of f on division
by x^2 - tr x + q, and a point that passes has, applying a0 + a1 (tr - pi) as well,
[a0^2 + a0 a1 tr + a1^2 q]P = O. That multiplier is a multiple of N prime to h2, so the point's
order divides N; N does not divide h2, so the points of E'(F_p2) whose order divides N are
those of G2.
[t]P is formed by a chain of doublings and additions over the non-adjacent form of t, whose
sixty-four digits have eleven that are not 0: sixty-three doublings and ten additions, where
the ladder multiply(java.math.BigInteger) runs would take sixty-three doublings and sixty-two additions over
the 63 bits of t (and [N]P a ladder over 256 bits). t being public, a ladder's regularity gains
nothing here. [t + 1]P is one addition more. None of the chain's additions meets two equal
operands (see add(org.bouncycastle.math.ec.sm9.SM9G2Point)), so none forms the double that addAny(int[], int[], int[], int[], int[]) forms each time to
take that case; the rest is two additions through addAny, a doubling and three applications
of pi, and the two sides are compared in Jacobian coordinates, so nothing is inverted. For no
point of the twist other than infinity do those two additions meet an operand at infinity or
two equal or opposite operands, or the comparison a side at infinity: each would need [t]P,
[t + 1]P, [2t]P, or (t + 1) -+ t pi or (t + 1) + t pi -+ t pi^2 applied to P, to be O, and
the point's order, which divides N h2, h2 = 2q - N, the order of the twist being N h2, would
then divide the multiplier's norm, a0^2 + a0 a1 tr + a1^2 q for its remainder a0 + a1 pi,
each of which is prime to N h2. The additions take them through addAny all the same. The
cost, under a sixth of a pairing, is paid when a key is decoded, not per operation.
public boolean equals(java.lang.Object other)
equals in class java.lang.Objectpublic int hashCode()
hashCode in class java.lang.Object