Bouncy Castle Cryptography Library 1.87

org.bouncycastle.math.ec.sm9
Class SM9Curve

java.lang.Object
  extended byorg.bouncycastle.math.ec.sm9.SM9Curve

public class SM9Curve
extends java.lang.Object

Fixed system parameters of the SM9 256-bit BN curve (GM/T 0044.5-2016, clause 1).

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.


Field Summary
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
           
 
Method Summary
static ECPoint g1FromBytes(byte[] b, int off)
          Reconstruct a G1 point from its 64-byte x || y encoding at .
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)).
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

G1

public static final ECCurve G1

N

public static final java.math.BigInteger N
The group order N, shared by G1, G2 and G_T. Taken from the G1 curve, which already carries it as its order, rather than transcribed a second time - two hand-copied hex strings had nothing to keep them the same.


P1

public static final ECPoint P1

P2

public static final SM9G2Point P2
Method Detail

g1ToBytes

public 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).


g1FromBytes

public static ECPoint g1FromBytes(byte[] b,
                                  int off)
Reconstruct a G1 point from its 64-byte x || y encoding at . The caller is responsible for validating the result (e.g. ECPoint.isValid()).

Throws:
java.lang.IllegalArgumentException - if fewer than 64 bytes are available at , or a coordinate is not below q.

multiplySecure

public 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. It runs Lim and Lee's comb over a table of thirty-two multiples of the point and their doubles, 4 KB, which is made the first time the point is multiplied and kept with it, so that later multiplications of the same point skip it. The comb reads the scalar blinded with a random multiple of N into 320 bits, carries the entries it reads by a random factor drawn for the call, reads each entry by a full scan of the table from an entry drawn at random, and takes the running point at infinity or equal to the entry it adds by the same steps as any other - the entry itself, or its double, which the table holds beside it - so that neither the steps it takes, the memory it reads nor the values it computes on follow the scalar's digits from call to call.

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.


sumOfTwoMultipliesSecure

public 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)). 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.


multiplyPublic

public 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. It runs the GLV method over the endomorphism (x, y) -> (beta x, y) of G1, which is the multiplication by a cube root of 1 mod N: the scalar is split into two of half its length, and the point and its image are multiplied by them together, two interleaved windowed NAFs over some 128 bits, where 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.


g1FromUncompressed

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

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.

Parameters:
enc - the encoded point.
Returns:
the decoded point, which is on the curve.

Bouncy Castle Cryptography Library 1.87