# Groups

The CryptoGroups package provides a main API for working with cryptographic groups in a group-agnostic manner, supporting modular prime groups, elliptic curves over prime fields, and binary fields. This flexibility enables polymorphic implementations of standards like FIPS 186-4 digital signature algorithm to work seamlessly across different group types. Essential security checks, such as verifying point membership on elliptic curves or cofactor validation, are integrated into the constructors.

CryptoGroups encodes relevant group parameters as type parameter values, leveraging Julia's powerful type system to minimize the need for runtime assertions and ensure efficient memory use. This design allows for vector-like collections to be used without subtyping AbstractArray, resulting in a leaner and more predictable codebase. This also necessitates compiling every group, and are up to the user to decide which groups are needed for their applications.

`CryptoGroups.ECGroup`

— Type```
struct ECGroup{P<:ECPoint} <: Group
x::P
end
```

Ellitpic curve group that maps `ECPoint`

add and multiply to multiply and exponent semantics. The group can be instantiated from `x`

, `y`

coordinates `ECGroup{P}(x, y)`

which are passed to corepsonding elliptic curve point constructor or via octet representation as specified in FIPS 186-4 standart. To construct the type use `concretize_type`

or `@ECGroup`

macro.

**Example**

```
p192_spec = spec(:P_192)
G = concretize_type(ECGroup, p192_spec)
# A macro syntax
G = @ECGroup{P_192}
```

If a group is instantiated from an existing specification then `G()`

creates an instance of generator. A following ilustrates typical operations:

```
G = @ECGroup{P_192}
g = G()
g^3 * g^5/g^2 == (g^3)^2 == g^6
g^(order(G) - 1) * g == one(G)
one(G) * g == g
G(octet(g)) == G(value(g)) == g
```

See also `octet`

, `value`

, `concretize_type`

, `spec`

`CryptoGroups.Group`

— Type`abstract type Group end`

A cyclic group interface type. It is expected that constructor of the group does instance validation and throws an `ArgumentError`

if it can't be constructed. Identity element can be constructed with explicit argument `allow_one=true`

and validation can be opted out with `skip_validation=true`

argument for the constructor which can be useful for deserialization from a secure location locally.

The group element shall support construction from vector of bytes (octet) as well as `octet`

method itself. In addition `value`

method is expected that provides most simple representation useful for debugging purposes. Given `g::Group`

a following constructor methods are supported:

```
G = typeof(g)
g == G(octet(g)) == G(value(g))
one(G) == G(octet(one(G)), allow_one=true)
```

The group must support `order`

, `*`

, `^`

, `rem`

and identity element via `one`

. For concrete implementations see `PGroup`

and `ECGroup`

.

`CryptoGroups.PGroup`

— Type```
struct PGroup{S} <: Group
g::BigInt
end
```

Modulus prime group where `S`

is a static type parameter encoding group properties. To instantiate a concrete type use a macor `@PGroup`

or use `concretize_type`

.

**Example**

```
# Directly passing type arguments
G = concretize_type(PGroup, 23, 11) # where modulus is 23 and order is 11
# Using a macro for user specification
G = @PGroup{p = 23, q = 11}
# Using existing specification
modp = spec(:RFC5114_2048_224)
G = concretize_type(PGroup, modp)
# Using a macro for existing specification
G = @PGroup{RFC5114_2048_224}
```

If a group is instantiated from an existing specification then `G()`

creates an instance of generator. A following ilustrates typical operations:

```
G = @PGroup{p = 23, q = 11}
g = G(2)
g^3 * g^5/g^2 == (g^3)^2 == g^6
g^(order(G) - 1) * g == one(G)
one(G) * g == g
G(octet(g)) == G(value(g)) == g
```

See also `octet`

, `value`

, `concretize_type`

, `spec`

`Base.:*`

— Method`*(x::G, y::G)::G where G <: Group`

Multiplies two group elements.

`Base.:/`

— Method`/(x::G, y::G)::G where G <: Group`

Convinience method for `x * inv(y)`

`Base.:^`

— Method`^(x::G, n::Integer)::G where G <: Group`

Exponentiates the group element. In case `mod(n, order(G)) == 0`

throws an error in strict mode or shows a warning in relaxed mode.

See also `isstrict`

and `set_strict_mode`

`Base.convert`

— Method`convert(::Type{G}, x; allow_one=false)::G where G <: Group`

Converts representation of `x`

into a group element type `G`

. The conversion is safe as the validation checks are performed within group constructors. In case identity element needs to be read into `allow_one`

flag can be used to allow constructing identity elements.

`Base.inv`

— Method`inv(g::G)::G where G <: Group`

Computes inverse of the group element so that `inv(g) * g == one(G)`

`Base.one`

— Method`one(::Type{G}) where G`

Construct an identity element of the group.

`Base.rem`

— Method`rem(x::ECGroup, q::T)::T where T <: Integer`

Computes remainder of the elliptic curve point

`Base.rem`

— Method`rem(x::PGroup, q::T)::T where T <: Integer`

Computes remainder of a prime group integer value

`CryptoGroups.Fields.modulus`

— Method`modulus(::Union{G, Type{G}})::BigInt where G <: PGroup`

Modulus of a prime group. It is not recommended to depend on this method in the codebase as it destroys polymorphism.

`CryptoGroups.Fields.octet`

— Method`octet(g::ECGroup; mode = :uncompressed|:hybrid|:compressed)::Vector{UInt8}`

Converts elliptic curve point to an octet representation as specified in FIPS 186-4 standart. The `mode=:uncompressed|:hybrid|:compressed`

can be used to specify compression mode.

See also `iscompressable`

`CryptoGroups.Fields.octet`

— Method`octet(x::PGroup)::Vector{UInt8}`

Converts modulus prime group element into octet representation. A padding is added to match the length of modulus.

`CryptoGroups.concretize_type`

— Function`concretize_type(::Type{T}, args...) <: T where T`

Constructs a concrete subtype of union all or abstract type `T`

. The arguments `args`

are used to set concrtete values for type parameters of `T`

, effectivelly `concretizing`

a generic abstract type. The resulting type then can be instanitated by a value.

See also `spec`

`CryptoGroups.iscompressable`

— Method`iscompressable(g::Group)::Bool`

Returns `true`

if `octet`

function accepts `mode=:compressed`

as is groups based on eliptic curves. Currently for binary curves decompression is not implemented and hence this method returns false for them.

`CryptoGroups.order`

— Method`order(::Union{G, Type{G})::BigInt where G <: Group`

Get the order of the group

`CryptoGroups.spec`

— Function`spec(::Union{G, Type{G}})::GroupSpec where G <: Group`

Constructs a specification of a group type or instance. It's general intended use is for debugging purposes and serves as an inverse to `concretize_type`

method. If called with a group instance the the value of it is used for a generator for the group specification otherwise it is left empty.

See also `concretize_type`

`CryptoGroups.spec`

— Method`spec(name::Symbol)::GroupSpec`

Gets a group specification from a provided canonical `name`

of the group specification which are hardcoded into the library.

**Examples**

```
# NIST elliptic curve P-192 specification:
p192_spec = spec(:P_192)
P192 = concretize_type(ECGroup, p192_spec)
# Modular prime group specification
modp_spec = spec(:RFC5114_2048_224)
MODP = concretize_type(PGroup, modp_spec)
```

See also `concretize_type`

, `@ECGroup`

, `@PGroup`

`CryptoGroups.value`

— Method`value(g::Group)::Union{BigInt, Tuple{BigInt, BigInt}, Tuple{BitVector, BitVector}}`

Converts the group instance to the most simple representation. Generally intended for debugging purposes and for serialization one should use `octet`

as it also ensures consistent padding.

See also `octet`

, `Curves.gx`

, `Curves.gy`

`CryptoGroups.verify_pgroup_membership`

— MethodVerifies membership in a prime-order group with optimizations for common cases.