You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
6.0 KiB

# Supercop
> 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 - specifically
> `crypto::derivation_to_scalar`. So currently this project provides
> performance enhancements but not standalone usage.
## 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).
## C Wallet Functions
Every cryptographic library implements:
- **`monero_crypto_<namespace>_scalarmult(char* out, const char* pub, const char* sec)`** -
where `out` is the shared secret, `pub` is an ed25519 public key, and `sec`
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)`** -
where `out` is the shared secret, `tx_pub` is the public key from the
transaction and `view_sec` is the users view-key secret.
- **`monero_crypto_<namespace>_generate_subaddress_public_key(char* out, const char* output_pub, const char* special_sec)`** -
where `out` is the computed spend-public (primary or subaddress),
`output_pub` is the public key from the transaction output, and
`special_sec` is the output from `crypto::derivation_to_scalar` (which is
given the shared secret from `generate_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.
## CMake Usage
### Explicit Library Usage
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`.
## Basic In-Tree Dynamic Usage
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](#c-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](#explicit-library-usage) for the difference
between the `all` and `referenced` libraries.
## Advanced In-Tree Dynamic Usage
See `intree.cmake` on how to use the individual cmake functions in your project
for more control. Each of the cmake functions is documented.
## Standalone Usage
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.