Note: only 24k for now.
This project could use a rename :/
The objective of this project is to provide fast cryptographic operations for Monero wallets. Unfortunately, there isn't necessarily a single fastest library for all platforms - donna64 for instance likely performs poorly when cross-compiled to asm.js or 32-bit arm. This project mitigates this issue by copying the cryptographic libraries with as little changes as possible (ideally zero), and then provides smaller and easier to audit "glue" functions that use the cryptographic library to perform typical Monero wallet tasks. These "glue" functions are often not obvious to the typical developer (otherwise they would be using the cryptographic libraries already), however auditing these functions should be straightforward to anyone familar with how the cryptography works.
The project is also designed to be used in-tree in other projects or installable on a system. The default Monero wallets use the in-tree implementation which serve as a more complex example of its usage. The project directory structure:
- crypto_sign - whose name is taken from supercop. The code in here is from upstream cryptographic libraries with minimal changes (position independent ASM).
- include - The only files that should be included by external projects, with the exception of the auto-generated header.
- src - Contains all of the glue functions and build code.
- functions.cmake - The raw components for building the library. Used by the default Monero wallet.
- intree.cmake - Creates a cmake library target
monero-crypto-intree
and generates a header at<BUILD_LOCATION>/include/monero/crypto.h
. - CMakeLists.txt - Declares a new project for creating/installing a
shared or static
monero-crypto
library.
Downstream projects cannot currently use this project without also using the
monero-project/monero/src/crypto/crypto.h
functions - specificallycrypto::derivation_to_scalar
. So currently this project provides performance enhancements but not standalone usage.
Every cryptographic library implements the same function signatures but with unique namespaces to avoid collisions in the C symbol table. Downstream projects can either use a specific library and header file OR dynamically select a library and use a cmake generated header that uses macro replacement to reference the selected library. Since each library has unique symbol names, multiple can be used simulatenously (benchmarking, etc).
Every cryptographic library implements:
monero_crypto_<namespace>_scalarmult(char* out, const char* pub, const char* sec)
- whereout
is the shared secret,pub
is an ed25519 public key, andsec
is a user secret key. This operation is a standard ECDH operation on the ed25519 curve.monero_crypto_<namespace>_generate_key_derivation(char* out, const char* tx_pub, const char* view_sec)
- whereout
is the shared secret,tx_pub
is the public key from the transaction andview_sec
is the users view-key secret.monero_crypto_<namespace>_generate_subaddress_public_key(char* out, const char* output_pub, const char* special_sec)
- whereout
is the computed spend-public (primary or subaddress),output_pub
is the public key from the transaction output, andspecial_sec
is the output fromcrypto::derivation_to_scalar
(which is given the shared secret fromgenerate_key_derivation
).
All char
pointers must be exactly 32-bytes. The auto-generated header has an
empty namespace for these functions and uses macro replacement to forward to the
selected library. If using dynamically selected libraries, include the
auto-generated header and use monero_crypto_generate_key_derivation
, etc.
A library can be selected explicitly in-tree:
include(supercop/functions.cmake)
monero_crypto_get_target("amd64-64-24k" CRYPTO_TARGET)
add_library(all $<OBJECT_TARGETS:${CRYPTO_TARGET}> all.cpp)
add_library(referenced referenced.cpp)
target_link_libraries(referenced ${CRYPTO_TARGET})
The all
library will have all C functions in the amd64-64-24k
library
whereas the referenced
library will only have C functions referenced in
referenced.cpp
.
A library can be selected at build time in-tree:
include(supercop/intree.cmake)
add_library(all $<OBJECT_TARGETS:monero-crypto-intree> all.cpp)
add_library(referenced referenced.cpp)
target_link_libraries(referenced monero-crypto-intree)
The best available library for the target platform is selected which can be
overriden with -DMONERO_CRYPTO_LIBRARY=amd64-51-30k
or by setting the
variable with the same name.
A header file is written to <BUILD_LOCATION>/include/monero/crypto.h
which
contains empty namespace macros that expand to the
wallet functions for the selected library. Including
this header file and using the empty namespace macros will allow for the
crypto library to be selected dynamically.
See the explicit usage section for the difference
between the all
and referenced
libraries.
See intree.cmake
on how to use the individual cmake functions in your project
for more control. Each of the cmake functions is documented.
Is not-yet fully functional since the crypto::derivation_to_scalar
from the
Monero source tree is still needed. However this is a proof-of-concept that
will be useful for testing if your project does not use cmake.
Running cmake <source_path> . && make && sudo make install
will autodetect
the best crypto library, build it in the current directory, and then install to
the default location for your system. An error is generated if your target
platform does not have a supported crypto library. The auto-selected library
can be overriden with -DMONERO_CRYPTO_LIBRARY=amd64-51-30k
at the first
cmake step. Using -DMONERO_CRYPTO_LIBRARY=invalid
will generate an error
that displays all available crypto libraries.