jupyter-xeus / xeus-zmq

ZeroMQ-based middleware for xeus
http://xeus-zmq.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
9 stars 12 forks source link

Make the OpenSSL dependency optional #6

Open mrexodia opened 2 years ago

mrexodia commented 2 years ago

It looks like OpenSSL is only used for HMAC. mbedtls is a great alternative that's actually easy to build. According to this issue there is support for constant-time HMAC comparisons as well.

It would be ideal if you could do something like: cmake -B build -DXEUS_ZMQ_USE_MBEDTLS=ON.

Right now I'm using CMake as a package manager like this (the mamba packages are not working whatsoever on the M1):

# https://alexreinking.com/blog/how-to-use-cmake-without-the-agonizing-pain-part-1.html
cmake_minimum_required(VERSION 3.24)

project(dependencies)

# OpenSSL is the only system dependency we're using
find_package(OpenSSL REQUIRED)
if(OPENSSL_ROOT_DIR)
    # This is an attempt at getting the root from a documented variable
    file(REAL_PATH "${OPENSSL_INCLUDE_DIR}/.." OPENSSL_ROOT_DIR)
endif()

message(STATUS "OpenSSL root: ${OPENSSL_ROOT_DIR}")

include(ExternalProject)

set(INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/install")

set(INSTALL_ARGS
    "-DCMAKE_PREFIX_PATH:FILEPATH=${INSTALL_PREFIX}"
    "-DCMAKE_INSTALL_PREFIX:FILEPATH=${INSTALL_PREFIX}"
)

ExternalProject_Add(nlohmann_json
    URL
        "https://github.com/nlohmann/json/releases/download/v3.11.2/json.tar.xz"
    URL_HASH
        SHA256=8c4b26bf4b422252e13f332bc5e388ec0ab5c3443d24399acb675e68278d341f
    CMAKE_CACHE_ARGS
        ${INSTALL_ARGS}
        "-DJSON_BuildTests:STRING=OFF"
        "-DJSON_MultipleHeaders:STRING=OFF"
)

ExternalProject_Add(pugixml
    GIT_REPOSITORY
        "https://github.com/zeux/pugixml"
    GIT_TAG
        "v1.8.1"
    GIT_PROGRESS
        ON
    GIT_SHALLOW
        ON
    CMAKE_CACHE_ARGS
        ${INSTALL_ARGS}
)

ExternalProject_Add(cxxopts
    GIT_REPOSITORY
        "https://github.com/jarro2783/cxxopts"
    GIT_TAG
        "v3.0.0"
    GIT_PROGRESS
        ON
    GIT_SHALLOW
        ON
    CMAKE_CACHE_ARGS
        ${INSTALL_ARGS}
)

ExternalProject_Add(libzmq
    GIT_REPOSITORY
        "https://github.com/zeromq/libzmq"
    GIT_TAG
        "v4.3.4"
    GIT_PROGRESS
        ON
    GIT_SHALLOW
        ON
    CMAKE_CACHE_ARGS
        ${INSTALL_ARGS}
        "-DBUILD_TESTS:STRING=OFF"
)

ExternalProject_Add(cppzmq
    GIT_REPOSITORY
        "https://github.com/zeromq/cppzmq"
    GIT_TAG
        "v4.8.1"
    GIT_PROGRESS
        ON
    GIT_SHALLOW
        ON
    CMAKE_CACHE_ARGS
        ${INSTALL_ARGS}
        "-DCPPZMQ_BUILD_TESTS:STRING=OFF"
)

ExternalProject_Add(xtl
    GIT_REPOSITORY
        "https://github.com/xtensor-stack/xtl"
    GIT_TAG
        "0.7.4"
    GIT_PROGRESS
        ON
    GIT_SHALLOW
        ON
    CMAKE_CACHE_ARGS
        ${INSTALL_ARGS}
)

ExternalProject_Add(xeus
    GIT_REPOSITORY
        "https://github.com/jupyter-xeus/xeus"
    GIT_TAG
        "3.0.1"
    GIT_PROGRESS
        ON
    GIT_SHALLOW
        ON
    CMAKE_CACHE_ARGS
        ${INSTALL_ARGS}
)

ExternalProject_Add(xeus-zmq
    GIT_REPOSITORY
        "https://github.com/mrexodia/xeus-zmq"
    GIT_TAG
        "1.0.0-openssl-fix"
    GIT_PROGRESS
        ON
    GIT_SHALLOW
        ON
    CMAKE_CACHE_ARGS
        ${INSTALL_ARGS}
        "-DOPENSSL_ROOT_DIR:FILEPATH=${OPENSSL_ROOT_DIR}"
        "-DXEUS_ZMQ_DISABLE_ARCH_NATIVE:STRING=ON"
)

As you can see this requires me to pass OPENSSL_ROOT_DIR around (and I can forget about statically linking everything). With mbedtls I would only have to add the following in front of xeus-zmq and everything would work as a fully self-contained environment:

ExternalProject_Add(mbedtls
    GIT_REPOSITORY
        "https://github.com/Mbed-TLS/mbedtls"
    GIT_TAG
        "v3.2.1"
    GIT_PROGRESS
        ON
    GIT_SHALLOW
        ON
    CMAKE_CACHE_ARGS
        ${INSTALL_ARGS}
        "-DENABLE_PROGRAMS:STRING=OFF"
        "-DENABLE_TESTING:STRING=OFF"
)

Likely I'll do the work anyway, but let me know your thoughts on how to best approach this.

JohanMabille commented 1 year ago

Sorry for the late reply, it is possible to link statically with OpenSSL, that's what we do for xeus-python-wheel.

However, if you want or need the ability to link with another crypto library, I have nothing against adding it as an optional dependency in the CMakeLists.txt that would disable the dependency on OpenSSL. The part of the code related to authentication is already flexible enough to accept another implementation (see https://github.com/jupyter-xeus/xeus-zmq/blob/51d1c3d8c69d38d8be3a8c56748504306bf72796/src/xauthentication.cpp#L43 where openssl_authentication is a private implementation of the xauthentication interface).

mrexodia commented 1 year ago

Alright, I'll try to find some time to implement xauthentication with mbedtls and send a PR 👍🏻

mrexodia commented 2 months ago

I would like to get back to this issue. I found a few standalone hmac-sha256 implementations that could be embedded into the project directly as a single C file. From my searches in the organization this is the only scheme used, are there other schemes actually in use today you know of?

JohanMabille commented 2 months ago

I am not aware of other schemes that would be used at the protocol level. Your implementation could throw an exception when another scheme is used, that would help to detect them.

Besides, I don't think we want to embed cryptographic files directly in xeus-zmq, because that means that we would have to maintain them, and we are definitely not cryptographic experts. Depending on a well-known, rocket-tested library like mbedtls is a better alternative.

Also the packages for osx-arm64 have been added on conda-forge, I think they should work on the M1 now.