Skip to content

Commit

Permalink
pgroup optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
Janis Erdmanis committed Nov 4, 2024
1 parent 6642538 commit 66969e8
Show file tree
Hide file tree
Showing 11 changed files with 366 additions and 219 deletions.
5 changes: 2 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "CryptoGroups"
uuid = "bc997328-bedd-407e-bcd3-5758e064a52d"
authors = ["Janis Erdmanis <[email protected]>"]
version = "0.6.0"
version = "0.6.1"

[deps]
CryptoPRG = "d846c407-34c1-46cb-aa27-d51818cc05e2"
Expand All @@ -18,11 +18,10 @@ Primes = "0.5"
julia = "1"

[extras]
BitIntegers = "c3b6d118-76ef-56ca-8cc7-ebb389d030a1"
GaloisFields = "8d0d7f98-d412-5cd4-8397-071c807280aa"
Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45"
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["SafeTestsets", "Test", "GaloisFields", "BitIntegers", "Polynomials"]
test = ["SafeTestsets", "Test", "GaloisFields", "Polynomials"]
130 changes: 59 additions & 71 deletions src/Curves/conversions.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Implements point compression. Currently it is tied to AffinePoint but should be extended for generic case
using ..Fields: modulus, value, bitlength, int2octet, octet2int, octet2bits, bits2octet, tobits
using ..Fields: modulus, value, bitlength, int2octet!, octet2int, octet2bits, bits2octet, tobits
using CryptoUtils: sqrt_mod_prime
import ..Fields: octet

Expand Down Expand Up @@ -27,9 +27,6 @@ function decompress_weierstrass(x::BigInt, ỹ::Bool, (a, b)::Tuple{F, F}) where
return decompress_weierstrass(x, ỹ, (value(a), value(b)), p)
end


#function (::Type{P})(po::Vector{UInt8}) where P <: AbstractPoint

function Base.convert(::Type{P}, po::AbstractVector{UInt8}) where P <: AbstractPoint

pc = po[1]
Expand Down Expand Up @@ -101,109 +98,100 @@ end
(::Type{ECPoint{P, S}})(po::Vector{UInt8}) where {P <: AffinePoint, S} = ECPoint{P, S}(P(po))


function _compressed_octet(x::Vector{UInt8}, y::Vector{UInt8}, ỹ::Bool)

if== false
return UInt8[2, x...]
elseif== true
return UInt8[3, x...]
end

end


function _hybrid_octet(x::Vector{UInt8}, y::Vector{UInt8}, ỹ::Bool)

if== false
return UInt8[6, x..., y...]
elseif== true
return UInt8[7, x..., y...]
end

end


function _uncompressed_octet(x::Vector{UInt8}, y::Vector{UInt8})
return UInt8[4, x..., y...]
end


# This shall be considered internal as x, y can't be arbitrary!!!
function _octet(x::BigInt, y::BigInt, N::Int; mode::Symbol = :uncompressed) # N is bitlength(modulus(field()))

function _octet(x::BigInt, y::BigInt, N::Int; mode::Symbol = :uncompressed)
if iszero(x) && iszero(y)
return UInt8[0]
end

_x = int2octet(x, N)
_y = int2octet(y, N)


nbytes = cld(N, 8)
# Preallocate single output buffer
# Size is 1 (mode byte) + nbytes (x) + nbytes (y) for the largest case
out = Vector{UInt8}(undef, 2*nbytes + 1)

if mode == :uncompressed

return _uncompressed_octet(_x, _y)

out[1] = 0x04
# Write x and y directly into the output buffer at appropriate offsets
int2octet!(@view(out[2:nbytes+1]), x)
int2octet!(@view(out[nbytes+2:2nbytes+1]), y)
written = 2*nbytes + 1
elseif mode in [:compressed, :hybrid]

= mod(y, 2) % Bool
= mod(y, 2) % Bool

if mode == :compressed

return _compressed_octet(_x, _y, ỹ)

elseif mode == :hybrid

return _hybrid_octet(_x, _y, ỹ)

out[1] =? 0x03 : 0x02
int2octet!(@view(out[2:nbytes+1]), x)
written = nbytes + 1
else # mode == :hybrid
out[1] =? 0x07 : 0x06
int2octet!(@view(out[2:nbytes+1]), x)
int2octet!(@view(out[nbytes+2:2nbytes+1]), y)
written = 2*nbytes + 1
end

else
error("Unrecognized mode $mode")
end

# Return only the portion of the buffer that was written to
return resize!(out, written)
end


_octet(x::F, y::F; mode::Symbol = :uncompressed) where F <: PrimeField = _octet(value(x), value(y), bitlength(modulus(F)); mode)


function _octet(x::F, y::F; mode::Symbol = :uncompressed) where F <: BinaryField

if iszero(x) && iszero(y)
return UInt8[0]
end


# Get octets for x and y
_x = octet(x)
_y = octet(y)


# Calculate result size and allocate buffer
nbytes_x = length(_x)
nbytes_y = length(_y)

# Determine output size based on mode
outsize = if mode == :compressed
nbytes_x + 1 # 1 byte for header + x
else # :uncompressed or :hybrid
nbytes_x + nbytes_y + 1 # 1 byte for header + x + y
end

out = Vector{UInt8}(undef, outsize)

if mode == :uncompressed

return _uncompressed_octet(_x, _y)

# [4; x; y]
out[1] = 0x04
copyto!(out, 2, _x, 1, nbytes_x)
copyto!(out, nbytes_x + 2, _y, 1, nbytes_y)

elseif mode in [:compressed, :hybrid]

if isstrict()
@warn "Calculation of could be wrong due to insufficient tests."
@warn "Calculation of could be wrong due to insufficient tests."
end

z = y * inv(x)

= tobits(z)[end]

= tobits(z)[end]

if mode == :compressed
# [2/3; x]
out[1] =? 0x03 : 0x02
copyto!(out, 2, _x, 1, nbytes_x)

return _compressed_octet(_x, _y, ỹ)

elseif mode == :hybrid

return _hybrid_octet(_x, _y, ỹ)

else # mode == :hybrid
# [6/7; x; y]
out[1] =? 0x07 : 0x06
copyto!(out, 2, _x, 1, nbytes_x)
copyto!(out, nbytes_x + 2, _y, 1, nbytes_y)
end

else
error("Unrecognized mode $mode")
end

return out
end


octet(p::AbstractPoint; mode::Symbol = :uncompressed) = _octet(gx(p), gy(p); mode)

iscompressable(::P) where P <: AbstractPoint = eq(P) <: Weierstrass
13 changes: 11 additions & 2 deletions src/Fields/abstract_fields.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ..CryptoGroups.Utils: int2octet, octet2int, octet2bits, bits2octet
import ..CryptoGroups.Utils: int2octet!, octet2int, octet2bits, bits2octet

"""
abstract type Field end
Expand Down Expand Up @@ -200,7 +200,16 @@ Base.isless(x::F, y::F) where F <: PrimeField = value(x) < value(y)
Returns a byte representation of a field element according to FIPS 186-4 standart.
"""
octet(x::BinaryField) = bits2octet(tobits(x))
octet(x::PrimeField) = int2octet(value(x), bitlength(modulus(x)))
#octet(x::PrimeField) = int2octet(value(x), bitlength(modulus(x)))
function octet(x::PrimeField)

nbytes = cld(bitlength(x), 8)
buffer = Vector{UInt8}(undef, nbytes)
int2octet!(buffer, value(x), )

return buffer
end


# Perhaps a convert method fits better here as the type is specific
(::Type{F})(x::Vector{UInt8}) where F <: PrimeField = F(octet2int(x))
Expand Down
3 changes: 0 additions & 3 deletions src/Specs/Specs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import ..CryptoGroups.Utils: octet2int, octet2bits, hex2bits, int2octet, bits2oc

include("spec.jl")
include("field_specs.jl")

include("legacy.jl")

include("curve_constants.jl")
include("modp_constants.jl")

Expand Down
99 changes: 0 additions & 99 deletions src/Specs/legacy.jl

This file was deleted.

Loading

0 comments on commit 66969e8

Please sign in to comment.