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
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
— Typeabstract 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
— Typestruct 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
— Methodconvert(::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
— Methodinv(g::G)::G where G <: Group
Computes inverse of the group element so that inv(g) * g == one(G)
Base.one
— Methodone(::Type{G}) where G
Construct an identity element of the group.
Base.rem
— Methodrem(x::ECGroup, q::T)::T where T <: Integer
Computes remainder of the elliptic curve point
Base.rem
— Methodrem(x::PGroup, q::T)::T where T <: Integer
Computes remainder of a prime group integer value
CryptoGroups.Fields.modulus
— Methodmodulus(::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
— 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 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
— Methodiscompressable(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
— Methodorder(::Union{G, Type{G})::BigInt where G <: Group
Get the order of the group
CryptoGroups.spec
— Functionspec(::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
— Methodspec(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
— 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.