* upgrade curve25519-dalek to 4.0.0-rc.2
* clippy fixes
* activate ed25519/pem only when needed
* bump to 4.0.0; bump MSRV to 1.65; fix no_std support; test MSRV and no_std in CI
* use rust-toolchain instead of TOML to work with (unmaitained) actions-rs/toolchain
* Add DER & PEM support for SigningKeySeed and VerificationKeyBytes (RFC 8410)
- Add encoding to and decoding from DER bytes and PEM strings for SigningKeySeed and VerificationKeyBytes.
- Add some functions so that the Java code mirrors, to a certain degree, the JDK 15 interface for Ed25519 keys and signatures.
- Add encoding and decoding for signatures (technically identity functions).
- Miscellaneous cleanup.
* Accommodate extra octet string in private key DER bytes
- In RFC 8410, DER-encoded private keys are in an octet string that's encapsulated by another octet string. Add the extra octet string, and adjust tests as necessary.
- In the tests, use the private key from RFC 8410, Sect. 10.3.
* Update pkcs8 to 0.7.0
* Cleanup
- Enhance PEM capabilities for SigningKey and VerificationKeyBytes. This also allowed for some tests to be simplified.
- From -> TryFrom for some VerificationKeyBytes impls.
* Upgrade JNI Rust bindings to PKCS8 0.7.5
- Make necessary changes to support the newer crate.
- Fix an unrelated compiler warning.
* More fixups
- Get code to compile after updating to the latest Rust.
- Fix a couple of failing tests (add LF to expected encoding output).
* Major update
- Update pkcs8 crate to 0.10.0, and update code as required to support the crate. This includes supporting the Decode(Public/Private)Key and Encode(Public/Private)Key traits so as to take advantage of Ed25519 DER and PEM code in the crate.
- Add the latest ed25519 crate (2.2.0) to support KeypairBytes and other features.
- Remove the signature code and implement Signature (Signer and Verifier traits) from the "signatures" crate included with the pkcs8 crate.
- Update the JNI code. This includes mandating Scala 3 usage.
- Minor cleanup (including warning fixes) and changes to make the code a bit clearer.
A follow-up commit will clean up the tests and probably add support for v2 private DER keys.
* Further code cleanup
- Update pkcs8 crate to 0.10.1.
- Fix PEM feature code.
- Update Ed25519 JNI code as needed.
- Remove dead code.
- Re-enable a couple of unit tests.
Note that a couple of Ed25519 JNI unit tests are still failing. A follow-up PR will have the fix.
* Add missing DER/PEM files for unit tests
* Add JNI comments to resolve publisher warnings
When executing `sbt publishLocal` and generating a JAR file, there are warnings regarding some functions not having public comments. Add public comments as needed.
* JNI README update
* Comment touchup
* Review fixups
- Finish adding PEM/PKCS8 tags and cfg items as needed to separate the features from default compilation.
- Revert some minor name changes.
- Make the JNI README more precise with regards to requirements.
- Add ARM64 macOS support to JNI. Untested but it should work, and it doesn't break Intel Macs.
- Miscellaneous cleanup, including fixing cargo and sbt warnings.
* Upgrade jni crate to 0.20.0
The 0.21.X crates feature a major refactor that breaks the code. Don't upgrade to them until some issues are resolved. (See https://github.com/jni-rs/jni-rs/issues/432 for more info.)
* Upgrade jni crate to 0.21.1
- A path forward to upgrading to 0.21.X was suggested by the jni-rs library developer (https://github.com/jni-rs/jni-rs/issues/439#issuecomment-1493074721). Upgrade the code, improving the safety of the JNI code.
- Cargo.toml fixups.
* cargo clippy / cargo fmt cleanup
Also do minor JNI README cleanup.
* Use an export to clean up some tests a bit
---------
Co-authored-by: Douglas Roark <douglas.roark@gemini.com>
* Add batch::Item::verify_single and Item: Clone + Debug.
This closes a gap in the API where it was impossible to retry items in a failed
batch, because the opaque Item type could not be verified individually.
* Implement ZIP 215 validation rules.
These have the effect that batched and singleton verification are now
equivalent.
* Add ZIP 215 conformance tests.
This test constructs signatures on the message "Zcash" using small-order
verification keys, some with canonical and some with non-canonical encodings of
points. All of these signatures should pass verification under the ZIP 215
rules, but most of them should fail verification under legacy rules.
These tests exercise all of the special-case behaviors from the specific
version of libsodium used by Zcashd:
* the all-zero check for the verification key;
* the excluded point encodings for the signature's R value;
* the choice to test equality of the encoded bytes of the recomputed R value
rather than on the projective coordinates of the two points.
Running
```
cargo test -- --nocapture
```
will print a hex-formatted list of the test cases, which can also be found here:
https://gist.github.com/hdevalence/93ed42d17ecab8e42138b213812c8cc7
* Update spec links.
Thanks to @ebfull for pointing this out.
* No ... there is another.
@ebfull pointed out that two test cases were duplicates. The cause was that I
misread the RFC8032 check was checking for the non-canonical encoding of
the identity point that NCC Group apparently brought up. Carefully analyzing all
the cases instead of assuming reveals there is another non-canonically encoded
point (of order 2).
* Change formatting of printed test cases.
It's essential to be able to separate the lifetime of the batch item from the
lifetime of associated data (in this case, the message). The previous API did
this mixed in to the Tower implementation, but it was removed along with that
code.
Making the `queue` function take `I: Into<Item>` means that users who don't
care about lifetimes just need to wrap the function arguments in an extra
tuple.
These are better names than secret and public keys, because they concisely
describe the functional *role* of the key material, not just whether or not the
key is revealed.
The futures-based batch verification design is still good, but it turns out
that things like the latency bounds and control of when to flush the batch
should be common across different kinds of batchable verification. This should
be done by the forthcoming `tower-batch` middleware currently in the Zebra
repo.
This ensures that any
```
impl From<T> for [u8; N]
```
is accompanied by a matching
```
impl AsRef<[u8]> for T
```
except for Signature, whose internals have to change (issue #9).
This changes the `VerificationRequest` type alias (now called `batch::Request`)
to an enum containing either a verification request or a request to flush the
batch. This allows both automatic and manual control of batch sizes, either by
setting a low batch limit on service creation or by setting a high limit and
manually sending flush commands.
To keep things ergonomic, the `Request` enum now has a `impl From` the previous
tuple, so to send a request, all that's necessary is to assemble a
pubkey-sig-message tuple and call `.into()` on it.
This will hopefully allow things like building a Tower layer with a timeout and
a retry policy that retries timed out requests (not a big enough concurrent
batch) with singleton verification, or retries a failed batch by falling back
to singleton verification to detect which element of a batch failed.
However, there are still some rough spots in the API, and it's not clear that
manually dropping the service is an adequate way to flush requests (see comment).
This implements the last suggestion in the previous commit message: the
verification service maintains a target batch size and periodically flushes
signature verification requests after reaching that many pending requests.
Requests can be manually flushed by dropping the service. In contrast to
flushing requests by calling an inherent method, this approach has the
advantage that the verification service can be wrapped in other tower
middleware without losing functionality (drops propagate through wrapped
services).
This approach still does not impose any maximum latency on verification
requests, but it seems potentially better to leave that out of scope for the
verification service itself, as consumers wishing to have latency bounds can do
so using a timeout layer, perhaps with a retry policy that does singleton
verification after a timeout, etc.
This commit incidentally includes an optimization for batch verification that
improves performance when verifying multiple signatures from the same public
key.
I'm not totally happy with a few things about this API, however. Currently,
the actual batch computation is performed only when the inherent `finalize()`
method is called on the service. However, this doesn't work well with `tower`
layering, because once the service is wrapped, the inherent method is no longer
available. Another option would be for the batching service to be created with
a batch size parameter, automatically resolving the batch computation whenever
the batch size was reached. This improves latency but does not solve the
problem of finalizing the batch, since unless there's guaranteed to be a
constant stream of verification requests, a tail of requests may be left
unresolved. A third option would be for the service to return some kind of
control handle on creation that would allow shutdown via a channel or
something, but this is also unsatisfying because it means that the service has
to be listening for a shutdown signal. A fourth option would be to have a
batch size parameter but customize the `Drop` impl to finalize all pending
requests on drop; this would potentially allow "flushing" pending requests by
manually dropping the service in a way that would still be possible when using
tower wrappers.