public class SM9Curve
extends java.lang.Object
Curve E: y^2 = x^3 + 5 over F_q. G1 is E(F_q) itself, with generator P1 - the curve has
prime order N, so its cofactor is 1 and every point on it other than infinity is in G1; G2
is the order-N subgroup of the sextic twist E'(F_p2): y^2 = x^3 + 5u, with generator P2,
whose cofactor is not 1 (see SM9G2Point.isInSubgroup()). The R-ate pairing
e: G1 x G2 -> G_T uses loop parameter 6t+2.
| Modifier and Type | Field and Description |
|---|---|
static ECCurve |
G1 |
static java.math.BigInteger |
N
The group order N, shared by G1, G2 and G_T.
|
static ECPoint |
P1 |
static SM9G2Point |
P2 |
| Modifier and Type | Method and Description |
|---|---|
static ECPoint |
g1FromBytes(byte[] b,
int off)
Reconstruct a G1 point from its 64-byte x || y encoding at
off. |
static ECPoint |
g1FromUncompressed(byte[] enc)
Decode a G1 point from the 65-byte uncompressed form 0x04 || x || y that SM9 writes,
or from the one-octet 0x00 that encodes the point at infinity.
|
static byte[] |
g1ToBytes(ECPoint p)
Encode a G1 point as x || y (32 bytes each, big-endian), the affine-coordinate
form SM9 concatenates into KDF/MAC inputs and ciphertexts (no 0x04 prefix).
|
static ECPoint |
multiplyPublic(ECPoint p,
java.math.BigInteger k)
G1 scalar multiplication by a public scalar of a public point: verification's
[h1]S, h1 the hash of the signer's identity and S the point the signature carries.
|
static ECPoint |
multiplySecure(ECPoint p,
java.math.BigInteger k)
Constant-time G1 scalar multiplication by a secret scalar, for a point that is
multiplied by many: the generator P1, which the KGC multiplies by the encryption master
secret and by each signing key's t2, and a user's signing key ds, which each signature
multiplies by its l.
|
static ECPoint |
sumOfTwoMultipliesSecure(ECPoint p,
java.math.BigInteger a,
ECPoint q,
java.math.BigInteger b)
Constant-time [a]p + [b]q in G1 for secret scalars a and b and two points each multiplied
by many: [r h1]P1 + [r]P_pub-e, which is [r]Q for the recipient's point
Q = [h1]P1 + P_pub-e that encryption and encapsulation multiply by their ephemeral r, h1 being
the hash of the recipient's identity, and for the peer's point the key exchange multiplies (see
SM9EncMasterPublicKeyParameters.multiplyRecipientPoint(byte[], byte, java.math.BigInteger)). |
public static final ECCurve G1
public static final java.math.BigInteger N
public static final ECPoint P1
public static final SM9G2Point P2
public static byte[] g1ToBytes(ECPoint p)
public static ECPoint g1FromBytes(byte[] b, int off)
off. The caller is
responsible for validating the result (e.g. ECPoint.isValid()).java.lang.IllegalArgumentException - if fewer than 64 bytes are available at off, or
a coordinate is not below q.public static ECPoint multiplySecure(ECPoint p, java.math.BigInteger k)
NOTE: the multiplication computes in F_q on fixed-width limbs in Montgomery form, as the
pairing does and as G1's field SM9P256V1Field
does, in arithmetic that runs the same instructions whatever values it is given - its
reduction below q included, which BouncyCastle's other custom prime-field curves make by a
conditional subtraction.
The result is checked to lie on the curve, as BouncyCastle's multipliers check theirs, and one that does not - a fault in the table kept with the point, or in the running point - is refused with an IllegalStateException rather than returned.
public static ECPoint sumOfTwoMultipliesSecure(ECPoint p, java.math.BigInteger a, ECPoint q, java.math.BigInteger b)
SM9EncMasterPublicKeyParameters.multiplyRecipientPoint(byte[], byte, java.math.BigInteger)).
It runs multiplySecure(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger)'s comb over both points' tables at once, each column doubling
the running point once and adding the entry its bits pick out of each table, so that the two
multiplications share their doublings and the one inversion that brings the sum to affine
coordinates, and keeps each point's table with the point, as multiplySecure(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger) does:
P1's, which the KGC's multiplications of P1 read as well, and the master public key's, made the
first time the key is multiplied. Each scalar is blinded with its own random multiple of N, the
entries of both tables are carried by the one random factor drawn for the call, and each is
read by a full scan of its table from an entry drawn at random, as the comb reads them for one
point; the running point at infinity, or equal to the entry it adds, is taken by the same
steps as any other, whichever table the entry is read from. The result is checked to lie on
the curve, as multiplySecure(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger)'s is.public static ECPoint multiplyPublic(ECPoint p, java.math.BigInteger k)
ECPoint.multiply(java.math.BigInteger) runs one over all 256. Neither the steps it takes nor the entries it
reads are independent of the scalar and the point, and it keeps the multiples of the point it
makes, and the point's image, with the point: never for a private key, nor for any value
derived from one - multiplySecure(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger) and sumOfTwoMultipliesSecure(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger, org.bouncycastle.math.ec.ECPoint, java.math.BigInteger) are for those.public static ECPoint g1FromUncompressed(byte[] enc)
ECCurve.decodePoint(byte[]) would also take the hybrid form
(0x06 / 0x07 || x || y), which carries the same coordinates behind a different prefix
byte and so gives every G1 key a second accepted encoding - the malleability already
closed for the signature's S component and for ciphertexts. The compressed form is
refused as well: GM/T 0044.1 7.1 makes the compressed and hybrid forms optional, and SM9
writes neither.
Infinity is decoded rather than refused here, so that a caller whose key may not be the point at infinity rejects it in its own terms; no SM9 key may be, and each says so where it is decoded.
enc - the encoded point.