BLS12_381SubgroupCheck (Bouncy Castle Library 1.85 API Specification)
Date: 2026-07-12

org.bouncycastle.crypto.bls

## Class BLS12_381SubgroupCheck

- java.lang.Object
- - org.bouncycastle.crypto.bls.BLS12_381SubgroupCheck

-     public class BLS12_381SubgroupCheck
      extends java.lang.Object

  Fast subgroup-membership tests for BLS12-381 G1 and G2, replacing the naive `[r] * P == 0` scalar multiplication (255-bit).

  For G1: the GLV endomorphism σ(x, y) = (β·x, y), where β is a primitive cube root of unity in Fp, has eigenvalue λ = x² - 1 on G1 (a primitive cube root of unity in Z/r). The test `σ(P) == [λ] P` reduces the scalar to ~128 bits.

  For G2: the untwist-Frobenius-twist endomorphism ψ has eigenvalue x (the BLS parameter) on G2. The test `ψ(P) == [x] P` reduces the scalar to ~64 bits, and ψ itself is essentially free (one Fp² conjugation + one Fp² multiplication per coordinate).

  Both checks assume the input is already on the corresponding curve; verifying the curve equation is the caller's responsibility (and is done implicitly by `BLS12_381G2Point.of(org.bouncycastle.crypto.bls.Fp2Element, org.bouncycastle.crypto.bls.Fp2Element)` for G2 and `ECPoint.isValid()` for G1).

- - ### Method Summary

    All Methods Static Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `static boolean` | `isInG1Subgroup(ECPoint p)` Test G1 prime-order subgroup membership.
    `static boolean` | `isInG2Subgroup(BLS12_381G2Point p)` Test G2 prime-order subgroup membership.
    `static BLS12_381G2Point` | `psiG2(BLS12_381G2Point p)` The untwist-Frobenius-twist endomorphism on G2: `(x, y) -> (conjugate(x) * PSI_X, conjugate(y) * PSI_Y)`.
    `static ECPoint` | `sigmaG1(ECPoint p)` The GLV endomorphism on G1: σ(x, y) = (β·x, y).

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Method Detail

    - #### sigmaG1

          public static ECPoint sigmaG1(ECPoint p)

      The GLV endomorphism on G1: σ(x, y) = (β·x, y).

      Exposed for cross-package layered testing (the test classes live in `org.bouncycastle.crypto.hash2curve.test` and need direct access to the endomorphism for verification against the naive `[r] * P == 0` check). Not part of the intended public API of this class — production callers should use `isInG1Subgroup(org.bouncycastle.math.ec.ECPoint)`.

    - #### psiG2

          public static BLS12_381G2Point psiG2(BLS12_381G2Point p)

      The untwist-Frobenius-twist endomorphism on G2: `(x, y) -> (conjugate(x) * PSI_X, conjugate(y) * PSI_Y)`.

      Exposed for cross-package layered testing (see `sigmaG1(org.bouncycastle.math.ec.ECPoint)` for the rationale). Not part of the intended public API of this class — production callers should use `isInG2Subgroup(org.bouncycastle.crypto.bls.BLS12_381G2Point)`.

    - #### isInG1Subgroup

          public static boolean isInG1Subgroup(ECPoint p)

      Test G1 prime-order subgroup membership.

      Returns `true` iff `σ(P) == [x² - 1] P`, which is equivalent to `[r] P == 0` for any P on E(Fp).

    - #### isInG2Subgroup

          public static boolean isInG2Subgroup(BLS12_381G2Point p)

      Test G2 prime-order subgroup membership.

      Returns `true` iff `ψ(P) == [x] P`, which is equivalent to `[r] P == 0` for any P on E'(Fp²).