Fast and efficient ed25519 signing and verification in Rust.

Overview

ed25519-dalek

Fast and efficient Rust implementation of ed25519 key generation, signing, and verification in Rust.

Documentation

Documentation is available here.

Installation

To install, add the following to your project's Cargo.toml:

[dependencies.ed25519-dalek]
version = "1"

Benchmarks

On an Intel Skylake i9-7900X running at 3.30 GHz, without TurboBoost, this code achieves the following performance benchmarks:

∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench
   Compiling ed25519-dalek v0.7.0 (file:///home/isis/code/rust/ed25519-dalek)
    Finished release [optimized] target(s) in 3.11s
      Running target/release/deps/ed25519_benchmarks-721332beed423bce

Ed25519 signing                     time:   [15.617 us 15.630 us 15.647 us]
Ed25519 signature verification      time:   [45.930 us 45.968 us 46.011 us]
Ed25519 keypair generation          time:   [15.440 us 15.465 us 15.492 us]

By enabling the avx2 backend (on machines with compatible microarchitectures), the performance for signature verification is greatly improved:

∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ export RUSTFLAGS=-Ctarget_cpu=native
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench --features=avx2_backend
   Compiling ed25519-dalek v0.7.0 (file:///home/isis/code/rust/ed25519-dalek)
    Finished release [optimized] target(s) in 4.28s
      Running target/release/deps/ed25519_benchmarks-e4866664de39c84d
Ed25519 signing                     time:   [15.923 us 15.945 us 15.967 us]
Ed25519 signature verification      time:   [33.382 us 33.411 us 33.445 us]
Ed25519 keypair generation          time:   [15.246 us 15.260 us 15.275 us]

In comparison, the equivalent package in Golang performs as follows:

∃!isisⒶmistakenot:(master *=)~/code/go/src/github.com/agl/ed25519 ∴ go test -bench .
BenchmarkKeyGeneration     30000             47007 ns/op
BenchmarkSigning           30000             48820 ns/op
BenchmarkVerification      10000            119701 ns/op
ok      github.com/agl/ed25519  5.775s

Making key generation and signing a rough average of 2x faster, and verification 2.5-3x faster depending on the availability of avx2. Of course, this is just my machine, and these results—nowhere near rigorous—should be taken with a handful of salt.

Translating to a rough cycle count: we multiply by a factor of 3.3 to convert nanoseconds to cycles per second on a 3300 Mhz CPU, that's 110256 cycles for verification and 52618 for signing, which is competitive with hand-optimised assembly implementations.

Additionally, if you're using a CSPRNG from the rand crate, the nightly feature will enable u128/i128 features there, resulting in potentially faster performance.

If your protocol or application is able to batch signatures for verification, the verify_batch() function has greatly improved performance. On the aforementioned Intel Skylake i9-7900X, verifying a batch of 96 signatures takes 1.7673ms. That's 18.4094us, or roughly 60750 cycles, per signature verification, more than double the speed of batch verification given in the original paper (this is likely not a fair comparison as that was a Nehalem machine). The numbers after the / in the test name refer to the size of the batch:

∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ export RUSTFLAGS=-Ctarget_cpu=native
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench --features=avx2_backend batch
   Compiling ed25519-dalek v0.8.0 (file:///home/isis/code/rust/ed25519-dalek)
    Finished release [optimized] target(s) in 34.16s
      Running target/release/deps/ed25519_benchmarks-cf0daf7d68fc71b6
Ed25519 batch signature verification/4   time:   [105.20 us 106.04 us 106.99 us]
Ed25519 batch signature verification/8   time:   [178.66 us 179.01 us 179.39 us]
Ed25519 batch signature verification/16  time:   [325.65 us 326.67 us 327.90 us]
Ed25519 batch signature verification/32  time:   [617.96 us 620.74 us 624.12 us]
Ed25519 batch signature verification/64  time:   [1.1862 ms 1.1900 ms 1.1943 ms]
Ed25519 batch signature verification/96  time:   [1.7611 ms 1.7673 ms 1.7742 ms]
Ed25519 batch signature verification/128 time:   [2.3320 ms 2.3376 ms 2.3446 ms]
Ed25519 batch signature verification/256 time:   [5.0124 ms 5.0290 ms 5.0491 ms]

As you can see, there's an optimal batch size for each machine, so you'll likely want to test the benchmarks on your target CPU to discover the best size. For this machine, around 100 signatures per batch is the optimum:

Additionally, thanks to Rust, this implementation has both type and memory safety. It's also easily readable by a much larger set of people than those who can read qhasm, making it more readily and more easily auditable. We're of the opinion that, ultimately, these features—combined with speed—are more valuable than simply cycle counts alone.

A Note on Signature Malleability

The signatures produced by this library are malleable, as discussed in the original paper:

While the scalar component of our Signature struct is strictly not malleable, because reduction checks are put in place upon Signature deserialisation from bytes, for all types of signatures in this crate, there is still the question of potential malleability due to the group element components.

We could eliminate the latter malleability property by multiplying by the curve cofactor, however, this would cause our implementation to not match the behaviour of every other implementation in existence. As of this writing, RFC 8032, "Edwards-Curve Digital Signature Algorithm (EdDSA)," advises that the stronger check should be done. While we agree that the stronger check should be done, it is our opinion that one shouldn't get to change the definition of "ed25519 verification" a decade after the fact, breaking compatibility with every other implementation.

However, if you require this, please see the documentation for the verify_strict() function, which does the full checks for the group elements. This functionality is available by default.

If for some reason—although we strongely advise you not to—you need to conform to the original specification of ed25519 signatures as in the excerpt from the paper above, you can disable scalar malleability checking via --features='legacy_compatibility'. WE STRONGLY ADVISE AGAINST THIS.

The legacy_compatibility Feature

By default, this library performs a stricter check for malleability in the scalar component of a signature, upon signature deserialisation. This stricter check, that s < \ell where \ell is the order of the basepoint, is mandated by RFC8032. However, that RFC was standardised a decade after the original paper, which, as described above, (usually, falsely) stated that malleability was inconsequential.

Because of this, most ed25519 implementations only perform a limited, hackier check that the most significant three bits of the scalar are unset. If you need compatibility with legacy implementations, including:

  • ed25519-donna
  • Golang's /x/crypto ed25519
  • libsodium (only when built with -DED25519_COMPAT)
  • NaCl's "ref" implementation
  • probably a bunch of others

then enable ed25519-dalek's legacy_compatibility feature. Please note and be forewarned that doing so allows for signature malleability, meaning that there may be two different and "valid" signatures with the same key for the same message, which is obviously incredibly dangerous in a number of contexts, including—but not limited to—identification protocols and cryptocurrency transactions.

The verify_strict() Function

The scalar component of a signature is not the only source of signature malleability, however. Both the public key used for signature verification and the group element component of the signature are malleable, as they may contain a small torsion component as a consquence of the curve25519 group not being of prime order, but having a small cofactor of 8.

If you wish to also eliminate this source of signature malleability, please review the documentation for the verify_strict() function.

A Note on Randomness Generation

The original paper's specification and the standarisation of RFC8032 do not specify precisely how randomness is to be generated, other than using a CSPRNG (Cryptographically Secure Random Number Generator). Particularly in the case of signature verification, where the security proof relies on the uniqueness of the blinding factors/nonces, it is paramount that these samples of randomness be unguessable to an adversary. Because of this, a current growing belief among cryptographers is that it is safer to prefer synthetic randomness.

To explain synthetic randomness, we should first explain how ed25519-dalek handles generation of deterministic randomness. This mode is disabled by default due to a tiny-but-not-nonexistent chance that this mode will open users up to fault attacks, wherein an adversary who controls all of the inputs to batch verification (i.e. the public keys, signatures, and messages) can craft them in a specialised manner such as to induce a fault (e.g. causing a mistakenly flipped bit in RAM, overheating a processor, etc.). In the deterministic mode, we seed the PRNG which generates our blinding factors/nonces by creating a PRNG based on the Fiat-Shamir transform of the public inputs. This mode is potentially useful to protocols which require strong auditability guarantees, as well as those which do not have access to secure system-/chip- provided randomness. This feature can be enabled via --features='batch_deterministic'. Note that we do not support deterministic signing, due to the numerous pitfalls therein, including a re-used nonce accidentally revealing the secret key.

In the default mode, we do as above in the fully deterministic mode, but we ratchet the underlying keccak-f1600 function (used for the provided transcript-based PRNG) forward additionally based on some system-/chip- provided randomness. This provides synthetic randomness, that is, randomness based on both deterministic and undeterinistic data. The reason for doing this is to prevent badly seeded system RNGs from ruining the security of the signature verification scheme.

Features

#![no_std]

This library aims to be #![no_std] compliant. If batch verification is required (--features='batch'), please enable either of the std or alloc features.

Nightly Compilers

To cause your application to build ed25519-dalek with the nightly feature enabled by default, instead do:

[dependencies.ed25519-dalek]
version = "1"
features = ["nightly"]

To cause your application to instead build with the nightly feature enabled when someone builds with cargo build --features="nightly" add the following to the Cargo.toml:

[features]
nightly = ["ed25519-dalek/nightly"]

Serde

To enable serde support, build ed25519-dalek with the serde feature.

(Micro)Architecture Specific Backends

By default, ed25519-dalek builds against curve25519-dalek's u64_backend feature, which uses Rust's i128 feature to achieve roughly double the speed as the u32_backend feature. When targetting 32-bit systems, however, you'll likely want to compile with cargo build --no-default-features --features="u32_backend". If you're building for a machine with avx2 instructions, there's also the experimental simd_backends, currently comprising either avx2 or avx512 backends. To use them, compile with RUSTFLAGS="-C target_cpu=native" cargo build --no-default-features --features="simd_backend"

Batch Signature Verification

The standard variants of batch signature verification (i.e. many signatures made with potentially many different public keys over potentially many different message) is available via the batch feature. It uses synthetic randomness, as noted above.

Deterministic Batch Signature Verification

The same notion of batch signature verification as above, but with purely deterministic randomness can be enabled via the batch_deterministic feature.

Comments
  • `rand` update to v0.8

    `rand` update to v0.8

    The package rand has been updated to v0.8.X. As this crate used rand v0.7.X it is not compatible with the current version (1.0.1) of this crate.

    And will show error like this:

    error[E0277]: the trait bound `OsRng: rand_core::CryptoRng` is not satisfied
       --> lib.rs:20:46
        |
    315 |     let keypair: Keypair = Keypair::generate(&mut csprng);
        |                                              ^^^^^^^^^^^ the trait `rand_core::CryptoRng` is not implemented for `OsRng`
        | 
       ::: ed25519-dalek-1.0.1/src/keypair.rs:129:12
        |
    129 |         R: CryptoRng + RngCore,
        |            --------- required by this bound in `Keypair::generate`
    
    error[E0277]: the trait bound `OsRng: rand_core::RngCore` is not satisfied
       --> lib.rs:20:46
        |
    315 |     let keypair: Keypair = Keypair::generate(&mut csprng);
        |                                              ^^^^^^^^^^^ the trait `rand_core::RngCore` is not implemented for `OsRng`
        | 
       ::: ed25519-dalek-1.0.1/src/keypair.rs:129:24
        |
    129 |         R: CryptoRng + RngCore,
        |                        ------- required by this bound in `Keypair::generate`
    

    On the code that looks like this (similar to example code in documentation).

    use rand::rngs::OsRng;
    
    let mut csprng = OsRng {};
    let keypair: Keypair = Keypair::generate(&mut csprng);
    

    So for the next version of this crate the rand version should be updated. Current workaround is to downgrade to rand version 0.7.X.

    opened by ralpha 28
  • restrict ExpandedSK::sign visibility to avoid pk oracle

    restrict ExpandedSK::sign visibility to avoid pk oracle

    The least disruptive API changes might be turn ExpandedSecretKey::sign_*() to pub(crate), leaving only the correct KeyPair.sign_*() API for signing to public invocation, which is always correct and not vulnerable to "Signing Function Oracle" attack.

    opened by alxiong 26
  • Consider using traits/types from the 'signature' and 'ed25519' crates?

    Consider using traits/types from the 'signature' and 'ed25519' crates?

    NOTE: PR open with these proposed changes here #124

    Problem

    Crates which use Ed25519 as part of a high-level protocol implementation or abstract signature functionality who want to enable the consumers of their crates to be able to use their choice of Rust Ed25519 libraries wind up writing their own abstractions to do so on a crate-by-crate basis.

    Here's an example from the Noise Protocol implementation snow, which does not (yet) use Ed25519 signatures, but I hope still illustrates the point:

    Screen Shot 2019-03-24 at 5 02 24 PM

    Instead of every crate which wants to do this having to wrangle a silly zoo of optional crypto crates dependencies, a better approach would be to define a common set of traits for how to produce (Ed25519) signatures, and encourage algorithm "provider" crates to impl those traits. This makes it easy to, say, use ed25519-dalek as a software signing crate while also supporting the yubihsm crate for hardware-backed Ed25519 signatures.

    signature crate

    I've been working with @newpavlov via the RustCrypto GH org to create a crate which provides abstract digital signature functionality, which I plan on using to rewrite the internals of Signatory, an existing multi-provider digital signature library.

    Where Signatory provides a set of compatible "provider" crates, e.g. signatory-dalek, what I would really love to do as part of a minimalist rewrite is also get crypto library authors to adopt the traits directly into their libraries instead of using "wrapper" crates which impl the relevant traits. And congratulations, you're the first project I'm pinging.

    I've just opened a PR to the signature crate which implements the initial set of signing traits:

    https://github.com/RustCrypto/signatures/pull/7

    (Sidebar: If you see anything you don't like there, please let us know! This is the first major non-boilerplate PR to the crate, so now is a great time to fix anything you don't like about it)

    Namely it has traits like these:

    pub trait Sign<S: Signature>: Send + Sync {
        fn sign(&self, msg: &[u8]) -> Result<S, Error>;
    }
    
    pub trait Verify<S: Signature>: Send + Sync {
        fn verify(&self, msg: &[u8], signature: &S) -> Result<(), Error>;
    }
    

    These traits provide equivalent methods to the existing Keypair::sign and PublicKey::verify methods (the only difference being the Sign trait returns a Result for its sign method, in which case it might be worth considering separating sign from try_sign so people who don't care about things like HSM errors don't always need to call unwrap).

    Having people import an additional trait is, I will admit, mildly annoying, but I imagine most people are copying/pasting the relevant code, so adding an additional import is not that annoying. You can re-export the relevant traits similar to what you're already doing for Digest.

    ed25519 crate

    ~~For true interop, crates need to agree on at least an ed25519::Signature type. That said, the ed25519 crate is presently vaporware and these types don't yet exist.~~ Update: it's real, and used in production in a few crates, e.g. yubihsm.

    One option, if you are so inclined as authors of what is pretty much the definitive Rust Ed25519 crate, would be to upstream the existing Signature type into the ed25519 crate.

    All that said, I'm happy to both make changes to the signature crate as well as put in a PR to ed25519-dalek to switch to using these traits once we publish the initial signature crate. Let me know if you're interested!

    opened by tarcieri 21
  • Fix serde implementation

    Fix serde implementation

    In serde, the fixed length byte array (i.e. [u8; LENGTH]) and normal byte array (i.e., &[u8]) are two different data types. In the previous implementation, these two data types are mixed together. As such, the deserialization operation will fail for certain encoding like json.

    This PR fixes this issue by using the fixed length byte array as the serde internal data types for all data structures. This also comes with the benefit to reduce the size of the encoded data.

    We also add more tests to prevent future breakage.

    Noted that this PR introduced breaking changes. However, the previous serde implementation was already partially broken.

    opened by xu-cheng 17
  • Remove rand from public api.

    Remove rand from public api.

    I expect for most users this is fine, and if some user would like to use a different Rng they can use the from_bytes call.

    Since rand has a history of causing breakage in ed25519-dalek I think this change could be justified as a bug fix.

    Also updates the dependencies to new versions where appropriate.

    Closes #160 Closes #159 Closes #162

    opened by dvc94ch 16
  • no_std fails to build

    no_std fails to build

    Reproduce:

    build the following minimal crate: https://github.com/scs/test-no-std/tree/ed25519-dalek

    cargo build --no-default-features results in

    error: duplicate lang item in crate `std`: `f32_runtime`.
      |
      = note: first defined in crate `sgx_tstd`.
    
    error: duplicate lang item in crate `std`: `f64_runtime`.
      |
      = note: first defined in crate `sgx_tstd`.
    
    error: duplicate lang item in crate `std`: `panic_impl`.
      |
      = note: first defined in crate `sgx_tstd`.
    
    error: duplicate lang item in crate `std`: `begin_panic`.
      |
      = note: first defined in crate `sgx_tstd`.
    
    error: duplicate lang item in crate `std`: `oom`.
      |
      = note: first defined in crate `sgx_tstd`.
    
    error: aborting due to 5 previous errors
    
    error: Could not compile `test_no_std`.
    
    
    opened by brenzi 12
  • Reduce the number of PublicKey decompressions

    Reduce the number of PublicKey decompressions

    When interacting with other Ed25519 libraries one might need to be able to bring in a Public Key which is in x + y form ([u8,64]). One might also want to export the x + y form.

    Neither of these use cases is currently supported by ed25519-dalek, which can be a deal breaker for some users. Is there something I'm missing that would allow the export of the public key in expanded form? Is there interest in adding this kind of support if it's not already possible?

    enhancement question 
    opened by coltfred 12
  • semver break in 1.0.0-pre.4

    semver break in 1.0.0-pre.4

    Steps to reproduce

    Cloning into 'rustup3'...
    remote: Enumerating objects: 17372, done.        
    remote: Total 17372 (delta 0), reused 0 (delta 0), pack-reused 17372        
    Receiving objects: 100% (17372/17372), 6.09 MiB | 1.12 MiB/s, done.
    Resolving deltas: 100% (11820/11820), done.
    rustcargo@zealot:~/Rustup/Itself$ cd rustup3/
    rustcargo@zealot:~/Rustup/Itself/rustup3$ cargo build
    ...
       Compiling ed25519-dalek v1.0.0-pre.3
    ...
        Finished dev [unoptimized + debuginfo] target(s) in 1m 19s
    

    Observe that the build works, and that this is with 1.0.0-pre3. Now switch to 1.0.0-pre4:

    rustcargo@zealot:~/Rustup/Itself/rustup3$ cargo update -p ed25519-dalek --precise 1.0.0-pre.4
        Updating crates.io index
          Adding ed25519 v1.0.1
        Updating ed25519-dalek v1.0.0-pre.3 -> v1.0.0-pre.4
          Adding signature v1.1.0
    rustcargo@zealot:~/Rustup/Itself/rustup3$ cargo build                                        
       Compiling signature v1.1.0
       Compiling rustup v1.22.1 (/volatile/rustcargo/Rustup/Itself/rustup3)
       Compiling ed25519 v1.0.1
       Compiling ed25519-dalek v1.0.0-pre.4
       Compiling pgp v0.5.2
    error[E0599]: no function or associated item named `from_bytes` found for struct `ed25519_dalek::Signature` in the current scope
      --> /home/rustcargo/.cargo/registry/src/github.com-1ecc6299db9ec823/pgp-0.5.2/src/crypto/eddsa.rs:58:49
       |
    58 |             let sig = ed25519_dalek::Signature::from_bytes(&sig_bytes)?;
       |                                                 ^^^^^^^^^^
       |                                                 |
       |                                                 function or associated item not found in `ed25519_dalek::Signature`
       |                                                 help: there is an associated function with a similar name: `to_bytes`
       |
       = help: items from traits can only be used if the trait is in scope
       = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
               `use ed25519_dalek::ed25519::signature::Signature;`
    
    error[E0599]: no method named `verify` found for struct `ed25519_dalek::PublicKey` in the current scope
      --> /home/rustcargo/.cargo/registry/src/github.com-1ecc6299db9ec823/pgp-0.5.2/src/crypto/eddsa.rs:60:16
       |
    60 |             pk.verify(hashed, &sig)?;
       |                ^^^^^^ method not found in `ed25519_dalek::PublicKey`
       |
       = help: items from traits can only be used if the trait is in scope
       = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
               `use ed25519_dalek::Verifier;`
    
    error[E0599]: no method named `sign` found for struct `ed25519_dalek::Keypair` in the current scope
      --> /home/rustcargo/.cargo/registry/src/github.com-1ecc6299db9ec823/pgp-0.5.2/src/crypto/eddsa.rs:83:24
       |
    83 |     let signature = kp.sign(digest);
       |                        ^^^^ method not found in `ed25519_dalek::Keypair`
       |
       = help: items from traits can only be used if the trait is in scope
       = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
               `use ed25519_dalek::Signer;`
    
    error: aborting due to 3 previous errors
    
    For more information about this error, try `rustc --explain E0599`.
    error: could not compile `pgp`.
    
    To learn more, run the command again with --verbose.
    rustcargo@zealot:~/Rustup/Itself/rustup3$ 
    

    Sorry for not minimising this further. I tried producing a repro based only on rpgp, but ran into probably-unrelated trouble.

    cc @kinnison

    opened by ijackson 11
  • Change from_bytes methods to take fixed-size array argument

    Change from_bytes methods to take fixed-size array argument

    Change from_bytes methods of all the types to take &[u8; N] argument (with N appropriate for given type) rather than &[u8]. This does a few things:

    • it makes SecretKey::from_bytes infallible which will simplify call sites (if the call site already has properly-sized array),
    • harmonises the convention with ed25519::Signature::from_bytes method and
    • encodes the size of the bytes representation in type system which means that users can assert it at compile time.

    To still allow creating the objects from a slice whose size is checked at run time, introduce TryFrom<&[u8]> implementations for affected public types.

    This is an API breaking change. The simplest way to update existing code is to replace Foo::from_bytes with Foo::try_from. This should cover majority of uses.

    opened by mina86 10
  • PKCS#8 support

    PKCS#8 support

    ~~NOTE: depends on #222 and #223 which need to be merged first.~~

    Adds optional integration with ed25519::pkcs8 with support for decoding/encoding Keypair from/to PKCS#8-encoded documents.

    ~~TODO: support for decoding/encoding PublicKey from/to SPKI documents.~~ Added, good to go!

    opened by tarcieri 10
  • Use `SigningKey`/`VerifyingKey` naming convention?

    Use `SigningKey`/`VerifyingKey` naming convention?

    In the @RustCrypto project we have adopted a convention of naming signature keys SigningKey and VerifyingKey which describes keys by their roles in a signature system.

    The basic pitch is that such names are clearer and more intuitive to users who don't necessarily have a background in cryptography.

    Would it make sense to adopt similar names in this crate?

    opened by tarcieri 9
  • Bump `ed25519` crate to v2.0.0-rc.1

    Bump `ed25519` crate to v2.0.0-rc.1

    This transitively updates signature to v2.0.0-rc.1, which contains RNG API changes which don't impact ed25519-dalek, as it doesn't use or enable the RNG API.

    opened by tarcieri 0
  • Use `curve25519-dalek` from git; check in Cargo.lock

    Use `curve25519-dalek` from git; check in Cargo.lock

    Updates to the latest upstream changes in curve25519-dalek, including using the new EdwardsPoint::mul_base API.

    To keep the build deterministic, this also checks in Cargo.lock, which pins curve25519-dalek to a particular git commit SHA which can be updated using cargo update -p curve25519-dalek.

    We can potentially remove Cargo.lock again after a crate release.

    opened by tarcieri 1
  • Make `verify_batch` deterministic

    Make `verify_batch` deterministic

    Previously we had batch and batch_deterministic features, which would do a different thing under the hood depending on what you picked. This PR removes all nondeterminism from batch verification, and simply uses Merlin for everything. This is for a few reasons:

    1. Having 2 mutually exclusive flags is a pain point in the API. And splitting them into two functions is similarly annoying.
    2. I couldn't find any arguments for the use of nondeterminism in batch verif. There's the old docs (which this PR deletes), which links to Merlin's reasoning and Trevor Perrin's reasoning, but they are talking about signing, not verifying. It is perfectly sound to use Merlin to apply the Fiat-Shamir transform to this protocol and use its randomness for verification.

    I only have two arguments against this PR:

    1. If there is any part of the transcript that we did not properly hash into the context, it could allow an attacker to brute force a transcript that causes verify_batch to succeed on a bad signature. I think this is unlikely, given the transcript hash is done in 3 lines and consumes literally every input to the function in the process. Unfortunately, this claim requires some deep code checking. For example, the signatures that are hashed are actually the result of InternalSignature::into. Is this accidentally two-to-one? The answer is no but it requires you to check how scalars and points are deserialized. I don't think there's a problem here, but I can make the code more obviously correct by hashing in the un-converted input values. Update: I did this
    2. You could brute-force verif so that it succeeds on specific ill-formed pubkey-signature pairs (i.e., the low-order R and A values that pass our validation criteria). However, even a nondeterministic batch function will succeed on these batches with 1/8 probability (technically, (1/8)^n for n such items in a batch). How much do we care if the alternative has such a high likelihood of false positive as well? I think this if anything, this is a good argument to use the batched equation, which multiplies by the cofactor and accepts all of these 100% of the time.
    opened by rozbb 2
  • Add on-by-default `fast` crate feature for gating basepoint tables

    Add on-by-default `fast` crate feature for gating basepoint tables

    ~~NOTE: depends on https://github.com/dalek-cryptography/curve25519-dalek/pull/489 which needs to be merged first~~ Merged!

    NOTE: now depends on #260 which needs to be merged first

    Disabling the feature reduces overall code size at the cost of performance, which is useful for e.g. embedded users.

    This feature transitively enables the basepoint-tables feature in curve25519-dalek.

    ~~TODO: fallback support for using variable-base scalar multiplication by the basepoint when the basepoint-tables feature is disabled.~~ Added in 8f56c5c

    opened by tarcieri 2
  • Generic `to_radix_2w` Function

    Generic `to_radix_2w` Function

    Hello. Please forgive my ignorance, but the radix documentation states that radices greater than 256 are prohibited, and radix 32 is unsupported. It says higher radices are not supported to save cache space, but my understanding is that generalizing the function would not incur additional cache costs for the existing racides. Would it be advantageous, then, to write a generic radix function, like to_radix_2W<const W: usize> -> [i8; (256 + W - 1)/W + 1], or, if generic const expressions are permissible, to_radix_2W<const W: usize> -> [i8; to_radix_2w_size_hint(W)] Theres obviously the possibility that this introduces some side channel attack, but, if this is the case, could this be documented? Even so, I think it would be safer to have an implementation for higher radices here, where it can be audited with everything else, than have every library user write their own, each with their own attack surfaces. I want to be very careful about timing and cache vulnerabilities here particularly, but I also want larger radices, so I'm really not sure what to do here. Any advice would be appreciated. Thank you!

    opened by based-a-tron 0
Owner
dalek cryptography
Fast, safe, pure-rust elliptic curve cryptography
dalek cryptography
Freelance payment protocol written in Rust.. (with multi-sig signing for dispute settling)

Freelance Escrow payment protocol ?? About The freelance protocol is a protocol built on decentralized and open systems such as blockchain and decentr

Femi Bolaji 4 Jan 3, 2023
A library facilitating the signing and broadcasting of transactions on Cosmos SDK-based blockchains

txf Transaction factory - a library facilitating the signing and broadcasting of transactions (txs) on Cosmos SDK-based blockchains. How to use Exampl

larry 5 Jun 29, 2023
Like a thread pool, but for signing and broadcasting transactions

ethers-signer-pool This library provides a utility built on top of the ethers crate. The purpose of the utility is to provide a pool of signers (walle

Shaurya Arora 3 Aug 14, 2023
Key derivation and cryptographic signing functionality for Ethereum applications (ethers-rs)

ethers-signer-factory ethers-signer-factory is a Rust crate that provides functions for key derivation and signing of Ethereum transactions and messag

Ilia 3 Sep 27, 2023
deductive verification of Rust code. (semi) automatically prove your code satisfies your specifications!

Le marteau-pilon, forges et aciéries de Saint-Chamond, Joseph-Fortuné LAYRAUD, 1889 About Creusot is a tool for deductive verification of Rust code. I

Xavier Denis 609 Dec 28, 2022
An implementation of NZ COVID Pass verification written in Rust

NZCP Rust   An implementation of NZ COVID Pass verification, New Zealand's proof of COVID-19 vaccination solution, written in Rust ?? We also have a J

Vaxx.nz 7 Nov 24, 2022
RSA dependency for rust, with cert verification

About Project End to End encryption (RSA) for multiple languages (cross-platform) with double encryption and double decryption methods Icon Item ?? Up

Zot Cryptography 2 Nov 27, 2022
A certificate verification library for rustls that uses the operating system's verifier

rustls-platform-verifier A Rust library to verify the validity of TLS certificates based on the operating system's certificate facilities. On operatin

null 17 Dec 26, 2022
A certificate verification library for rustls that uses the operating system's verifier

rustls-platform-verifier A Rust library to verify the validity of TLS certificates based on the operating system's certificate facilities. On operatin

null 13 Nov 6, 2022
Simple, reliable, open-source contract verification built for an L2 centric Ethereum ecosystem

Cove This repo contains the backend verification1 code for Cove, a simple, reliable, open-source contract verification built for an L2 centric Ethereu

ScopeLift 12 Apr 1, 2023
specs & benchmarks for the ZPrize 3 - High Throughput Signature Verification

Zprize: High Throughput Signature Verification How fast do you think you can verify our ECDSA signatures on Aleo? This year's Zprize is winner-take-al

null 6 Oct 21, 2023
An efficient, robust, and generalized batch submission service for rollup stacks written in pure rust.

archon is an efficient, robust, and generalized batch submission service for rollup stacks written in pure rust. Note Archon is primarily tested again

refcell.eth 75 Apr 2, 2023
Efficient state-based CRDT replication and anti-entropy

Merkle Search Tree This crate implements a Merkle Search Tree as described in the 2019 paper Merkle Search Trees: Efficient State-Based CRDTs in Open

Dom 5 Jul 9, 2023
Vanitygen-bip39 - Generate vanity / gas efficient Ethereum addresses for your hdwallet (bip39 12 or 24 words)

vanitygen-bip39 Generate Ethereum gas efficient addresses with leading zeros https://medium.com/coinmonks/on-efficient-ethereum-addresses-3fef0596e263

iam4x 9 Jul 2, 2022
A sparse merkle tree lib focused on efficient on-chain proofs. Enforces ordering within the merkle tree.

sparse-merkle-tree The merkle tree functions are located in sparse.ak. Currently the supported functionality is: Verifying a new root with an added me

Aiken 5 May 6, 2024
Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.

foundry Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust. Foundry consists of: Forge: Ethe

Georgios Konstantopoulos 5.1k Jan 9, 2023
A lightning-fast password generator and manager written in Rust

Passlane A lightning-fast password manager for the command line Features Generate passwords Place the generated password into the clipboard Save previ

Anssi Piirainen 4 Dec 15, 2022
Fast(er) AES-based constructions for WebAssembly and Rust.

Fast(er) AES-based constructions for Rust and WebAssembly AEGIS-128L AEGIS-256 AES-128-CTR AES-256-CTR AES-128-OCB AES-256-OCB AES-128-GCM AES-256-GCM

Frank Denis 5 May 31, 2023