diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/ecdsa | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ecdsa')
-rw-r--r-- | vendor/ecdsa/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/ecdsa/CHANGELOG.md | 455 | ||||
-rw-r--r-- | vendor/ecdsa/Cargo.toml | 126 | ||||
-rw-r--r-- | vendor/ecdsa/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | vendor/ecdsa/LICENSE-MIT | 25 | ||||
-rw-r--r-- | vendor/ecdsa/README.md | 93 | ||||
-rw-r--r-- | vendor/ecdsa/src/der.rs | 349 | ||||
-rw-r--r-- | vendor/ecdsa/src/dev.rs | 221 | ||||
-rw-r--r-- | vendor/ecdsa/src/hazmat.rs | 261 | ||||
-rw-r--r-- | vendor/ecdsa/src/lib.rs | 421 | ||||
-rw-r--r-- | vendor/ecdsa/src/recovery.rs | 110 | ||||
-rw-r--r-- | vendor/ecdsa/src/sign.rs | 424 | ||||
-rw-r--r-- | vendor/ecdsa/src/verify.rs | 325 | ||||
-rw-r--r-- | vendor/ecdsa/tests/lib.rs | 14 |
14 files changed, 3026 insertions, 0 deletions
diff --git a/vendor/ecdsa/.cargo-checksum.json b/vendor/ecdsa/.cargo-checksum.json new file mode 100644 index 000000000..3f233a5f2 --- /dev/null +++ b/vendor/ecdsa/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"3ce4bb9d644207d6be3015fb14fb8b21b5a5b1726d6e23e518069c09b72c3c6d","Cargo.toml":"8251cd573e1cccd72cc28d182555834efeced8c9b9b9d8b6f66dc45e66d7c88c","LICENSE-APACHE":"78779d420019e6b4630376af8e86b6b335ee8a2f89ede6e0411e0469a326aaa4","LICENSE-MIT":"bdebaf9156a298f8fdab56dd26cb5144673de522d80f4c0d88e0039145f147f9","README.md":"5b6363fc1dc18b5ea22dcb4e11481abd2c9fff9a5bce268296e119dc23cdc3d6","src/der.rs":"496d7b6047b4d346fa76c00b07db2cec06d935e552ced3abb939ea2a84a38c38","src/dev.rs":"2403e76837802f1587ea9b7da7ce62f6ae65b431691977f31bce71ae36639a05","src/hazmat.rs":"7baab4647e5e9fb2d918c69a8df557aef41e4b5cc92fc964592f315798603e40","src/lib.rs":"8a9f7e22c1ffe206eaaf0844ca4eaea29910f7cfd6dd61e3c95b1297c01931b0","src/recovery.rs":"7dd92127de3b33883ca1bf1eaadd4ce8176febe9b5c1353dc31fbee0c092a611","src/sign.rs":"6c360d0292e23c21dc5274a08ab98c5005df4b83a8d22871cfc91d4c413b0511","src/verify.rs":"19a759a7a8db7e0b17cbf6ba69a8fe2634089546b31a6423d86f8b693a6f1d7d","tests/lib.rs":"68922b3fb793f7f64a6fdf8aa59b6fb9432d4706d7ad1d82129a8337c5cf6568"},"package":"413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"}
\ No newline at end of file diff --git a/vendor/ecdsa/CHANGELOG.md b/vendor/ecdsa/CHANGELOG.md new file mode 100644 index 000000000..ba65d59cf --- /dev/null +++ b/vendor/ecdsa/CHANGELOG.md @@ -0,0 +1,455 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 0.14.8 (2022-09-27) +### Added +- Impl `From<SigningKey>` for `SecretKey` ([#548]) + +### Fixed +- Prehash must receive zero-pads on left ([#547]) + +[#547]: https://github.com/RustCrypto/signatures/pull/547 +[#548]: https://github.com/RustCrypto/signatures/pull/548 + +## 0.14.7 (2022-09-15) +### Changed +- Relax `Keypair` bounds ([#539]) + +[#539]: https://github.com/RustCrypto/signatures/pull/539 + +## 0.14.6 (2022-09-12) +### Added +- Impl `signature::hazmat::{PrehashSigner, PrehashVerifier}` ([#534]) +- Impl `signature::Keypair` for `SigningKey` ([#535]) + +[#534]: https://github.com/RustCrypto/signatures/pull/534 +[#535]: https://github.com/RustCrypto/signatures/pull/535 + +## 0.14.5 (2022-09-06) +### Added +- Impl `EncodePrivateKey` for `SigningKey` ([#523]) +- `SigningKey::as_nonzero_scalar` ([#528]) +- `VerifyingKey::as_affine` ([#528]) +- `RecoveryId::from_byte` ([#531]) + +### Changed +- Make `RecoveryId` methods `const fn` ([#529]) + +[#523]: https://github.com/RustCrypto/signatures/pull/523 +[#528]: https://github.com/RustCrypto/signatures/pull/528 +[#529]: https://github.com/RustCrypto/signatures/pull/529 +[#531]: https://github.com/RustCrypto/signatures/pull/531 + +## 0.14.4 (2022-08-15) +### Added +- Impl `EncodePublicKey` for `VerifyingKey` ([#505]) +- ZeroizeOnDrop marker for SigningKey ([#509]) + +### Changed +- Restrict `signature` version to v1.5-v1.6 ([#508], [#512]) + +[#505]: https://github.com/RustCrypto/signatures/pull/505 +[#508]: https://github.com/RustCrypto/signatures/pull/508 +[#509]: https://github.com/RustCrypto/signatures/pull/509 +[#512]: https://github.com/RustCrypto/signatures/pull/512 + +## 0.14.3 (2022-06-26) [YANKED] +### Changed +- Simplified digest trait bounds ([#499]) +- Bump `rfc6979` dependency to v0.3 ([#500]) + +[#499]: https://github.com/RustCrypto/signatures/pull/499 +[#500]: https://github.com/RustCrypto/signatures/pull/500 + +## 0.14.2 (2022-06-17) [YANKED] +### Added +- Security warning in README.md ([#486]) + +### Changed +- Use `serdect` for `Signature` types ([#497]) + +[#486]: https://github.com/RustCrypto/signatures/pull/486 +[#497]: https://github.com/RustCrypto/signatures/pull/497 + +## 0.14.1 (2022-05-09) [YANKED] +### Added +- `SignPrimitive::try_sign_digest_rfc6979` ([#475]) +- `VerifyPrimitive::verify_digest` ([#475]) + +[#475]: https://github.com/RustCrypto/signatures/pull/475 + +## 0.14.0 (2022-05-09) [YANKED] +### Added +- `VerifyingKey::from_affine` ([#452]) + +### Changed +- Bump `digest` dependency to v0.10 ([#433]) +- `SignPrimitive` and `VerifyPrimitive` to accept `FieldBytes<C>` rather than `Scalar<C>` ([#460]) +- Replace `hazmat::rfc6979_generate_k` with `SignPrimitive::try_sign_prehashed_rfc6979` ([#460]) +- Bump `der` dependency to v0.6 ([#468]) +- Bump `elliptic-curve` dependency to v0.12 ([#468]) +- Bump `rfc6979` dependency to v0.2 ([#470]) + +[#433]: https://github.com/RustCrypto/signatures/pull/433 +[#452]: https://github.com/RustCrypto/signatures/pull/452 +[#460]: https://github.com/RustCrypto/signatures/pull/460 +[#468]: https://github.com/RustCrypto/signatures/pull/468 +[#470]: https://github.com/RustCrypto/signatures/pull/470 + +## 0.13.4 (2022-01-06) +### Added +- `Signature::to_vec` ([#428]) + +[#428]: https://github.com/RustCrypto/signatures/pull/428 + +## 0.13.3 (2021-12-04) +### Changed +- Use revised `LinearCombination` trait ([#419]) + +[#419]: https://github.com/RustCrypto/signatures/pull/419 + +## 0.13.2 (2021-12-04) [YANKED] +### Changed +- Use `LinearCombination` trait ([#417]) + +[#417]: https://github.com/RustCrypto/signatures/pull/417 + +## 0.13.1 (2021-12-03) [YANKED] +### Added +- `hazmat::rfc6979_generate_k` function ([#414]) + +[#414]: https://github.com/RustCrypto/signatures/pull/414 + +## 0.13.0 (2021-11-21) [YANKED] +### Added +- `RecoveryId` type ([#392]) +- Default generic impl of `SignPrimitive::try_sign_prehashed` ([#396]) +- Default generic impl of `VerifyPrimitive::verify_prehashed` ([#397]) +- `serde` support ([#406]) + +### Changed +- Make `Signature::normalize_s` non-mutating ([#355]) +- Switch from `ScalarBytes<C>` to `ScalarCore<C>` ([#356]) +- Use `PrimeCurve` trait ([#357]) +- Replace `FromDigest` trait with `Reduce` ([#372]) +- 2021 edition upgrade; MSRV 1.56 ([#384]) +- Allow `signature` v1.4 as a dependency ([#385]) +- Bump `der` dependency to v0.5 ([#408]) +- Bump `elliptic-curve` dependency to v0.11 ([#408]) +- Split out `rfc6979` crate ([#409]) + +### Removed +- `NormalizeLow` trait ([#393]) +- `RecoverableSignPrimitive` ([#394]) + +[#355]: https://github.com/RustCrypto/signatures/pull/355 +[#356]: https://github.com/RustCrypto/signatures/pull/356 +[#357]: https://github.com/RustCrypto/signatures/pull/357 +[#372]: https://github.com/RustCrypto/signatures/pull/372 +[#384]: https://github.com/RustCrypto/signatures/pull/384 +[#385]: https://github.com/RustCrypto/signatures/pull/385 +[#392]: https://github.com/RustCrypto/signatures/pull/392 +[#393]: https://github.com/RustCrypto/signatures/pull/393 +[#394]: https://github.com/RustCrypto/signatures/pull/394 +[#396]: https://github.com/RustCrypto/signatures/pull/396 +[#397]: https://github.com/RustCrypto/signatures/pull/397 +[#406]: https://github.com/RustCrypto/signatures/pull/406 +[#408]: https://github.com/RustCrypto/signatures/pull/408 +[#409]: https://github.com/RustCrypto/signatures/pull/409 + +## 0.12.4 (2021-08-12) +### Added +- Impl `Clone`, `Debug`, `*Eq` for `SigningKey` ([#345]) + +[#345]: https://github.com/RustCrypto/signatures/pull/345 + +## 0.12.3 (2021-06-17) +### Added +- Impl `TryFrom<&[u8]>` for `Verifying<C>` ([#329]) +- Impl `TryFrom<&[u8]>` for `SigningKey<C>` ([#330]) + +### Changed +- Use `signature::Result` alias ([#331]) + +[#329]: https://github.com/RustCrypto/signatures/pull/329 +[#330]: https://github.com/RustCrypto/signatures/pull/330 +[#331]: https://github.com/RustCrypto/signatures/pull/331 + +## 0.12.2 (2021-06-18) +### Added +- Zeroization on drop for `SigningKey` ([#321]) + +[#321]: https://github.com/RustCrypto/signatures/pull/321 + +## 0.12.1 (2021-06-09) +### Added +- Explicit `Copy` bounds on `VerifyingKey` ([#318]) + +[#318]: https://github.com/RustCrypto/signatures/pull/318 + +## 0.12.0 (2021-06-07) +### Changed +- Bump `der` crate to v0.4 ([#302], [#315]) +- Bump `elliptic-curve` crate dependency to v0.10 ([#315]) +- MSRV 1.51+ ([#302], [#315]) + +### Removed +- Bounds now expressed via `*Arithmetic` traits ([#303], [#312]) + +[#302]: https://github.com/RustCrypto/signatures/pull/302 +[#303]: https://github.com/RustCrypto/signatures/pull/303 +[#315]: https://github.com/RustCrypto/signatures/pull/315 + +## 0.11.1 (2021-05-24) +### Added +- `Ord` and `PartialOrd` impls on VerifyingKey ([#298], [#299]) + +### Changed +- Bump `elliptic-curve` dependency to v0.9.12 ([#299]) + +[#298]: https://github.com/RustCrypto/signatures/pull/298 +[#299]: https://github.com/RustCrypto/signatures/pull/299 + +## 0.11.0 (2021-04-29) +### Added +- `FromDigest` trait ([#238], [#244]) +- Wycheproof test vector support ([#260]) + +### Changed +- Use `der` crate for decoding/encoding signatures ([#226], [#267]) +- Support `HmacDrbg` with variable output size ([#243]) +- Bump `base64ct` and `pkcs8`; MSRV 1.47+ ([#262]) +- Flatten and simplify public API ([#268]) +- Use `verifying_key` name consistently ([#273]) +- Bound curve implementations on Order trait ([#280]) +- Bump `elliptic-curve` to v0.9.10+; use `ScalarBytes` ([#284]) +- Bump `hmac` crate dependency to v0.11 ([#287]) + +### Removed +- `FieldBytes` bounds ([#227]) +- `CheckSignatureBytes` trait ([#281]) + +[#226]: https://github.com/RustCrypto/signatures/pull/226 +[#227]: https://github.com/RustCrypto/signatures/pull/227 +[#238]: https://github.com/RustCrypto/signatures/pull/238 +[#243]: https://github.com/RustCrypto/signatures/pull/243 +[#244]: https://github.com/RustCrypto/signatures/pull/244 +[#260]: https://github.com/RustCrypto/signatures/pull/260 +[#262]: https://github.com/RustCrypto/signatures/pull/262 +[#267]: https://github.com/RustCrypto/signatures/pull/267 +[#268]: https://github.com/RustCrypto/signatures/pull/268 +[#273]: https://github.com/RustCrypto/signatures/pull/273 +[#280]: https://github.com/RustCrypto/signatures/pull/280 +[#281]: https://github.com/RustCrypto/signatures/pull/281 +[#284]: https://github.com/RustCrypto/signatures/pull/284 +[#287]: https://github.com/RustCrypto/signatures/pull/287 + +## 0.10.2 (2020-12-22) +### Changed +- Bump `elliptic-curve` crate to v0.8.3 ([#218]) +- Use the `dev` module from the `elliptic-curve` crate ([#218]) + +[#218]: https://github.com/RustCrypto/signatures/pull/218 + +## 0.10.1 (2020-12-16) [YANKED] +### Fixed +- Trigger docs.rs rebuild with nightly bugfix ([RustCrypto/traits#412]) + +[RustCrypto/traits#412]: https://github.com/RustCrypto/traits/pull/412 + +## 0.10.0 (2020-12-16) [YANKED] +### Changed +- Bump `elliptic-curve` dependency to v0.8 ([#215]) + +[#215]: https://github.com/RustCrypto/signatures/pull/215 + +## 0.9.0 (2020-12-06) +### Added +- PKCS#8 support ([#203]) + +### Changed +- Bump `elliptic-curve` crate dependency to v0.7; MSRV 1.46+ ([#204]) +- Rename `VerifyKey` to `VerifyingKey` ([#200]) +- Rename `VerifyingKey::new()` to `::from_sec1_bytes()` ([#198]) +- Rename `SigningKey::new()` to `::from_bytes()` ([#205]) + +### Fixed +- Additional validity checks on ASN.1 DER-encoded signatures ([#192]) + +[#205]: https://github.com/RustCrypto/signatures/pull/205 +[#204]: https://github.com/RustCrypto/signatures/pull/204 +[#203]: https://github.com/RustCrypto/signatures/pull/203 +[#200]: https://github.com/RustCrypto/signatures/pull/200 +[#198]: https://github.com/RustCrypto/signatures/pull/198 +[#192]: https://github.com/RustCrypto/signatures/pull/192 + +## 0.8.5 (2020-10-09) +### Fixed +- Bug in default impl of CheckSignatureBytes ([#184]) + +[#184]: https://github.com/RustCrypto/signatures/pull/184 + +## 0.8.4 (2020-10-08) +### Fixed +- Work around `nightly-2020-10-06` breakage ([#180]) + +[#180]: https://github.com/RustCrypto/signatures/pull/180 + +## 0.8.3 (2020-09-28) +### Fixed +- 32-bit builds for the `dev` feature ([#177]) + +[#177]: https://github.com/RustCrypto/signatures/pull/177 + +## 0.8.2 (2020-09-27) +### Added +- `RecoverableSignPrimitive` ([#174], [#175]) + +[#174]: https://github.com/RustCrypto/signatures/pull/174 +[#175]: https://github.com/RustCrypto/signatures/pull/175 + +## 0.8.1 (2020-09-23) +### Added +- Conditional `Copy` impl on `VerifyKey<C>` ([#171]) + +[#171]: https://github.com/RustCrypto/signatures/pull/171 + +## 0.8.0 (2020-09-11) +### Added +- `CheckSignatureBytes` trait ([#151]) +- Add `Signature::r`/`::s` methods which return `NonZeroScalar`values ([#151]) +- `alloc` feature ([#150]) +- Impl `From<&VerifyKey<C>>` for `EncodedPoint<C>` ([#144]) +- Serialization methods for `SigningKey`/`VerifyKey` ([#143]) +- RFC6979-based deterministic signatures ([#133], [#134], [#136]) + +### Changed +- Bump `elliptic-curve` crate dependency to v0.6 ([#165]) +- Use `ProjectiveArithmetic` trait ([#164]) +- Rename `ElementBytes` to `FieldBytes` ([#160]) +- Use `ff` and `group` crates to v0.8 ([#156]) +- MSRV 1.44+ ([#156]) +- Remove `rand` feature; make `rand_core` a hard dependency ([#154]) +- Use `impl Into<ElementBytes>` bounds on `Signature::from_scalars` ([#149]) +- Derive `Clone`, `Debug`, `Eq`, and `Ord` on `VerifyKey` ([#148]) +- Renamed `{Signer, Verifier}` => `{SigningKey, VerifyKey}` ([#140]) +- Use newly refactored `sec1::EncodedPoint` ([#131]) + +### Removed +- `Generate` trait ([#159]) +- `RecoverableSignPrimitive` ([#146]) + +[#165]: https://github.com/RustCrypto/signatures/pull/165 +[#164]: https://github.com/RustCrypto/signatures/pull/164 +[#160]: https://github.com/RustCrypto/signatures/pull/160 +[#159]: https://github.com/RustCrypto/signatures/pull/159 +[#156]: https://github.com/RustCrypto/signatures/pull/156 +[#154]: https://github.com/RustCrypto/signatures/pull/154 +[#151]: https://github.com/RustCrypto/signatures/pull/151 +[#150]: https://github.com/RustCrypto/signatures/pull/150 +[#149]: https://github.com/RustCrypto/signatures/pull/149 +[#148]: https://github.com/RustCrypto/signatures/pull/148 +[#146]: https://github.com/RustCrypto/signatures/pull/146 +[#144]: https://github.com/RustCrypto/signatures/pull/144 +[#143]: https://github.com/RustCrypto/signatures/pull/143 +[#140]: https://github.com/RustCrypto/signatures/pull/140 +[#136]: https://github.com/RustCrypto/signatures/pull/136 +[#134]: https://github.com/RustCrypto/signatures/pull/134 +[#133]: https://github.com/RustCrypto/signatures/pull/133 +[#131]: https://github.com/RustCrypto/signatures/pull/131 + +## 0.7.2 (2020-08-11) +### Added +- Conditional `PrehashSignature` impl for `asn1::Signature` ([#128]) + +[#128]: https://github.com/RustCrypto/signatures/pull/128 + +## 0.7.1 (2020-08-10) +### Changed +- Use `all-features = true` on docs.rs ([#126]) + +[#126]: https://github.com/RustCrypto/signatures/pull/126 + +## 0.7.0 (2020-08-10) +### Added +- `hazmat` traits: `SignPrimitive`, `RecoverableSignPrimitive`, + `VerifyPrimitive`, `DigestPrimitive` ([#96], [#99], [#107], [#111]) +- `dev` module ([#103]) +- `NormalizeLow` trait ([#115], [#118], [#119]) +- `Copy` impl on `Signature` ([#117]) +- `RecoverableSignPrimitive` ([#120]) + +### Changed +- Bumped `elliptic-curve` crate to v0.5 release ([#123]) +- Renamed `FixedSignature` to `ecdsa::Signature` ([#98]) +- Renamed `Asn1Signature` to `ecdsa::asn1::Signature` ([#98], [#102]) + +### Removed +- Curve-specific types - migrated to `k256`, `p256`, `p384` crates ([#96]) + +[#96]: https://github.com/RustCrypto/signatures/pull/96 +[#98]: https://github.com/RustCrypto/signatures/pull/98 +[#99]: https://github.com/RustCrypto/signatures/pull/99 +[#102]: https://github.com/RustCrypto/signatures/pull/102 +[#103]: https://github.com/RustCrypto/signatures/pull/103 +[#107]: https://github.com/RustCrypto/signatures/pull/107 +[#111]: https://github.com/RustCrypto/signatures/pull/111 +[#115]: https://github.com/RustCrypto/signatures/pull/115 +[#117]: https://github.com/RustCrypto/signatures/pull/117 +[#118]: https://github.com/RustCrypto/signatures/pull/118 +[#119]: https://github.com/RustCrypto/signatures/pull/119 +[#120]: https://github.com/RustCrypto/signatures/pull/120 +[#123]: https://github.com/RustCrypto/signatures/pull/123 + +## 0.6.1 (2020-06-29) +### Added +- `doc_cfg` attributes for https://docs.rs ([#91]) +- `ecdsa::curve::secp256k1::RecoverableSignature` ([#90]) + +[#91]: https://github.com/RustCrypto/signatures/pull/91 +[#90]: https://github.com/RustCrypto/signatures/pull/90 + +## 0.6.0 (2020-06-09) +### Changed +- Upgrade to `signature` ~1.1.0; `sha` v0.9 ([#87]) +- Bump all elliptic curve crates; MSRV 1.41+ ([#86]) + +[#87]: https://github.com/RustCrypto/signatures/pull/87 +[#86]: https://github.com/RustCrypto/signatures/pull/86 + +## 0.5.0 (2020-04-18) +### Changed +- Upgrade `signature` crate to v1.0 final release ([#80]) + +[#80]: https://github.com/RustCrypto/signatures/pull/80 + +## 0.4.0 (2020-01-07) +### Changed +- Upgrade `elliptic-curve` crate to v0.3.0; make curves cargo features ([#68]) + +[#68]: https://github.com/RustCrypto/signatures/pull/68 + +## 0.3.0 (2019-12-11) +### Changed +- Upgrade `elliptic-curve` crate to v0.2.0; MSRV 1.37+ ([#65]) + +[#65]: https://github.com/RustCrypto/signatures/pull/65 + +## 0.2.1 (2019-12-06) +### Added +- Re-export `PublicKey` and `SecretKey` from the `elliptic-curve` crate ([#61]) + +[#61]: https://github.com/RustCrypto/signatures/pull/61 + +## 0.2.0 (2019-12-06) +### Changed +- Use curve types from the `elliptic-curve` crate ([#58]) + +[#58]: https://github.com/RustCrypto/signatures/pull/58 + +## 0.1.0 (2019-10-29) + +- Initial release diff --git a/vendor/ecdsa/Cargo.toml b/vendor/ecdsa/Cargo.toml new file mode 100644 index 000000000..62a5410a5 --- /dev/null +++ b/vendor/ecdsa/Cargo.toml @@ -0,0 +1,126 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.57" +name = "ecdsa" +version = "0.14.8" +authors = ["RustCrypto Developers"] +description = """ +Pure Rust implementation of the Elliptic Curve Digital Signature Algorithm +(ECDSA) as specified in FIPS 186-4 (Digital Signature Standard), providing +RFC6979 deterministic signatures as well as support for added entropy +""" +readme = "README.md" +keywords = [ + "crypto", + "ecc", + "nist", + "secp256k1", + "signature", +] +categories = [ + "cryptography", + "no-std", +] +license = "Apache-2.0 OR MIT" +repository = "https://github.com/RustCrypto/signatures/tree/master/ecdsa" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[dependencies.der] +version = "0.6" +optional = true + +[dependencies.elliptic-curve] +version = "0.12" +features = [ + "digest", + "sec1", +] +default-features = false + +[dependencies.rfc6979] +version = "0.3" +optional = true + +[dependencies.serdect] +version = "0.1" +features = ["alloc"] +optional = true +default-features = false + +[dependencies.signature] +version = ">=1.6.2, <1.7" +features = [ + "hazmat-preview", + "rand-preview", +] +default-features = false + +[dev-dependencies.elliptic-curve] +version = "0.12" +features = ["dev"] +default-features = false + +[dev-dependencies.hex-literal] +version = "0.3" + +[dev-dependencies.sha2] +version = "0.10" +default-features = false + +[features] +alloc = [] +arithmetic = ["elliptic-curve/arithmetic"] +default = ["digest"] +dev = [ + "arithmetic", + "digest", + "elliptic-curve/dev", + "hazmat", +] +digest = ["signature/digest-preview"] +hazmat = [] +pem = [ + "elliptic-curve/pem", + "pkcs8", +] +pkcs8 = [ + "elliptic-curve/pkcs8", + "der", +] +serde = [ + "elliptic-curve/serde", + "serdect", +] +sign = [ + "arithmetic", + "digest", + "hazmat", + "rfc6979", +] +std = [ + "alloc", + "elliptic-curve/std", + "signature/std", +] +verify = [ + "arithmetic", + "digest", + "hazmat", +] diff --git a/vendor/ecdsa/LICENSE-APACHE b/vendor/ecdsa/LICENSE-APACHE new file mode 100644 index 000000000..c394d8ad9 --- /dev/null +++ b/vendor/ecdsa/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2018-2022 RustCrypto Developers + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/ecdsa/LICENSE-MIT b/vendor/ecdsa/LICENSE-MIT new file mode 100644 index 000000000..81a3d57ac --- /dev/null +++ b/vendor/ecdsa/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2018-2022 RustCrypto Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/ecdsa/README.md b/vendor/ecdsa/README.md new file mode 100644 index 000000000..6da609998 --- /dev/null +++ b/vendor/ecdsa/README.md @@ -0,0 +1,93 @@ +# [RustCrypto]: ECDSA + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +[![Build Status][build-image]][build-link] +![Apache2/MIT licensed][license-image] +![MSRV][rustc-image] +[![Project Chat][chat-image]][chat-link] + +[Elliptic Curve Digital Signature Algorithm (ECDSA)][1] as specified in +[FIPS 186-4][2] (Digital Signature Standard). + +[Documentation][docs-link] + +## About + +This crate provides generic ECDSA support which can be used in the following +ways: + +- Generic implementation of ECDSA usable with the following crates: + - [`k256`] (secp256k1) + - [`p256`] (NIST P-256) + - [`p384`] (NIST P-384) +- Other crates which provide their own complete implementations of ECDSA can + also leverage the types from this crate to export ECDSA functionality in a + generic, interoperable way by leveraging [`ecdsa::Signature`] with the + [`signature::Signer`] and [`signature::Verifier`] traits. + +## โ ๏ธ Security Warning + +The ECDSA implementation contained in this crate has never been independently +audited for security! + +This crate contains a generic implementation of ECDSA which must be +instantiated using a separate crate providing a concrete implementation of +arithmetic for a particular curve. It's possible timing variability can exist +in concrete curve implementations, and thus this crate's security can only be +properly assessed for a specific elliptic curve. + +USE AT YOUR OWN RISK! + +## Minimum Supported Rust Version + +This crate requires **Rust 1.57** at a minimum. + +We may change the MSRV in the future, but it will be accompanied by a minor +version bump. + +## License + +All crates licensed under either of + +- [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) +- [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://buildstats.info/crate/ecdsa +[crate-link]: https://crates.io/crates/ecdsa +[docs-image]: https://docs.rs/ecdsa/badge.svg +[docs-link]: https://docs.rs/ecdsa/ +[build-image]: https://github.com/RustCrypto/signatures/actions/workflows/ecdsa.yml/badge.svg +[build-link]: https://github.com/RustCrypto/signatures/actions/workflows/ecdsa.yml +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.57+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260048-signatures + +[//]: # (links) + +[RustCrypto]: https://github.com/RustCrypto + +[//]: # (footnotes) + +[1]: https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm +[2]: https://csrc.nist.gov/publications/detail/fips/186/4/final + +[//]: # (docs.rs definitions) + +[`ecdsa::Signature`]: https://docs.rs/ecdsa/latest/ecdsa/struct.Signature.html +[`k256`]: https://docs.rs/k256 +[`p256`]: https://docs.rs/p256 +[`p384`]: https://docs.rs/p384 +[`signature::Signer`]: https://docs.rs/signature/latest/signature/trait.Signer.html +[`signature::Verifier`]: https://docs.rs/signature/latest/signature/trait.Verifier.html diff --git a/vendor/ecdsa/src/der.rs b/vendor/ecdsa/src/der.rs new file mode 100644 index 000000000..5925df443 --- /dev/null +++ b/vendor/ecdsa/src/der.rs @@ -0,0 +1,349 @@ +//! Support for ECDSA signatures encoded as ASN.1 DER. + +use crate::{Error, Result}; +use core::{ + fmt, + ops::{Add, Range}, +}; +use der::{asn1::UIntRef, Decode, Encode, Reader}; +use elliptic_curve::{ + bigint::Encoding as _, + consts::U9, + generic_array::{ArrayLength, GenericArray}, + FieldSize, PrimeCurve, +}; + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +#[cfg(feature = "serde")] +use serdect::serde::{de, ser, Deserialize, Serialize}; + +/// Maximum overhead of an ASN.1 DER-encoded ECDSA signature for a given curve: +/// 9-bytes. +/// +/// Includes 3-byte ASN.1 DER header: +/// +/// - 1-byte: ASN.1 `SEQUENCE` tag (0x30) +/// - 2-byte: length +/// +/// ...followed by two ASN.1 `INTEGER` values, which each have a header whose +/// maximum length is the following: +/// +/// - 1-byte: ASN.1 `INTEGER` tag (0x02) +/// - 1-byte: length +/// - 1-byte: zero to indicate value is positive (`INTEGER` is signed) +pub type MaxOverhead = U9; + +/// Maximum size of an ASN.1 DER encoded signature for the given elliptic curve. +pub type MaxSize<C> = <<FieldSize<C> as Add>::Output as Add<MaxOverhead>>::Output; + +/// Byte array containing a serialized ASN.1 signature +type SignatureBytes<C> = GenericArray<u8, MaxSize<C>>; + +/// ASN.1 DER-encoded signature. +/// +/// Generic over the scalar size of the elliptic curve. +pub struct Signature<C> +where + C: PrimeCurve, + MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, +{ + /// ASN.1 DER-encoded signature data + bytes: SignatureBytes<C>, + + /// Range of the `r` value within the signature + r_range: Range<usize>, + + /// Range of the `s` value within the signature + s_range: Range<usize>, +} + +impl<C> signature::Signature for Signature<C> +where + C: PrimeCurve, + MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, +{ + /// Parse an ASN.1 DER-encoded ECDSA signature from a byte slice + fn from_bytes(bytes: &[u8]) -> Result<Self> { + bytes.try_into() + } +} + +#[allow(clippy::len_without_is_empty)] +impl<C> Signature<C> +where + C: PrimeCurve, + MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, +{ + /// Get the length of the signature in bytes + pub fn len(&self) -> usize { + self.s_range.end + } + + /// Borrow this signature as a byte slice + pub fn as_bytes(&self) -> &[u8] { + &self.bytes.as_slice()[..self.len()] + } + + /// Serialize this signature as a boxed byte slice + #[cfg(feature = "alloc")] + pub fn to_bytes(&self) -> Box<[u8]> { + self.as_bytes().to_vec().into_boxed_slice() + } + + /// Create an ASN.1 DER encoded signature from big endian `r` and `s` scalars + pub(crate) fn from_scalar_bytes(r: &[u8], s: &[u8]) -> der::Result<Self> { + let r = UIntRef::new(r)?; + let s = UIntRef::new(s)?; + + let mut bytes = SignatureBytes::<C>::default(); + let mut writer = der::SliceWriter::new(&mut bytes); + + writer.sequence((r.encoded_len()? + s.encoded_len()?)?, |seq| { + seq.encode(&r)?; + seq.encode(&s) + })?; + + writer + .finish()? + .try_into() + .map_err(|_| der::Tag::Sequence.value_error()) + } + + /// Get the `r` component of the signature (leading zeros removed) + pub(crate) fn r(&self) -> &[u8] { + &self.bytes[self.r_range.clone()] + } + + /// Get the `s` component of the signature (leading zeros removed) + pub(crate) fn s(&self) -> &[u8] { + &self.bytes[self.s_range.clone()] + } +} + +impl<C> AsRef<[u8]> for Signature<C> +where + C: PrimeCurve, + MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, +{ + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +impl<C> fmt::Debug for Signature<C> +where + C: PrimeCurve, + MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ecdsa::der::Signature<{:?}>(", C::default())?; + + for &byte in self.as_ref() { + write!(f, "{:02X}", byte)?; + } + + write!(f, ")") + } +} + +impl<C> TryFrom<&[u8]> for Signature<C> +where + C: PrimeCurve, + MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, +{ + type Error = Error; + + fn try_from(input: &[u8]) -> Result<Self> { + let (r, s) = decode_der(input).map_err(|_| Error::new())?; + + if r.as_bytes().len() > C::UInt::BYTE_SIZE || s.as_bytes().len() > C::UInt::BYTE_SIZE { + return Err(Error::new()); + } + + let r_range = find_scalar_range(input, r.as_bytes())?; + let s_range = find_scalar_range(input, s.as_bytes())?; + + if s_range.end != input.len() { + return Err(Error::new()); + } + + let mut bytes = SignatureBytes::<C>::default(); + bytes[..s_range.end].copy_from_slice(input); + + Ok(Signature { + bytes, + r_range, + s_range, + }) + } +} + +impl<C> TryFrom<Signature<C>> for super::Signature<C> +where + C: PrimeCurve, + MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, +{ + type Error = Error; + + fn try_from(sig: Signature<C>) -> Result<super::Signature<C>> { + let mut bytes = super::SignatureBytes::<C>::default(); + let r_begin = C::UInt::BYTE_SIZE.saturating_sub(sig.r().len()); + let s_begin = bytes.len().saturating_sub(sig.s().len()); + bytes[r_begin..C::UInt::BYTE_SIZE].copy_from_slice(sig.r()); + bytes[s_begin..].copy_from_slice(sig.s()); + Self::try_from(bytes.as_slice()) + } +} + +#[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] +impl<C> Serialize for Signature<C> +where + C: PrimeCurve, + MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, +{ + fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + serdect::slice::serialize_hex_upper_or_bin(&self.as_bytes(), serializer) + } +} + +#[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] +impl<'de, C> Deserialize<'de> for Signature<C> +where + C: PrimeCurve, + MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, +{ + fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error> + where + D: de::Deserializer<'de>, + { + let mut buf = SignatureBytes::<C>::default(); + let slice = serdect::slice::deserialize_hex_or_bin(&mut buf, deserializer)?; + Self::try_from(slice).map_err(de::Error::custom) + } +} + +/// Decode the `r` and `s` components of a DER-encoded ECDSA signature. +fn decode_der(der_bytes: &[u8]) -> der::Result<(UIntRef<'_>, UIntRef<'_>)> { + let mut reader = der::SliceReader::new(der_bytes)?; + let header = der::Header::decode(&mut reader)?; + header.tag.assert_eq(der::Tag::Sequence)?; + + let ret = reader.read_nested(header.length, |reader| { + let r = UIntRef::decode(reader)?; + let s = UIntRef::decode(reader)?; + Ok((r, s)) + })?; + + reader.finish(ret) +} + +/// Locate the range within a slice at which a particular subslice is located +fn find_scalar_range(outer: &[u8], inner: &[u8]) -> Result<Range<usize>> { + let outer_start = outer.as_ptr() as usize; + let inner_start = inner.as_ptr() as usize; + let start = inner_start + .checked_sub(outer_start) + .ok_or_else(Error::new)?; + let end = start.checked_add(inner.len()).ok_or_else(Error::new)?; + Ok(Range { start, end }) +} + +#[cfg(all(feature = "digest", feature = "hazmat"))] +impl<C> signature::PrehashSignature for Signature<C> +where + C: PrimeCurve + crate::hazmat::DigestPrimitive, + MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, +{ + type Digest = C::Digest; +} + +#[cfg(all(test, feature = "arithmetic"))] +mod tests { + use elliptic_curve::dev::MockCurve; + use signature::Signature as _; + + type Signature = crate::Signature<MockCurve>; + + const EXAMPLE_SIGNATURE: [u8; 64] = [ + 0xf3, 0xac, 0x80, 0x61, 0xb5, 0x14, 0x79, 0x5b, 0x88, 0x43, 0xe3, 0xd6, 0x62, 0x95, 0x27, + 0xed, 0x2a, 0xfd, 0x6b, 0x1f, 0x6a, 0x55, 0x5a, 0x7a, 0xca, 0xbb, 0x5e, 0x6f, 0x79, 0xc8, + 0xc2, 0xac, 0x8b, 0xf7, 0x78, 0x19, 0xca, 0x5, 0xa6, 0xb2, 0x78, 0x6c, 0x76, 0x26, 0x2b, + 0xf7, 0x37, 0x1c, 0xef, 0x97, 0xb2, 0x18, 0xe9, 0x6f, 0x17, 0x5a, 0x3c, 0xcd, 0xda, 0x2a, + 0xcc, 0x5, 0x89, 0x3, + ]; + + #[test] + fn test_fixed_to_asn1_signature_roundtrip() { + let signature1 = Signature::from_bytes(&EXAMPLE_SIGNATURE).unwrap(); + + // Convert to ASN.1 DER and back + let asn1_signature = signature1.to_der(); + let signature2 = Signature::from_der(asn1_signature.as_ref()).unwrap(); + + assert_eq!(signature1, signature2); + } + + #[test] + fn test_asn1_too_short_signature() { + assert!(Signature::from_der(&[]).is_err()); + assert!(Signature::from_der(&[der::Tag::Sequence.into()]).is_err()); + assert!(Signature::from_der(&[der::Tag::Sequence.into(), 0x00]).is_err()); + assert!(Signature::from_der(&[ + der::Tag::Sequence.into(), + 0x03, + der::Tag::Integer.into(), + 0x01, + 0x01 + ]) + .is_err()); + } + + #[test] + fn test_asn1_non_der_signature() { + // A minimal 8-byte ASN.1 signature parses OK. + assert!(Signature::from_der(&[ + der::Tag::Sequence.into(), + 0x06, // length of below + der::Tag::Integer.into(), + 0x01, // length of value + 0x01, // value=1 + der::Tag::Integer.into(), + 0x01, // length of value + 0x01, // value=1 + ]) + .is_ok()); + + // But length fields that are not minimally encoded should be rejected, as they are not + // valid DER, cf. + // https://github.com/google/wycheproof/blob/2196000605e4/testvectors/ecdsa_secp256k1_sha256_test.json#L57-L66 + assert!(Signature::from_der(&[ + der::Tag::Sequence.into(), + 0x81, // extended length: 1 length byte to come + 0x06, // length of below + der::Tag::Integer.into(), + 0x01, // length of value + 0x01, // value=1 + der::Tag::Integer.into(), + 0x01, // length of value + 0x01, // value=1 + ]) + .is_err()); + } +} diff --git a/vendor/ecdsa/src/dev.rs b/vendor/ecdsa/src/dev.rs new file mode 100644 index 000000000..ce00c7fbf --- /dev/null +++ b/vendor/ecdsa/src/dev.rs @@ -0,0 +1,221 @@ +//! Development-related functionality. + +// TODO(tarcieri): implement full set of tests from ECDSA2VS +// <https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/dss2/ecdsa2vs.pdf> + +/// ECDSA test vector +pub struct TestVector { + /// Private scalar + pub d: &'static [u8], + + /// Public key x-coordinate (`Qx`) + pub q_x: &'static [u8], + + /// Public key y-coordinate (`Qy`) + pub q_y: &'static [u8], + + /// Ephemeral scalar (a.k.a. nonce) + pub k: &'static [u8], + + /// Message digest (prehashed) + pub m: &'static [u8], + + /// Signature `r` component + pub r: &'static [u8], + + /// Signature `s` component + pub s: &'static [u8], +} + +/// Define ECDSA signing test. +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! new_signing_test { + ($curve:path, $vectors:expr) => { + use $crate::{ + elliptic_curve::{ + bigint::Encoding, generic_array::GenericArray, group::ff::PrimeField, Curve, + ProjectiveArithmetic, Scalar, + }, + hazmat::SignPrimitive, + }; + + fn decode_scalar(bytes: &[u8]) -> Option<Scalar<$curve>> { + if bytes.len() == <$curve as Curve>::UInt::BYTE_SIZE { + Scalar::<$curve>::from_repr(GenericArray::clone_from_slice(bytes)).into() + } else { + None + } + } + + #[test] + fn ecdsa_signing() { + for vector in $vectors { + let d = decode_scalar(vector.d).expect("invalid vector.d"); + let k = decode_scalar(vector.k).expect("invalid vector.m"); + let z = GenericArray::clone_from_slice(vector.m); + let sig = d.try_sign_prehashed(k, z).expect("ECDSA sign failed").0; + + assert_eq!(vector.r, sig.r().to_bytes().as_slice()); + assert_eq!(vector.s, sig.s().to_bytes().as_slice()); + } + } + }; +} + +/// Define ECDSA verification test. +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! new_verification_test { + ($curve:path, $vectors:expr) => { + use $crate::{ + elliptic_curve::{ + generic_array::GenericArray, + group::ff::PrimeField, + sec1::{EncodedPoint, FromEncodedPoint}, + AffinePoint, ProjectiveArithmetic, Scalar, + }, + hazmat::VerifyPrimitive, + Signature, + }; + + #[test] + fn ecdsa_verify_success() { + for vector in $vectors { + let q_encoded = EncodedPoint::<$curve>::from_affine_coordinates( + GenericArray::from_slice(vector.q_x), + GenericArray::from_slice(vector.q_y), + false, + ); + + let q = AffinePoint::<$curve>::from_encoded_point(&q_encoded).unwrap(); + let z = GenericArray::clone_from_slice(vector.m); + + let sig = Signature::from_scalars( + GenericArray::clone_from_slice(vector.r), + GenericArray::clone_from_slice(vector.s), + ) + .unwrap(); + + let result = q.verify_prehashed(z, &sig); + assert!(result.is_ok()); + } + } + + #[test] + fn ecdsa_verify_invalid_s() { + for vector in $vectors { + let q_encoded = EncodedPoint::<$curve>::from_affine_coordinates( + GenericArray::from_slice(vector.q_x), + GenericArray::from_slice(vector.q_y), + false, + ); + + let q = AffinePoint::<$curve>::from_encoded_point(&q_encoded).unwrap(); + let z = GenericArray::clone_from_slice(vector.m); + + // Flip a bit in `s` + let mut s_tweaked = GenericArray::clone_from_slice(vector.s); + s_tweaked[0] ^= 1; + + let sig = + Signature::from_scalars(GenericArray::clone_from_slice(vector.r), s_tweaked) + .unwrap(); + + let result = q.verify_prehashed(z, &sig); + assert!(result.is_err()); + } + } + + // TODO(tarcieri): test invalid Q, invalid r, invalid m + }; +} + +/// Define a Wycheproof verification test. +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! new_wycheproof_test { + ($name:ident, $test_name: expr, $curve:path) => { + use $crate::{elliptic_curve::sec1::EncodedPoint, signature::Verifier, Signature}; + + #[test] + fn $name() { + use blobby::Blob5Iterator; + use elliptic_curve::{bigint::Encoding as _, generic_array::typenum::Unsigned}; + + // Build a field element but allow for too-short input (left pad with zeros) + // or too-long input (check excess leftmost bytes are zeros). + fn element_from_padded_slice<C: elliptic_curve::Curve>( + data: &[u8], + ) -> elliptic_curve::FieldBytes<C> { + let point_len = C::UInt::BYTE_SIZE; + if data.len() >= point_len { + let offset = data.len() - point_len; + for v in data.iter().take(offset) { + assert_eq!(*v, 0, "EcdsaVerifier: point too large"); + } + elliptic_curve::FieldBytes::<C>::clone_from_slice(&data[offset..]) + } else { + // Provided slice is too short and needs to be padded with zeros + // on the left. Build a combined exact iterator to do this. + let iter = core::iter::repeat(0) + .take(point_len - data.len()) + .chain(data.iter().cloned()); + elliptic_curve::FieldBytes::<C>::from_exact_iter(iter).unwrap() + } + } + + fn run_test( + wx: &[u8], + wy: &[u8], + msg: &[u8], + sig: &[u8], + pass: bool, + ) -> Option<&'static str> { + let x = element_from_padded_slice::<$curve>(wx); + let y = element_from_padded_slice::<$curve>(wy); + let q_encoded = EncodedPoint::<$curve>::from_affine_coordinates( + &x, &y, /* compress= */ false, + ); + let verifying_key = + $crate::VerifyingKey::<$curve>::from_encoded_point(&q_encoded).unwrap(); + + let sig = match Signature::from_der(sig) { + Ok(s) => s, + Err(_) if !pass => return None, + Err(_) => return Some("failed to parse signature ASN.1"), + }; + + match verifying_key.verify(msg, &sig) { + Ok(_) if pass => None, + Ok(_) => Some("signature verify unexpectedly succeeded"), + Err(_) if !pass => None, + Err(_) => Some("signature verify failed"), + } + } + + let data = include_bytes!(concat!("test_vectors/data/", $test_name, ".blb")); + + for (i, row) in Blob5Iterator::new(data).unwrap().enumerate() { + let [wx, wy, msg, sig, status] = row.unwrap(); + let pass = match status[0] { + 0 => false, + 1 => true, + _ => panic!("invalid value for pass flag"), + }; + if let Some(desc) = run_test(wx, wy, msg, sig, pass) { + panic!( + "\n\ + Failed test โ{}: {}\n\ + wx:\t{:?}\n\ + wy:\t{:?}\n\ + msg:\t{:?}\n\ + sig:\t{:?}\n\ + pass:\t{}\n", + i, desc, wx, wy, msg, sig, pass, + ); + } + } + } + }; +} diff --git a/vendor/ecdsa/src/hazmat.rs b/vendor/ecdsa/src/hazmat.rs new file mode 100644 index 000000000..3ca3fc4ce --- /dev/null +++ b/vendor/ecdsa/src/hazmat.rs @@ -0,0 +1,261 @@ +//! Low-level ECDSA primitives. +//! +//! # โ ๏ธ Warning: Hazmat! +//! +//! YOU PROBABLY DON'T WANT TO USE THESE! +//! +//! These primitives are easy-to-misuse low-level interfaces. +//! +//! If you are an end user / non-expert in cryptography, do not use these! +//! Failure to use them correctly can lead to catastrophic failures including +//! FULL PRIVATE KEY RECOVERY! + +#[cfg(feature = "arithmetic")] +use { + crate::{RecoveryId, SignatureSize}, + core::borrow::Borrow, + elliptic_curve::{ + group::Curve as _, + ops::{Invert, LinearCombination, Reduce}, + subtle::CtOption, + AffineArithmetic, AffineXCoordinate, Field, Group, ProjectiveArithmetic, ProjectivePoint, + Scalar, ScalarArithmetic, + }, +}; + +#[cfg(feature = "digest")] +use { + core::cmp, + elliptic_curve::{bigint::Encoding, FieldSize}, + signature::{digest::Digest, PrehashSignature}, +}; + +#[cfg(any(feature = "arithmetic", feature = "digest"))] +use crate::{ + elliptic_curve::{generic_array::ArrayLength, FieldBytes, PrimeCurve}, + Error, Result, Signature, +}; + +#[cfg(all(feature = "arithmetic", feature = "digest"))] +use signature::digest::FixedOutput; + +#[cfg(all(feature = "rfc6979"))] +use { + elliptic_curve::ScalarCore, + signature::digest::{core_api::BlockSizeUser, FixedOutputReset}, +}; + +/// Try to sign the given prehashed message using ECDSA. +/// +/// This trait is intended to be implemented on a type with access to the +/// secret scalar via `&self`, such as particular curve's `Scalar` type. +#[cfg(feature = "arithmetic")] +#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] +pub trait SignPrimitive<C>: Field + Into<FieldBytes<C>> + Reduce<C::UInt> + Sized +where + C: PrimeCurve + ProjectiveArithmetic + ScalarArithmetic<Scalar = Self>, + SignatureSize<C>: ArrayLength<u8>, +{ + /// Try to sign the prehashed message. + /// + /// Accepts the following arguments: + /// + /// - `k`: ephemeral scalar value. MUST BE UNIFORMLY RANDOM!!! + /// - `z`: message digest to be signed. MUST BE OUTPUT OF A CRYPTOGRAPHICALLY + /// SECURE DIGEST ALGORITHM!!! + /// + /// # Returns + /// + /// ECDSA [`Signature`] and, when possible/desired, a [`RecoveryId`] + /// which can be used to recover the verifying key for a given signature. + #[allow(non_snake_case)] + fn try_sign_prehashed<K>( + &self, + k: K, + z: FieldBytes<C>, + ) -> Result<(Signature<C>, Option<RecoveryId>)> + where + K: Borrow<Self> + Invert<Output = CtOption<Self>>, + { + if k.borrow().is_zero().into() { + return Err(Error::new()); + } + + let z = Self::from_be_bytes_reduced(z); + + // Compute scalar inversion of ๐ + let k_inv = Option::<Scalar<C>>::from(k.invert()).ok_or_else(Error::new)?; + + // Compute ๐น = ๐ร๐ฎ + let R = (C::ProjectivePoint::generator() * k.borrow()).to_affine(); + + // Lift x-coordinate of ๐น (element of base field) into a serialized big + // integer, then reduce it into an element of the scalar field + let r = Self::from_be_bytes_reduced(R.x()); + + // Compute ๐ as a signature over ๐ and ๐. + let s = k_inv * (z + (r * self)); + + if s.is_zero().into() { + return Err(Error::new()); + } + + // TODO(tarcieri): support for computing recovery ID + Ok((Signature::from_scalars(r, s)?, None)) + } + + /// Try to sign the given message digest deterministically using the method + /// described in [RFC6979] for computing ECDSA ephemeral scalar `k`. + /// + /// Accepts the following parameters: + /// - `z`: message digest to be signed. + /// - `ad`: optional additional data, e.g. added entropy from an RNG + /// + /// [RFC6979]: https://datatracker.ietf.org/doc/html/rfc6979 + #[cfg(all(feature = "rfc6979"))] + #[cfg_attr(docsrs, doc(cfg(feature = "rfc6979")))] + fn try_sign_prehashed_rfc6979<D>( + &self, + z: FieldBytes<C>, + ad: &[u8], + ) -> Result<(Signature<C>, Option<RecoveryId>)> + where + Self: From<ScalarCore<C>>, + C::UInt: for<'a> From<&'a Self>, + D: Digest + BlockSizeUser + FixedOutput<OutputSize = FieldSize<C>> + FixedOutputReset, + { + let x = C::UInt::from(self); + let k = rfc6979::generate_k::<D, C::UInt>(&x, &C::ORDER, &z, ad); + let k = Self::from(ScalarCore::<C>::new(*k).unwrap()); + self.try_sign_prehashed(k, z) + } + + /// Try to sign the given digest instance using the method described in + /// [RFC6979]. + /// + /// [RFC6979]: https://datatracker.ietf.org/doc/html/rfc6979 + #[cfg(all(feature = "rfc6979"))] + #[cfg_attr(docsrs, doc(cfg(feature = "rfc6979")))] + fn try_sign_digest_rfc6979<D>( + &self, + msg_digest: D, + ad: &[u8], + ) -> Result<(Signature<C>, Option<RecoveryId>)> + where + Self: From<ScalarCore<C>>, + C::UInt: for<'a> From<&'a Self>, + D: Digest + BlockSizeUser + FixedOutput<OutputSize = FieldSize<C>> + FixedOutputReset, + { + self.try_sign_prehashed_rfc6979::<D>(msg_digest.finalize_fixed(), ad) + } +} + +/// Verify the given prehashed message using ECDSA. +/// +/// This trait is intended to be implemented on type which can access +/// the affine point represeting the public key via `&self`, such as a +/// particular curve's `AffinePoint` type. +#[cfg(feature = "arithmetic")] +#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] +pub trait VerifyPrimitive<C>: AffineXCoordinate<C> + Copy + Sized +where + C: PrimeCurve + AffineArithmetic<AffinePoint = Self> + ProjectiveArithmetic, + Scalar<C>: Reduce<C::UInt>, + SignatureSize<C>: ArrayLength<u8>, +{ + /// Verify the prehashed message against the provided signature + /// + /// Accepts the following arguments: + /// + /// - `z`: message digest to be verified. MUST BE OUTPUT OF A + /// CRYPTOGRAPHICALLY SECURE DIGEST ALGORITHM!!! + /// - `sig`: signature to be verified against the key and message + fn verify_prehashed(&self, z: FieldBytes<C>, sig: &Signature<C>) -> Result<()> { + let z = Scalar::<C>::from_be_bytes_reduced(z); + let (r, s) = sig.split_scalars(); + let s_inv = *s.invert(); + let u1 = z * s_inv; + let u2 = *r * s_inv; + let x = ProjectivePoint::<C>::lincomb( + &ProjectivePoint::<C>::generator(), + &u1, + &ProjectivePoint::<C>::from(*self), + &u2, + ) + .to_affine() + .x(); + + if Scalar::<C>::from_be_bytes_reduced(x) == *r { + Ok(()) + } else { + Err(Error::new()) + } + } + + /// Verify message digest against the provided signature. + #[cfg(feature = "digest")] + #[cfg_attr(docsrs, doc(cfg(feature = "digest")))] + fn verify_digest<D>(&self, msg_digest: D, sig: &Signature<C>) -> Result<()> + where + D: FixedOutput<OutputSize = FieldSize<C>>, + { + self.verify_prehashed(msg_digest.finalize_fixed(), sig) + } +} + +/// Bind a preferred [`Digest`] algorithm to an elliptic curve type. +/// +/// Generally there is a preferred variety of the SHA-2 family used with ECDSA +/// for a particular elliptic curve. +/// +/// This trait can be used to specify it, and with it receive a blanket impl of +/// [`PrehashSignature`], used by [`signature_derive`][1]) for the [`Signature`] +/// type for a particular elliptic curve. +/// +/// [1]: https://github.com/RustCrypto/traits/tree/master/signature/derive +#[cfg(feature = "digest")] +#[cfg_attr(docsrs, doc(cfg(feature = "digest")))] +pub trait DigestPrimitive: PrimeCurve { + /// Preferred digest to use when computing ECDSA signatures for this + /// elliptic curve. This is typically a member of the SHA-2 family. + // TODO(tarcieri): add BlockSizeUser + FixedOutput(Reset) bounds in next breaking release + // These bounds ensure the digest algorithm can be used for HMAC-DRBG for RFC6979 + type Digest: Digest; + + /// Compute field bytes for a prehash (message digest), either zero-padding + /// or truncating if the prehash size does not match the field size. + fn prehash_to_field_bytes(prehash: &[u8]) -> Result<FieldBytes<Self>> { + // Minimum allowed prehash size is half the field size + if prehash.len() < Self::UInt::BYTE_SIZE / 2 { + return Err(Error::new()); + } + + let mut field_bytes = FieldBytes::<Self>::default(); + + // This is a operation according to RFC6979 Section 2.3.2. and SEC1 Section 2.3.8. + // https://datatracker.ietf.org/doc/html/rfc6979#section-2.3.2 + // https://www.secg.org/sec1-v2.pdf + match prehash.len().cmp(&Self::UInt::BYTE_SIZE) { + cmp::Ordering::Equal => field_bytes.copy_from_slice(prehash), + cmp::Ordering::Less => { + // If prehash is smaller than the field size, pad with zeroes on the left + field_bytes[(Self::UInt::BYTE_SIZE - prehash.len())..].copy_from_slice(prehash); + } + cmp::Ordering::Greater => { + // If prehash is larger than the field size, truncate + field_bytes.copy_from_slice(&prehash[..Self::UInt::BYTE_SIZE]); + } + } + + Ok(field_bytes) + } +} + +#[cfg(feature = "digest")] +impl<C> PrehashSignature for Signature<C> +where + C: DigestPrimitive, + <FieldSize<C> as core::ops::Add>::Output: ArrayLength<u8>, +{ + type Digest = C::Digest; +} diff --git a/vendor/ecdsa/src/lib.rs b/vendor/ecdsa/src/lib.rs new file mode 100644 index 000000000..9e339ba8f --- /dev/null +++ b/vendor/ecdsa/src/lib.rs @@ -0,0 +1,421 @@ +#![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![doc = include_str!("../README.md")] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg" +)] +#![forbid(unsafe_code)] +#![warn( + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::cast_sign_loss, + clippy::checked_conversions, + clippy::implicit_saturating_sub, + clippy::panic, + clippy::panic_in_result_fn, + clippy::unwrap_used, + missing_docs, + rust_2018_idioms, + unused_lifetimes, + unused_qualifications +)] + +//! ## `serde` support +//! +//! When the `serde` feature of this crate is enabled, `Serialize` and +//! `Deserialize` impls are provided for the [`Signature`] and [`VerifyingKey`] +//! types. +//! +//! Please see type-specific documentation for more information. +//! +//! ## Interop +//! +//! Any crates which provide an implementation of ECDSA for a particular +//! elliptic curve can leverage the types from this crate, along with the +//! [`k256`], [`p256`], and/or [`p384`] crates to expose ECDSA functionality in +//! a generic, interoperable way by leveraging the [`Signature`] type with in +//! conjunction with the [`signature::Signer`] and [`signature::Verifier`] +//! traits. +//! +//! For example, the [`ring-compat`] crate implements the [`signature::Signer`] +//! and [`signature::Verifier`] traits in conjunction with the +//! [`p256::ecdsa::Signature`] and [`p384::ecdsa::Signature`] types to +//! wrap the ECDSA implementations from [*ring*] in a generic, interoperable +//! API. +//! +//! [`k256`]: https://docs.rs/k256 +//! [`p256`]: https://docs.rs/p256 +//! [`p256::ecdsa::Signature`]: https://docs.rs/p256/latest/p256/ecdsa/type.Signature.html +//! [`p384`]: https://docs.rs/p384 +//! [`p384::ecdsa::Signature`]: https://docs.rs/p384/latest/p384/ecdsa/type.Signature.html +//! [`ring-compat`]: https://docs.rs/ring-compat +//! [*ring*]: https://docs.rs/ring + +#[cfg(feature = "alloc")] +extern crate alloc; + +mod recovery; + +#[cfg(feature = "der")] +#[cfg_attr(docsrs, doc(cfg(feature = "der")))] +pub mod der; + +#[cfg(feature = "dev")] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +pub mod dev; + +#[cfg(feature = "hazmat")] +#[cfg_attr(docsrs, doc(cfg(feature = "hazmat")))] +pub mod hazmat; + +#[cfg(feature = "sign")] +mod sign; + +#[cfg(feature = "verify")] +mod verify; + +pub use crate::recovery::RecoveryId; + +// Re-export the `elliptic-curve` crate (and select types) +pub use elliptic_curve::{self, sec1::EncodedPoint, PrimeCurve}; + +// Re-export the `signature` crate (and select types) +pub use signature::{self, Error, Result}; + +#[cfg(feature = "sign")] +#[cfg_attr(docsrs, doc(cfg(feature = "sign")))] +pub use crate::sign::SigningKey; + +#[cfg(feature = "verify")] +#[cfg_attr(docsrs, doc(cfg(feature = "verify")))] +pub use crate::verify::VerifyingKey; + +use core::{ + fmt::{self, Debug}, + ops::Add, +}; +use elliptic_curve::{ + bigint::Encoding as _, + generic_array::{sequence::Concat, ArrayLength, GenericArray}, + FieldBytes, FieldSize, ScalarCore, +}; + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +#[cfg(feature = "arithmetic")] +use { + core::str, + elliptic_curve::{ff::PrimeField, IsHigh, NonZeroScalar, ScalarArithmetic}, +}; + +#[cfg(feature = "serde")] +use serdect::serde::{de, ser, Deserialize, Serialize}; + +/// Size of a fixed sized signature for the given elliptic curve. +pub type SignatureSize<C> = <FieldSize<C> as Add>::Output; + +/// Fixed-size byte array containing an ECDSA signature +pub type SignatureBytes<C> = GenericArray<u8, SignatureSize<C>>; + +/// ECDSA signature (fixed-size). Generic over elliptic curve types. +/// +/// Serialized as fixed-sized big endian scalar values with no added framing: +/// +/// - `r`: field element size for the given curve, big-endian +/// - `s`: field element size for the given curve, big-endian +/// +/// For example, in a curve with a 256-bit modulus like NIST P-256 or +/// secp256k1, `r` and `s` will both be 32-bytes, resulting in a signature +/// with a total of 64-bytes. +/// +/// ASN.1 DER-encoded signatures also supported via the +/// [`Signature::from_der`] and [`Signature::to_der`] methods. +/// +/// # `serde` support +/// +/// When the `serde` feature of this crate is enabled, it provides support for +/// serializing and deserializing ECDSA signatures using the `Serialize` and +/// `Deserialize` traits. +/// +/// The serialization uses a 64-byte fixed encoding when used with binary +/// formats, and a hexadecimal encoding when used with text formats. +#[derive(Clone, Eq, PartialEq)] +pub struct Signature<C: PrimeCurve> +where + SignatureSize<C>: ArrayLength<u8>, +{ + bytes: SignatureBytes<C>, +} + +impl<C> Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, +{ + /// Parse a signature from ASN.1 DER + #[cfg(feature = "der")] + #[cfg_attr(docsrs, doc(cfg(feature = "der")))] + pub fn from_der(bytes: &[u8]) -> Result<Self> + where + der::MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>, + { + der::Signature::<C>::try_from(bytes).and_then(Self::try_from) + } + + /// Create a [`Signature`] from the serialized `r` and `s` scalar values + /// which comprise the signature. + pub fn from_scalars(r: impl Into<FieldBytes<C>>, s: impl Into<FieldBytes<C>>) -> Result<Self> { + Self::try_from(r.into().concat(s.into()).as_slice()) + } + + /// Split the signature into its `r` and `s` components, represented as bytes. + pub fn split_bytes(&self) -> (FieldBytes<C>, FieldBytes<C>) { + let (r_bytes, s_bytes) = self.bytes.split_at(C::UInt::BYTE_SIZE); + + ( + GenericArray::clone_from_slice(r_bytes), + GenericArray::clone_from_slice(s_bytes), + ) + } + + /// Serialize this signature as ASN.1 DER + #[cfg(feature = "der")] + #[cfg_attr(docsrs, doc(cfg(feature = "der")))] + pub fn to_der(&self) -> der::Signature<C> + where + der::MaxSize<C>: ArrayLength<u8>, + <FieldSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>, + { + let (r, s) = self.bytes.split_at(C::UInt::BYTE_SIZE); + der::Signature::from_scalar_bytes(r, s).expect("DER encoding error") + } + + /// Convert this signature into a byte vector. + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + pub fn to_vec(&self) -> Vec<u8> { + self.bytes.to_vec() + } +} + +#[cfg(feature = "arithmetic")] +#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] +impl<C> Signature<C> +where + C: PrimeCurve + ScalarArithmetic, + SignatureSize<C>: ArrayLength<u8>, +{ + /// Get the `r` component of this signature + pub fn r(&self) -> NonZeroScalar<C> { + NonZeroScalar::try_from(self.split_bytes().0.as_slice()) + .expect("r-component ensured valid in constructor") + } + + /// Get the `s` component of this signature + pub fn s(&self) -> NonZeroScalar<C> { + NonZeroScalar::try_from(self.split_bytes().1.as_slice()) + .expect("s-component ensured valid in constructor") + } + + /// Split the signature into its `r` and `s` scalars. + pub fn split_scalars(&self) -> (NonZeroScalar<C>, NonZeroScalar<C>) { + (self.r(), self.s()) + } + + /// Normalize signature into "low S" form as described in + /// [BIP 0062: Dealing with Malleability][1]. + /// + /// [1]: https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki + pub fn normalize_s(&self) -> Option<Self> { + let s = self.s(); + + if s.is_high().into() { + let neg_s = -s; + let mut result = self.clone(); + result.bytes[C::UInt::BYTE_SIZE..].copy_from_slice(&neg_s.to_repr()); + Some(result) + } else { + None + } + } +} + +impl<C> signature::Signature for Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, +{ + fn from_bytes(bytes: &[u8]) -> Result<Self> { + Self::try_from(bytes) + } +} + +impl<C> AsRef<[u8]> for Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, +{ + fn as_ref(&self) -> &[u8] { + self.bytes.as_slice() + } +} + +impl<C> Copy for Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, + <SignatureSize<C> as ArrayLength<u8>>::ArrayType: Copy, +{ +} + +impl<C> Debug for Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ecdsa::Signature<{:?}>(", C::default())?; + + for &byte in self.as_ref() { + write!(f, "{:02X}", byte)?; + } + + write!(f, ")") + } +} + +impl<C> TryFrom<&[u8]> for Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, +{ + type Error = Error; + + fn try_from(bytes: &[u8]) -> Result<Self> { + if bytes.len() != C::UInt::BYTE_SIZE * 2 { + return Err(Error::new()); + } + + for scalar_bytes in bytes.chunks_exact(C::UInt::BYTE_SIZE) { + let scalar = ScalarCore::<C>::from_be_slice(scalar_bytes).map_err(|_| Error::new())?; + + if scalar.is_zero().into() { + return Err(Error::new()); + } + } + + Ok(Self { + bytes: GenericArray::clone_from_slice(bytes), + }) + } +} + +impl<C> fmt::Display for Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:X}", self) + } +} + +impl<C> fmt::LowerHex for Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for byte in &self.bytes { + write!(f, "{:02x}", byte)?; + } + Ok(()) + } +} + +impl<C> fmt::UpperHex for Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for byte in &self.bytes { + write!(f, "{:02X}", byte)?; + } + Ok(()) + } +} + +#[cfg(feature = "arithmetic")] +#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] +impl<C> str::FromStr for Signature<C> +where + C: PrimeCurve + ScalarArithmetic, + SignatureSize<C>: ArrayLength<u8>, +{ + type Err = Error; + + fn from_str(hex: &str) -> Result<Self> { + if hex.as_bytes().len() != C::UInt::BYTE_SIZE * 4 { + return Err(Error::new()); + } + + // This check is mainly to ensure `hex.split_at` below won't panic + if !hex + .as_bytes() + .iter() + .all(|&byte| matches!(byte, b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z')) + { + return Err(Error::new()); + } + + let (r_hex, s_hex) = hex.split_at(C::UInt::BYTE_SIZE * 2); + + let r = r_hex + .parse::<NonZeroScalar<C>>() + .map_err(|_| Error::new())?; + + let s = s_hex + .parse::<NonZeroScalar<C>>() + .map_err(|_| Error::new())?; + + Self::from_scalars(r, s) + } +} + +#[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] +impl<C> Serialize for Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, +{ + fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + serdect::array::serialize_hex_upper_or_bin(&self.bytes, serializer) + } +} + +#[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] +impl<'de, C> Deserialize<'de> for Signature<C> +where + C: PrimeCurve, + SignatureSize<C>: ArrayLength<u8>, +{ + fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error> + where + D: de::Deserializer<'de>, + { + let mut bytes = SignatureBytes::<C>::default(); + serdect::array::deserialize_hex_or_bin(&mut bytes, deserializer)?; + Self::try_from(bytes.as_slice()).map_err(de::Error::custom) + } +} diff --git a/vendor/ecdsa/src/recovery.rs b/vendor/ecdsa/src/recovery.rs new file mode 100644 index 000000000..c923bbad7 --- /dev/null +++ b/vendor/ecdsa/src/recovery.rs @@ -0,0 +1,110 @@ +//! Public key recovery support. + +use crate::{Error, Result}; + +/// Recovery IDs, a.k.a. "recid". +/// +/// This is an integer value `0`, `1`, `2`, or `3` included along with a +/// signature which is used during the recovery process to select the correct +/// public key from the signature. +/// +/// It consists of two bits of information: +/// +/// - low bit (0/1): was the y-coordinate of the affine point resulting from +/// the fixed-base multiplication ๐ร๐ฎ odd? This part of the algorithm +/// functions similar to point decompression. +/// - hi bit (3/4): did the affine x-coordinate of ๐ร๐ฎ overflow the order of +/// the scalar field, requiring a reduction when computing `r`? +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct RecoveryId(u8); + +impl RecoveryId { + /// Maximum supported value for the recovery ID (inclusive). + pub const MAX: u8 = 3; + + /// Create a new [`RecoveryId`] from the following 1-bit arguments: + /// + /// - `is_y_odd`: is the affine y-coordinate of ๐ร๐ฎ odd? + /// - `is_x_reduced`: did the affine x-coordinate of ๐ร๐ฎ overflow the curve order? + pub const fn new(is_y_odd: bool, is_x_reduced: bool) -> Self { + Self((is_x_reduced as u8) << 1 | (is_y_odd as u8)) + } + + /// Did the affine x-coordinate of ๐ร๐ฎ overflow the curve order? + pub const fn is_x_reduced(self) -> bool { + (self.0 & 0b10) != 0 + } + + /// Is the affine y-coordinate of ๐ร๐ฎ odd? + pub const fn is_y_odd(self) -> bool { + (self.0 & 1) != 0 + } + + /// Convert a `u8` into a [`RecoveryId`]. + pub const fn from_byte(byte: u8) -> Option<Self> { + if byte <= Self::MAX { + Some(Self(byte)) + } else { + None + } + } + + /// Convert this [`RecoveryId`] into a `u8`. + pub const fn to_byte(self) -> u8 { + self.0 + } +} + +impl TryFrom<u8> for RecoveryId { + type Error = Error; + + fn try_from(byte: u8) -> Result<Self> { + Self::from_byte(byte).ok_or_else(Error::new) + } +} + +impl From<RecoveryId> for u8 { + fn from(id: RecoveryId) -> u8 { + id.0 + } +} + +#[cfg(test)] +mod tests { + use super::RecoveryId; + + #[test] + fn new() { + assert_eq!(RecoveryId::new(false, false).to_byte(), 0); + assert_eq!(RecoveryId::new(true, false).to_byte(), 1); + assert_eq!(RecoveryId::new(false, true).to_byte(), 2); + assert_eq!(RecoveryId::new(true, true).to_byte(), 3); + } + + #[test] + fn try_from() { + for n in 0u8..=3 { + assert_eq!(RecoveryId::try_from(n).unwrap().to_byte(), n); + } + + for n in 4u8..=255 { + assert!(RecoveryId::try_from(n).is_err()); + } + } + + #[test] + fn is_x_reduced() { + assert_eq!(RecoveryId::try_from(0).unwrap().is_x_reduced(), false); + assert_eq!(RecoveryId::try_from(1).unwrap().is_x_reduced(), false); + assert_eq!(RecoveryId::try_from(2).unwrap().is_x_reduced(), true); + assert_eq!(RecoveryId::try_from(3).unwrap().is_x_reduced(), true); + } + + #[test] + fn is_y_odd() { + assert_eq!(RecoveryId::try_from(0).unwrap().is_y_odd(), false); + assert_eq!(RecoveryId::try_from(1).unwrap().is_y_odd(), true); + assert_eq!(RecoveryId::try_from(2).unwrap().is_y_odd(), false); + assert_eq!(RecoveryId::try_from(3).unwrap().is_y_odd(), true); + } +} diff --git a/vendor/ecdsa/src/sign.rs b/vendor/ecdsa/src/sign.rs new file mode 100644 index 000000000..12d00edb2 --- /dev/null +++ b/vendor/ecdsa/src/sign.rs @@ -0,0 +1,424 @@ +//! ECDSA signing key. + +// TODO(tarcieri): support for hardware crypto accelerators + +use crate::{ + hazmat::{DigestPrimitive, SignPrimitive}, + Error, Result, Signature, SignatureSize, +}; +use core::fmt::{self, Debug}; +use elliptic_curve::{ + generic_array::ArrayLength, + group::ff::PrimeField, + ops::{Invert, Reduce}, + subtle::{Choice, ConstantTimeEq, CtOption}, + zeroize::{Zeroize, ZeroizeOnDrop}, + FieldBytes, FieldSize, NonZeroScalar, PrimeCurve, ProjectiveArithmetic, Scalar, SecretKey, +}; +use signature::{ + digest::{core_api::BlockSizeUser, Digest, FixedOutput, FixedOutputReset}, + hazmat::PrehashSigner, + rand_core::{CryptoRng, RngCore}, + DigestSigner, RandomizedDigestSigner, RandomizedSigner, Signer, +}; + +#[cfg(feature = "pem")] +use { + crate::elliptic_curve::pkcs8::{EncodePrivateKey, SecretDocument}, + core::str::FromStr, +}; + +#[cfg(feature = "pkcs8")] +use crate::elliptic_curve::{ + pkcs8::{self, AssociatedOid, DecodePrivateKey}, + sec1::{self, FromEncodedPoint, ToEncodedPoint}, + AffinePoint, +}; + +#[cfg(feature = "verify")] +use {crate::verify::VerifyingKey, elliptic_curve::PublicKey, signature::Keypair}; + +/// ECDSA signing key. Generic over elliptic curves. +/// +/// Requires an [`elliptic_curve::ProjectiveArithmetic`] impl on the curve, and a +/// [`SignPrimitive`] impl on its associated `Scalar` type. +#[derive(Clone)] +#[cfg_attr(docsrs, doc(cfg(feature = "sign")))] +pub struct SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + /// ECDSA signing keys are non-zero elements of a given curve's scalar field. + secret_scalar: NonZeroScalar<C>, + + /// Verifying key which corresponds to this signing key. + #[cfg(feature = "verify")] + verifying_key: VerifyingKey<C>, +} + +impl<C> SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + /// Generate a cryptographically random [`SigningKey`]. + pub fn random(rng: impl CryptoRng + RngCore) -> Self { + NonZeroScalar::<C>::random(rng).into() + } + + /// Initialize signing key from a raw scalar serialized as a byte slice. + pub fn from_bytes(bytes: &[u8]) -> Result<Self> { + SecretKey::<C>::from_be_bytes(bytes) + .map(|sk| sk.to_nonzero_scalar().into()) + .map_err(|_| Error::new()) + } + + /// Serialize this [`SigningKey`] as bytes + pub fn to_bytes(&self) -> FieldBytes<C> { + self.secret_scalar.to_repr() + } + + /// Borrow the secret [`NonZeroScalar`] value for this key. + /// + /// # โ ๏ธ Warning + /// + /// This value is key material. + /// + /// Please treat it with the care it deserves! + pub fn as_nonzero_scalar(&self) -> &NonZeroScalar<C> { + &self.secret_scalar + } + + /// Get the [`VerifyingKey`] which corresponds to this [`SigningKey`] + // TODO(tarcieri): make this return `&VerifyingKey<C>` in the next breaking release + #[cfg(feature = "verify")] + #[cfg_attr(docsrs, doc(cfg(feature = "verify")))] + pub fn verifying_key(&self) -> VerifyingKey<C> { + self.verifying_key + } +} + +#[cfg(feature = "verify")] +#[cfg_attr(docsrs, doc(cfg(feature = "verify")))] +impl<C> AsRef<VerifyingKey<C>> for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn as_ref(&self) -> &VerifyingKey<C> { + &self.verifying_key + } +} + +impl<C> ConstantTimeEq for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn ct_eq(&self, other: &Self) -> Choice { + self.secret_scalar.ct_eq(&other.secret_scalar) + } +} + +impl<C> Debug for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SigningKey").finish_non_exhaustive() + } +} + +impl<C> Drop for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn drop(&mut self) { + self.secret_scalar.zeroize(); + } +} + +impl<C> ZeroizeOnDrop for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ +} + +/// Constant-time comparison +impl<C> Eq for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ +} + +/// Constant-time comparison +impl<C> PartialEq for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn eq(&self, other: &SigningKey<C>) -> bool { + self.ct_eq(other).into() + } +} + +impl<C> From<SecretKey<C>> for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn from(secret_key: SecretKey<C>) -> Self { + Self::from(&secret_key) + } +} + +impl<C> From<&SecretKey<C>> for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn from(secret_key: &SecretKey<C>) -> Self { + secret_key.to_nonzero_scalar().into() + } +} + +impl<C> From<SigningKey<C>> for SecretKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn from(key: SigningKey<C>) -> Self { + key.secret_scalar.into() + } +} + +impl<C> From<&SigningKey<C>> for SecretKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn from(secret_key: &SigningKey<C>) -> Self { + secret_key.secret_scalar.into() + } +} + +impl<C, D> DigestSigner<D, Signature<C>> for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + C::UInt: for<'a> From<&'a Scalar<C>>, + D: Digest + BlockSizeUser + FixedOutput<OutputSize = FieldSize<C>> + FixedOutputReset, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + + SignatureSize<C>: ArrayLength<u8>, +{ + /// Sign message digest using a deterministic ephemeral scalar (`k`) + /// computed using the algorithm described in [RFC6979 ยง 3.2]. + /// + /// [RFC6979 ยง 3.2]: https://tools.ietf.org/html/rfc6979#section-3 + fn try_sign_digest(&self, msg_digest: D) -> Result<Signature<C>> { + Ok(self + .secret_scalar + .try_sign_digest_rfc6979::<D>(msg_digest, &[])? + .0) + } +} + +#[cfg(feature = "verify")] +#[cfg_attr(docsrs, doc(cfg(feature = "verify")))] +impl<C> Keypair<Signature<C>> for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + type VerifyingKey = VerifyingKey<C>; +} + +impl<C> PrehashSigner<Signature<C>> for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic + DigestPrimitive, + C::Digest: BlockSizeUser + FixedOutput<OutputSize = FieldSize<C>> + FixedOutputReset, + C::UInt: for<'a> From<&'a Scalar<C>>, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn sign_prehash(&self, prehash: &[u8]) -> Result<Signature<C>> { + let prehash = C::prehash_to_field_bytes(prehash)?; + + Ok(self + .secret_scalar + .try_sign_prehashed_rfc6979::<C::Digest>(prehash, &[])? + .0) + } +} + +impl<C> Signer<Signature<C>> for SigningKey<C> +where + Self: DigestSigner<C::Digest, Signature<C>>, + C: PrimeCurve + ProjectiveArithmetic + DigestPrimitive, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn try_sign(&self, msg: &[u8]) -> Result<Signature<C>> { + self.try_sign_digest(C::Digest::new_with_prefix(msg)) + } +} + +impl<C, D> RandomizedDigestSigner<D, Signature<C>> for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + C::UInt: for<'a> From<&'a Scalar<C>>, + D: Digest + BlockSizeUser + FixedOutput<OutputSize = FieldSize<C>> + FixedOutputReset, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + /// Sign message prehash using an ephemeral scalar (`k`) derived according + /// to a variant of RFC 6979 (Section 3.6) which supplies additional + /// entropy from an RNG. + fn try_sign_digest_with_rng( + &self, + mut rng: impl CryptoRng + RngCore, + msg_digest: D, + ) -> Result<Signature<C>> { + let mut ad = FieldBytes::<C>::default(); + rng.fill_bytes(&mut ad); + Ok(self + .secret_scalar + .try_sign_digest_rfc6979::<D>(msg_digest, &ad)? + .0) + } +} + +impl<C> RandomizedSigner<Signature<C>> for SigningKey<C> +where + Self: RandomizedDigestSigner<C::Digest, Signature<C>>, + C: PrimeCurve + ProjectiveArithmetic + DigestPrimitive, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn try_sign_with_rng(&self, rng: impl CryptoRng + RngCore, msg: &[u8]) -> Result<Signature<C>> { + self.try_sign_digest_with_rng(rng, C::Digest::new_with_prefix(msg)) + } +} + +impl<C> From<NonZeroScalar<C>> for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn from(secret_scalar: NonZeroScalar<C>) -> Self { + #[cfg(feature = "verify")] + let public_key = PublicKey::from_secret_scalar(&secret_scalar); + + Self { + secret_scalar, + #[cfg(feature = "verify")] + verifying_key: public_key.into(), + } + } +} + +impl<C> TryFrom<&[u8]> for SigningKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + type Error = Error; + + fn try_from(bytes: &[u8]) -> Result<Self> { + Self::from_bytes(bytes) + } +} + +#[cfg(feature = "verify")] +impl<C> From<&SigningKey<C>> for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn from(signing_key: &SigningKey<C>) -> VerifyingKey<C> { + signing_key.verifying_key() + } +} + +#[cfg(feature = "pkcs8")] +#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))] +impl<C> TryFrom<pkcs8::PrivateKeyInfo<'_>> for SigningKey<C> +where + C: PrimeCurve + AssociatedOid + ProjectiveArithmetic, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + type Error = pkcs8::Error; + + fn try_from(private_key_info: pkcs8::PrivateKeyInfo<'_>) -> pkcs8::Result<Self> { + SecretKey::try_from(private_key_info).map(Into::into) + } +} + +#[cfg(feature = "pem")] +#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] +impl<C> EncodePrivateKey for SigningKey<C> +where + C: AssociatedOid + PrimeCurve + ProjectiveArithmetic, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn to_pkcs8_der(&self) -> pkcs8::Result<SecretDocument> { + SecretKey::from(self.secret_scalar).to_pkcs8_der() + } +} + +#[cfg(feature = "pkcs8")] +#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))] +impl<C> DecodePrivateKey for SigningKey<C> +where + C: PrimeCurve + AssociatedOid + ProjectiveArithmetic, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ +} + +#[cfg(feature = "pem")] +#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] +impl<C> FromStr for SigningKey<C> +where + C: PrimeCurve + AssociatedOid + ProjectiveArithmetic, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, + Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>, + SignatureSize<C>: ArrayLength<u8>, +{ + type Err = Error; + + fn from_str(s: &str) -> Result<Self> { + Self::from_pkcs8_pem(s).map_err(|_| Error::new()) + } +} diff --git a/vendor/ecdsa/src/verify.rs b/vendor/ecdsa/src/verify.rs new file mode 100644 index 000000000..5aa8bcb8d --- /dev/null +++ b/vendor/ecdsa/src/verify.rs @@ -0,0 +1,325 @@ +//! ECDSA verification key. + +use crate::{ + hazmat::{DigestPrimitive, VerifyPrimitive}, + Error, Result, Signature, SignatureSize, +}; +use core::{cmp::Ordering, fmt::Debug}; +use elliptic_curve::{ + generic_array::ArrayLength, + ops::Reduce, + sec1::{self, EncodedPoint, FromEncodedPoint, ToEncodedPoint}, + AffinePoint, FieldSize, PointCompression, PrimeCurve, ProjectiveArithmetic, PublicKey, Scalar, +}; +use signature::{ + digest::{Digest, FixedOutput}, + hazmat::PrehashVerifier, + DigestVerifier, Verifier, +}; + +#[cfg(feature = "pkcs8")] +use elliptic_curve::pkcs8::{self, AssociatedOid, DecodePublicKey}; + +#[cfg(feature = "pem")] +use elliptic_curve::pkcs8::EncodePublicKey; + +#[cfg(feature = "pem")] +use core::str::FromStr; + +#[cfg(all(feature = "pem", feature = "serde"))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "serde"))))] +use serdect::serde::{de, ser, Deserialize, Serialize}; + +/// ECDSA verification key (i.e. public key). Generic over elliptic curves. +/// +/// Requires an [`elliptic_curve::ProjectiveArithmetic`] impl on the curve, and a +/// [`VerifyPrimitive`] impl on its associated `AffinePoint` type. +/// +/// # `serde` support +/// +/// When the `serde` feature of this crate is enabled, it provides support for +/// serializing and deserializing ECDSA signatures using the `Serialize` and +/// `Deserialize` traits. +/// +/// The serialization leverages the encoding used by the [`PublicKey`] type, +/// which is a binary-oriented ASN.1 DER encoding. +#[cfg_attr(docsrs, doc(cfg(feature = "verify")))] +#[derive(Clone, Debug)] +pub struct VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, +{ + pub(crate) inner: PublicKey<C>, +} + +impl<C> VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + /// Initialize [`VerifyingKey`] from a SEC1-encoded public key. + pub fn from_sec1_bytes(bytes: &[u8]) -> Result<Self> { + PublicKey::from_sec1_bytes(bytes) + .map(|pk| Self { inner: pk }) + .map_err(|_| Error::new()) + } + + /// Initialize [`VerifyingKey`] from an affine point. + /// + /// Returns an [`Error`] if the given affine point is the additive identity + /// (a.k.a. point at infinity). + pub fn from_affine(affine: AffinePoint<C>) -> Result<Self> { + Ok(Self { + inner: PublicKey::from_affine(affine).map_err(|_| Error::new())?, + }) + } + + /// Initialize [`VerifyingKey`] from an [`EncodedPoint`]. + pub fn from_encoded_point(public_key: &EncodedPoint<C>) -> Result<Self> { + Option::from(PublicKey::<C>::from_encoded_point(public_key)) + .map(|public_key| Self { inner: public_key }) + .ok_or_else(Error::new) + } + + /// Serialize this [`VerifyingKey`] as a SEC1 [`EncodedPoint`], optionally + /// applying point compression. + pub fn to_encoded_point(&self, compress: bool) -> EncodedPoint<C> { + self.inner.to_encoded_point(compress) + } + + /// Borrow the inner [`AffinePoint`] for this public key. + pub fn as_affine(&self) -> &AffinePoint<C> { + self.inner.as_affine() + } +} + +impl<C> AsRef<AffinePoint<C>> for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + fn as_ref(&self) -> &AffinePoint<C> { + self.as_affine() + } +} + +impl<C> Copy for VerifyingKey<C> where C: PrimeCurve + ProjectiveArithmetic {} + +impl<C, D> DigestVerifier<D, Signature<C>> for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + D: Digest + FixedOutput<OutputSize = FieldSize<C>>, + AffinePoint<C>: VerifyPrimitive<C>, + Scalar<C>: Reduce<C::UInt>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn verify_digest(&self, msg_digest: D, signature: &Signature<C>) -> Result<()> { + self.inner.as_affine().verify_digest(msg_digest, signature) + } +} + +impl<C> PrehashVerifier<Signature<C>> for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic + DigestPrimitive, + AffinePoint<C>: VerifyPrimitive<C>, + Scalar<C>: Reduce<C::UInt>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn verify_prehash(&self, prehash: &[u8], signature: &Signature<C>) -> Result<()> { + let prehash = C::prehash_to_field_bytes(prehash)?; + self.inner.as_affine().verify_prehashed(prehash, signature) + } +} + +impl<C> Verifier<Signature<C>> for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic + DigestPrimitive, + C::Digest: FixedOutput<OutputSize = FieldSize<C>>, + AffinePoint<C>: VerifyPrimitive<C>, + Scalar<C>: Reduce<C::UInt>, + SignatureSize<C>: ArrayLength<u8>, +{ + fn verify(&self, msg: &[u8], signature: &Signature<C>) -> Result<()> { + self.verify_digest(C::Digest::new_with_prefix(msg), signature) + } +} + +impl<C> From<&VerifyingKey<C>> for EncodedPoint<C> +where + C: PrimeCurve + ProjectiveArithmetic + PointCompression, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + fn from(verifying_key: &VerifyingKey<C>) -> EncodedPoint<C> { + verifying_key.to_encoded_point(C::COMPRESS_POINTS) + } +} + +impl<C> From<PublicKey<C>> for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, +{ + fn from(public_key: PublicKey<C>) -> VerifyingKey<C> { + VerifyingKey { inner: public_key } + } +} + +impl<C> From<&PublicKey<C>> for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, +{ + fn from(public_key: &PublicKey<C>) -> VerifyingKey<C> { + (*public_key).into() + } +} + +impl<C> From<VerifyingKey<C>> for PublicKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, +{ + fn from(verifying_key: VerifyingKey<C>) -> PublicKey<C> { + verifying_key.inner + } +} + +impl<C> From<&VerifyingKey<C>> for PublicKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, +{ + fn from(verifying_key: &VerifyingKey<C>) -> PublicKey<C> { + (*verifying_key).into() + } +} + +impl<C> Eq for VerifyingKey<C> where C: PrimeCurve + ProjectiveArithmetic {} + +impl<C> PartialEq for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, +{ + fn eq(&self, other: &Self) -> bool { + self.inner.eq(&other.inner) + } +} + +impl<C> PartialOrd for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + self.inner.partial_cmp(&other.inner) + } +} + +impl<C> Ord for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + fn cmp(&self, other: &Self) -> Ordering { + self.inner.cmp(&other.inner) + } +} + +impl<C> TryFrom<&[u8]> for VerifyingKey<C> +where + C: PrimeCurve + ProjectiveArithmetic, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + type Error = Error; + + fn try_from(bytes: &[u8]) -> Result<Self> { + Self::from_sec1_bytes(bytes) + } +} + +#[cfg(feature = "pkcs8")] +#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))] +impl<C> TryFrom<pkcs8::SubjectPublicKeyInfo<'_>> for VerifyingKey<C> +where + C: PrimeCurve + AssociatedOid + ProjectiveArithmetic + PointCompression, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + type Error = pkcs8::spki::Error; + + fn try_from(spki: pkcs8::SubjectPublicKeyInfo<'_>) -> pkcs8::spki::Result<Self> { + PublicKey::try_from(spki).map(|inner| Self { inner }) + } +} + +#[cfg(feature = "pkcs8")] +#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))] +impl<C> DecodePublicKey for VerifyingKey<C> +where + C: PrimeCurve + AssociatedOid + ProjectiveArithmetic + PointCompression, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ +} + +#[cfg(feature = "pem")] +#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] +impl<C> EncodePublicKey for VerifyingKey<C> +where + C: PrimeCurve + AssociatedOid + ProjectiveArithmetic + PointCompression, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + fn to_public_key_der(&self) -> pkcs8::spki::Result<pkcs8::Document> { + self.inner.to_public_key_der() + } +} + +#[cfg(feature = "pem")] +#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] +impl<C> FromStr for VerifyingKey<C> +where + C: PrimeCurve + AssociatedOid + ProjectiveArithmetic + PointCompression, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + type Err = Error; + + fn from_str(s: &str) -> Result<Self> { + Self::from_public_key_pem(s).map_err(|_| Error::new()) + } +} + +#[cfg(all(feature = "pem", feature = "serde"))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "serde"))))] +impl<C> Serialize for VerifyingKey<C> +where + C: PrimeCurve + AssociatedOid + ProjectiveArithmetic + PointCompression, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + self.inner.serialize(serializer) + } +} + +#[cfg(all(feature = "pem", feature = "serde"))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "serde"))))] +impl<'de, C> Deserialize<'de> for VerifyingKey<C> +where + C: PrimeCurve + AssociatedOid + ProjectiveArithmetic + PointCompression, + AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>, + FieldSize<C>: sec1::ModulusSize, +{ + fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error> + where + D: de::Deserializer<'de>, + { + PublicKey::<C>::deserialize(deserializer).map(Into::into) + } +} diff --git a/vendor/ecdsa/tests/lib.rs b/vendor/ecdsa/tests/lib.rs new file mode 100644 index 000000000..1b622f8bd --- /dev/null +++ b/vendor/ecdsa/tests/lib.rs @@ -0,0 +1,14 @@ +//! Smoke tests which use `MockCurve` + +#![cfg(feature = "dev")] + +use elliptic_curve::dev::MockCurve; + +type Signature = ecdsa::Signature<MockCurve>; +type SignatureBytes = ecdsa::SignatureBytes<MockCurve>; + +#[test] +fn rejects_all_zero_signature() { + let all_zero_bytes = SignatureBytes::default(); + assert!(Signature::try_from(all_zero_bytes.as_ref()).is_err()); +} |