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 — Typestruct ECGroup{P<:ECPoint} <: Group
x::P
endEllitpic 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)) == gSee also octet, value, concretize_type, spec
CryptoGroups.Group — Typeabstract type Group endA 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 — Typestruct PGroup{S} <: Group
g::BigInt
endModulus 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)) == gSee also octet, value, concretize_type, spec
Base.:* — Method*(x::G, y::G)::G where G <: GroupMultiplies two group elements.
Base.:/ — Method/(x::G, y::G)::G where G <: GroupConvinience method for x * inv(y)
Base.:^ — Method^(x::G, n::Integer)::G where G <: GroupExponentiates 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 — Methodconvert(::Type{G}, x; allow_one=false)::G where G <: GroupConverts 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 — Methodinv(g::G)::G where G <: GroupComputes inverse of the group element so that inv(g) * g == one(G)
Base.one — Methodone(::Type{G}) where GConstruct an identity element of the group.
Base.rem — Methodrem(x::ECGroup, q::T)::T where T <: IntegerComputes remainder of the elliptic curve point
Base.rem — Methodrem(x::PGroup, q::T)::T where T <: IntegerComputes remainder of a prime group integer value
CryptoGroups.Fields.modulus — Methodmodulus(::Union{G, Type{G}})::BigInt where G <: PGroupModulus of a prime group. It is not recommended to depend on this method in the codebase as it destroys polymorphism.
CryptoGroups.Fields.octet — Methodoctet(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 — Methodoctet(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 — Functionconcretize_type(::Type{T}, args...) <: T where TConstructs 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 — Methodiscompressable(g::Group)::BoolReturns 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 — Methodorder(::Union{G, Type{G})::BigInt where G <: GroupGet the order of the group
CryptoGroups.spec — Functionspec(::Union{G, Type{G}})::GroupSpec where G <: GroupConstructs 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 — Methodspec(name::Symbol)::GroupSpecGets 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 — Methodvalue(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.