chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

1
vendor/ecdsa/.cargo-checksum.json vendored Normal file
View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"6f3aac664bb2f64595adc11af8cb5f2fec981f046e2226afa8f68e7aec18fa02","CHANGELOG.md":"a6b49a96975d94d85d698369e5e1fc3cea7022c381c0ebe741efcc7a2879ba3c","Cargo.toml":"a1e1f54de247dd373355a433e3f45c657ea9a127a56154efc285a05b0a82ef52","Cargo.toml.orig":"d2b10e7c1073c0944f7ae5d56b38dafe41ada3ff1f25d2637ef546e90d56111d","LICENSE-APACHE":"78779d420019e6b4630376af8e86b6b335ee8a2f89ede6e0411e0469a326aaa4","LICENSE-MIT":"bdebaf9156a298f8fdab56dd26cb5144673de522d80f4c0d88e0039145f147f9","README.md":"f99485065d3d5541ef1814ea8d3f75718f08cb78eb5626f9d34941799655b4b9","src/der.rs":"12d336b65d1a9d45a44809746c572084d512812e4a8baad23158127a67c583b6","src/dev.rs":"75d56ac79f04efc018b37eca752c7861579772a758cac94874ccf85aa880602a","src/hazmat.rs":"230f3b337e826188825f76eb26ffc2fa19ce8b2bd45cc7b80f87c34f33cfe13d","src/lib.rs":"aeda83d19f5088920a814f9331f45fd0f1026e18bae384ebfaaaeb00b814cb47","src/normalized.rs":"57d6f3c00fa603a42b6351d29f4cb4a101b79277b3217c2bfa963f289fc475c9","src/recovery.rs":"41141f9f4ffbd155c5167fbe749299496077c55e6b64ed83f65ced1372205623","src/signing.rs":"11842af046b43fe53add72a7fdc78a9555a1dbc37fe6bb0d1139e8b25491538f","src/verifying.rs":"c7441025d4ddcfce2c7701813d84c032364da4bd38bd28895a75d09eaca53ee3","tests/lib.rs":"68922b3fb793f7f64a6fdf8aa59b6fb9432d4706d7ad1d82129a8337c5cf6568"},"package":"ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"}

6
vendor/ecdsa/.cargo_vcs_info.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "abd0175f3ae2dc4b118fa914e94c1fc4b0182ba9"
},
"path_in_vcs": "ecdsa"
}

588
vendor/ecdsa/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,588 @@
# 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.16.9 (2023-11-16)
### Changed
- Loosen `signature` bound to `2.0, <2.3` ([#756])
[#756]: https://github.com/RustCrypto/signatures/pull/756
## 0.16.8 (2023-07-20)
### Added
- `hazmat::{sign_prehashed, verify_prehashed}` ([#731])
### Changed
- Refactor `Signature` constructors and improve docs ([#730])
[#730]: https://github.com/RustCrypto/signatures/pull/730
[#731]: https://github.com/RustCrypto/signatures/pull/731
## 0.16.7 (2023-05-11)
### Added
- RFC5480 citation for `der::Signature` ([#710])
- support for the `SignatureBitStringEncoding` trait ([#716])
### Changed
- bump `elliptic-curve` from 0.13.3 to 0.13.4 ([#709])
- `der::Signature` citation to RFC5912 ([#711])
- make `fmt` impls more consistent ([#713])
### Fixed
- `serde` doc fixup ([#712])
[#709]: https://github.com/RustCrypto/signatures/pull/709
[#710]: https://github.com/RustCrypto/signatures/pull/710
[#711]: https://github.com/RustCrypto/signatures/pull/711
[#712]: https://github.com/RustCrypto/signatures/pull/712
[#713]: https://github.com/RustCrypto/signatures/pull/713
[#716]: https://github.com/RustCrypto/signatures/pull/716
## 0.16.6 (2023-04-09)
### Fixed
- Test macro handling of serialized field size ([#707])
[#707]: https://github.com/RustCrypto/signatures/pull/707
## 0.16.5 (2023-04-08)
### Fixed
- Use `C::FieldBytesSize` instead of `C::Uint::BYTES` ([#705])
[#705]: https://github.com/RustCrypto/signatures/pull/705
## 0.16.4 (2023-04-05)
### Fixed
- `RecoveryId` computation in `SignPrimitive` ([#702])
[#702]: https://github.com/RustCrypto/signatures/pull/702
## 0.16.3 (2023-04-04)
### Added
- RFC5758 OID support ([#686])
- `SignatureAlgorithmIdentifier` impls for `SigningKey`/`VerifyingKey` ([#688])
- `SignatureWithOid` ([#689], [#690])
- `AssociatedAlgorithmIdentifier` impls for `SigningKey`/`VerifyingKey` ([#698])
### Changed
- Loosen `signature` bound to `2.0, <2.2` ([#697])
[#686]: https://github.com/RustCrypto/signatures/pull/686
[#688]: https://github.com/RustCrypto/signatures/pull/688
[#689]: https://github.com/RustCrypto/signatures/pull/689
[#690]: https://github.com/RustCrypto/signatures/pull/690
[#697]: https://github.com/RustCrypto/signatures/pull/697
[#698]: https://github.com/RustCrypto/signatures/pull/698
## 0.16.2 (2023-03-28)
### Added
- Handle the reduced R.x case in public key recovery ([#680])
- `Signature::{from_bytes, from_slice}` methods ([#684])
[#680]: https://github.com/RustCrypto/signatures/pull/680
[#684]: https://github.com/RustCrypto/signatures/pull/684
## 0.16.1 (2023-03-09)
### Added
- `VerifyingKey::to_sec1_bytes` + more conversions ([#675])
[#675]: https://github.com/RustCrypto/signatures/pull/675
## 0.16.0 (2023-03-01)
### Added
- `Decode` and `Encode` impls for `der::Signature` ([#666])
### Changed
- Use `Scalar::invert_vartime` for faster verification ([#651])
- Bump `serdect` dependency to 0.2 ([#657])
- Bump `elliptic-curve` dependency to v0.13; MSRV 1.65 ([#660], [#663])
- Bump `rfc6979` dependency to v0.4 ([#662])
[#651]: https://github.com/RustCrypto/signatures/pull/651
[#657]: https://github.com/RustCrypto/signatures/pull/657
[#660]: https://github.com/RustCrypto/signatures/pull/660
[#662]: https://github.com/RustCrypto/signatures/pull/662
[#666]: https://github.com/RustCrypto/signatures/pull/666
## 0.15.1 (2023-01-23)
### Added
- `SigningKey::*_recoverable` methods ([#635])
[#635]: https://github.com/RustCrypto/signatures/pull/635
## 0.15.0 (2023-01-15)
### Added
- `DigestPrimitive::Digest` now has bounds that work with RFC6979 ([#568])
- `*Signer`/`*Verifier` impls for `der::Signature` ([#569])
- `VerifyingKey` recovery support ([#576])
- Trial recovery support ([#580])
### Changed
- Signature now internally structured with `r` and `s` components ([#565])
- `SigningKey::verifying_key` now returns a reference ([#567])
- Refactor `prehash_to_field_bytes` to `bits2field` free function ([#574])
- Rename `sign` feature to `signing` ([#610])
- Rename `verify` feature to `verifying` features ([#610])
- Bump `signature` crate dependency to v2.0 ([#614])
[#565]: https://github.com/RustCrypto/signatures/pull/565
[#567]: https://github.com/RustCrypto/signatures/pull/567
[#574]: https://github.com/RustCrypto/signatures/pull/574
[#580]: https://github.com/RustCrypto/signatures/pull/580
[#568]: https://github.com/RustCrypto/signatures/pull/568
[#569]: https://github.com/RustCrypto/signatures/pull/569
[#576]: https://github.com/RustCrypto/signatures/pull/576
[#580]: https://github.com/RustCrypto/signatures/pull/580
[#610]: https://github.com/RustCrypto/signatures/pull/610
[#614]: https://github.com/RustCrypto/signatures/pull/614
## 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

148
vendor/ecdsa/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,148 @@
# 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.65"
name = "ecdsa"
version = "0.16.9"
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.7"
optional = true
[dependencies.digest]
version = "0.10.7"
features = ["oid"]
optional = true
default-features = false
[dependencies.elliptic-curve]
version = "0.13.6"
features = [
"digest",
"sec1",
]
default-features = false
[dependencies.rfc6979]
version = "0.4"
optional = true
[dependencies.serdect]
version = "0.2"
features = ["alloc"]
optional = true
default-features = false
[dependencies.sha2]
version = "0.10"
features = ["oid"]
optional = true
default-features = false
[dependencies.signature]
version = "2.0, <2.3"
features = ["rand_core"]
default-features = false
[dependencies.spki]
version = "0.7.2"
optional = true
default-features = false
[dev-dependencies.elliptic-curve]
version = "0.13"
features = ["dev"]
default-features = false
[dev-dependencies.hex-literal]
version = "0.4"
[dev-dependencies.sha2]
version = "0.10"
default-features = false
[features]
alloc = [
"elliptic-curve/alloc",
"signature/alloc",
"spki/alloc",
]
arithmetic = ["elliptic-curve/arithmetic"]
default = ["digest"]
dev = [
"arithmetic",
"digest",
"elliptic-curve/dev",
"hazmat",
]
digest = [
"dep:digest",
"signature/digest",
]
hazmat = []
pem = [
"elliptic-curve/pem",
"pkcs8",
]
pkcs8 = [
"digest",
"elliptic-curve/pkcs8",
"der",
]
serde = [
"elliptic-curve/serde",
"serdect",
]
signing = [
"arithmetic",
"digest",
"hazmat",
"rfc6979",
]
std = [
"alloc",
"elliptic-curve/std",
"signature/std",
]
verifying = [
"arithmetic",
"digest",
"hazmat",
]

201
vendor/ecdsa/LICENSE-APACHE vendored Normal file
View File

@@ -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.

25
vendor/ecdsa/LICENSE-MIT vendored Normal file
View File

@@ -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.

93
vendor/ecdsa/README.md vendored Normal file
View File

@@ -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.65** 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.65+-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

464
vendor/ecdsa/src/der.rs vendored Normal file
View File

@@ -0,0 +1,464 @@
//! Support for ASN.1 DER-encoded ECDSA signatures as specified in
//! [RFC5912 Appendix A].
//!
//! [RFC5912 Appendix A]: https://www.rfc-editor.org/rfc/rfc5912#appendix-A
use crate::{Error, Result};
use core::{
fmt::{self, Debug},
ops::{Add, Range},
};
use der::{asn1::UintRef, Decode, Encode, FixedTag, Length, Reader, Tag, Writer};
use elliptic_curve::{
consts::U9,
generic_array::{typenum::Unsigned, ArrayLength, GenericArray},
FieldBytesSize, PrimeCurve,
};
#[cfg(feature = "alloc")]
use {
alloc::{boxed::Box, vec::Vec},
signature::SignatureEncoding,
spki::{der::asn1::BitString, SignatureBitStringEncoding},
};
#[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> = <<FieldBytesSize<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 as specified in [RFC5912 Appendix A]:
///
/// ```text
/// ECDSA-Sig-Value ::= SEQUENCE {
/// r INTEGER,
/// s INTEGER
/// }
/// ```
///
/// [RFC5912 Appendix A]: https://www.rfc-editor.org/rfc/rfc5912#appendix-A
pub struct Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<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>,
}
#[allow(clippy::len_without_is_empty)]
impl<C> Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
/// Parse signature from DER-encoded bytes.
pub fn from_bytes(input: &[u8]) -> Result<Self> {
let (r, s) = decode_der(input).map_err(|_| Error::new())?;
if r.as_bytes().len() > C::FieldBytesSize::USIZE
|| s.as_bytes().len() > C::FieldBytesSize::USIZE
{
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,
})
}
/// Create an ASN.1 DER encoded signature from big endian `r` and `s` scalar
/// components.
pub(crate) fn from_components(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())
}
/// 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()
}
/// Get the length of the signature in bytes
pub fn len(&self) -> usize {
self.s_range.end
}
/// 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>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl<C> Clone for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
fn clone(&self) -> Self {
Self {
bytes: self.bytes.clone(),
r_range: self.r_range.clone(),
s_range: self.s_range.clone(),
}
}
}
impl<C> Debug for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<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<'a, C> Decode<'a> for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
fn decode<R: Reader<'a>>(reader: &mut R) -> der::Result<Self> {
let header = reader.peek_header()?;
header.tag.assert_eq(Tag::Sequence)?;
let mut buf = SignatureBytes::<C>::default();
let len = (header.encoded_len()? + header.length)?;
let slice = buf
.get_mut(..usize::try_from(len)?)
.ok_or_else(|| reader.error(Tag::Sequence.length_error().kind()))?;
reader.read_into(slice)?;
Self::from_bytes(slice).map_err(|_| Tag::Integer.value_error())
}
}
impl<C> Encode for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
fn encoded_len(&self) -> der::Result<Length> {
Length::try_from(self.len())
}
fn encode(&self, writer: &mut impl Writer) -> der::Result<()> {
writer.write(self.as_bytes())
}
}
impl<C> FixedTag for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
const TAG: Tag = Tag::Sequence;
}
impl<C> From<crate::Signature<C>> for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
fn from(sig: crate::Signature<C>) -> Signature<C> {
sig.to_der()
}
}
impl<C> TryFrom<&[u8]> for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
type Error = Error;
fn try_from(input: &[u8]) -> Result<Self> {
Self::from_bytes(input)
}
}
impl<C> TryFrom<Signature<C>> for crate::Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<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::FieldBytesSize::USIZE.saturating_sub(sig.r().len());
let s_begin = bytes.len().saturating_sub(sig.s().len());
bytes[r_begin..C::FieldBytesSize::USIZE].copy_from_slice(sig.r());
bytes[s_begin..].copy_from_slice(sig.s());
Self::try_from(bytes.as_slice())
}
}
#[cfg(feature = "alloc")]
impl<C> From<Signature<C>> for Box<[u8]>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
fn from(signature: Signature<C>) -> Box<[u8]> {
signature.to_vec().into_boxed_slice()
}
}
#[cfg(feature = "alloc")]
impl<C> SignatureEncoding for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
type Repr = Box<[u8]>;
fn to_vec(&self) -> Vec<u8> {
self.as_bytes().into()
}
}
#[cfg(feature = "alloc")]
impl<C> SignatureBitStringEncoding for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
fn to_bitstring(&self) -> der::Result<BitString> {
BitString::new(0, self.to_vec())
}
}
#[cfg(feature = "serde")]
impl<C> Serialize for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<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")]
impl<'de, C> Deserialize<'de> for Signature<C>
where
C: PrimeCurve,
MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<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>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
type Digest = C::Digest;
}
#[cfg(all(test, feature = "arithmetic"))]
mod tests {
use elliptic_curve::dev::MockCurve;
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::try_from(EXAMPLE_SIGNATURE.as_ref()).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());
}
}

230
vendor/ecdsa/src/dev.rs vendored Normal file
View File

@@ -0,0 +1,230 @@
//! 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]
macro_rules! new_signing_test {
($curve:path, $vectors:expr) => {
use $crate::{
elliptic_curve::{
bigint::Encoding,
generic_array::{typenum::Unsigned, GenericArray},
group::ff::PrimeField,
Curve, CurveArithmetic, Scalar,
},
hazmat::SignPrimitive,
};
fn decode_scalar(bytes: &[u8]) -> Option<Scalar<$curve>> {
if bytes.len() == <$curve as Curve>::FieldBytesSize::USIZE {
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");
assert_eq!(
<$curve as Curve>::FieldBytesSize::USIZE,
vector.m.len(),
"invalid vector.m (must be field-sized digest)"
);
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]
macro_rules! new_verification_test {
($curve:path, $vectors:expr) => {
use $crate::{
elliptic_curve::{
generic_array::GenericArray,
group::ff::PrimeField,
sec1::{EncodedPoint, FromEncodedPoint},
AffinePoint, CurveArithmetic, 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]
macro_rules! new_wycheproof_test {
($name:ident, $test_name: expr, $curve:path) => {
use $crate::{
elliptic_curve::{bigint::Integer, 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::FieldBytesSize::USIZE;
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,
);
}
}
}
};
}

332
vendor/ecdsa/src/hazmat.rs vendored Normal file
View File

@@ -0,0 +1,332 @@
//! 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!
use crate::{Error, Result};
use core::cmp;
use elliptic_curve::{generic_array::typenum::Unsigned, FieldBytes, PrimeCurve};
#[cfg(feature = "arithmetic")]
use {
crate::{RecoveryId, SignatureSize},
elliptic_curve::{
ff::{Field, PrimeField},
group::{Curve as _, Group},
ops::{Invert, LinearCombination, MulByGenerator, Reduce},
point::AffineCoordinates,
scalar::IsHigh,
subtle::CtOption,
CurveArithmetic, ProjectivePoint, Scalar,
},
};
#[cfg(feature = "digest")]
use {
elliptic_curve::FieldBytesSize,
signature::{
digest::{core_api::BlockSizeUser, Digest, FixedOutput, FixedOutputReset},
PrehashSignature,
},
};
#[cfg(feature = "rfc6979")]
use elliptic_curve::{FieldBytesEncoding, ScalarPrimitive};
#[cfg(any(feature = "arithmetic", feature = "digest"))]
use crate::{elliptic_curve::generic_array::ArrayLength, Signature};
/// 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")]
pub trait SignPrimitive<C>:
AsRef<Self>
+ Into<FieldBytes<C>>
+ IsHigh
+ PrimeField<Repr = FieldBytes<C>>
+ Reduce<C::Uint, Bytes = FieldBytes<C>>
+ Sized
where
C: PrimeCurve + CurveArithmetic<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.
fn try_sign_prehashed<K>(
&self,
k: K,
z: &FieldBytes<C>,
) -> Result<(Signature<C>, Option<RecoveryId>)>
where
K: AsRef<Self> + Invert<Output = CtOption<Self>>,
{
sign_prehashed(self, k, z).map(|(sig, recid)| (sig, (Some(recid))))
}
/// 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(feature = "rfc6979")]
fn try_sign_prehashed_rfc6979<D>(
&self,
z: &FieldBytes<C>,
ad: &[u8],
) -> Result<(Signature<C>, Option<RecoveryId>)>
where
Self: From<ScalarPrimitive<C>> + Invert<Output = CtOption<Self>>,
D: Digest + BlockSizeUser + FixedOutput<OutputSize = FieldBytesSize<C>> + FixedOutputReset,
{
let k = Scalar::<C>::from_repr(rfc6979::generate_k::<D, _>(
&self.to_repr(),
&C::ORDER.encode_field_bytes(),
z,
ad,
))
.unwrap();
self.try_sign_prehashed::<Self>(k, z)
}
}
/// 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")]
pub trait VerifyPrimitive<C>: AffineCoordinates<FieldRepr = FieldBytes<C>> + Copy + Sized
where
C: PrimeCurve + CurveArithmetic<AffinePoint = Self>,
SignatureSize<C>: ArrayLength<u8>,
{
/// Verify the prehashed message against the provided ECDSA 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<()> {
verify_prehashed(&ProjectivePoint::<C>::from(*self), z, sig)
}
/// Verify message digest against the provided signature.
#[cfg(feature = "digest")]
fn verify_digest<D>(&self, msg_digest: D, sig: &Signature<C>) -> Result<()>
where
D: FixedOutput<OutputSize = FieldBytesSize<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")]
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.
type Digest: BlockSizeUser
+ Digest
+ FixedOutput<OutputSize = FieldBytesSize<Self>>
+ FixedOutputReset;
}
#[cfg(feature = "digest")]
impl<C> PrehashSignature for Signature<C>
where
C: DigestPrimitive,
<FieldBytesSize<C> as core::ops::Add>::Output: ArrayLength<u8>,
{
type Digest = C::Digest;
}
/// Partial implementation of the `bits2int` function as defined in
/// [RFC6979 § 2.3.2] as well as [SEC1] § 2.3.8.
///
/// This is used to convert a message digest whose size may be smaller or
/// larger than the size of the curve's scalar field into a serialized
/// (unreduced) field element.
///
/// [RFC6979 § 2.3.2]: https://datatracker.ietf.org/doc/html/rfc6979#section-2.3.2
/// [SEC1]: https://www.secg.org/sec1-v2.pdf
pub fn bits2field<C: PrimeCurve>(bits: &[u8]) -> Result<FieldBytes<C>> {
// Minimum allowed bits size is half the field size
if bits.len() < C::FieldBytesSize::USIZE / 2 {
return Err(Error::new());
}
let mut field_bytes = FieldBytes::<C>::default();
match bits.len().cmp(&C::FieldBytesSize::USIZE) {
cmp::Ordering::Equal => field_bytes.copy_from_slice(bits),
cmp::Ordering::Less => {
// If bits is smaller than the field size, pad with zeroes on the left
field_bytes[(C::FieldBytesSize::USIZE - bits.len())..].copy_from_slice(bits);
}
cmp::Ordering::Greater => {
// If bits is larger than the field size, truncate
field_bytes.copy_from_slice(&bits[..C::FieldBytesSize::USIZE]);
}
}
Ok(field_bytes)
}
/// Sign a prehashed message digest using the provided secret scalar and
/// ephemeral scalar, returning an ECDSA signature.
///
/// Accepts the following arguments:
///
/// - `d`: signing key. MUST BE UNIFORMLY RANDOM!!!
/// - `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.
#[cfg(feature = "arithmetic")]
#[allow(non_snake_case)]
pub fn sign_prehashed<C, K>(
d: &Scalar<C>,
k: K,
z: &FieldBytes<C>,
) -> Result<(Signature<C>, RecoveryId)>
where
C: PrimeCurve + CurveArithmetic,
K: AsRef<Scalar<C>> + Invert<Output = CtOption<Scalar<C>>>,
SignatureSize<C>: ArrayLength<u8>,
{
// TODO(tarcieri): use `NonZeroScalar<C>` for `k`.
if k.as_ref().is_zero().into() {
return Err(Error::new());
}
let z = <Scalar<C> as Reduce<C::Uint>>::reduce_bytes(z);
// Compute scalar inversion of 𝑘
let k_inv = Option::<Scalar<C>>::from(k.invert()).ok_or_else(Error::new)?;
// Compute 𝑹 = 𝑘×𝑮
let R = ProjectivePoint::<C>::mul_by_generator(k.as_ref()).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 = Scalar::<C>::reduce_bytes(&R.x());
let x_is_reduced = r.to_repr() != R.x();
// Compute 𝒔 as a signature over 𝒓 and 𝒛.
let s = k_inv * (z + (r * d));
// NOTE: `Signature::from_scalars` checks that both `r` and `s` are non-zero.
let signature = Signature::from_scalars(r, s)?;
let recovery_id = RecoveryId::new(R.y_is_odd().into(), x_is_reduced);
Ok((signature, recovery_id))
}
/// Verify the prehashed message against the provided ECDSA signature.
///
/// Accepts the following arguments:
///
/// - `q`: public key with which to verify the signature.
/// - `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.
#[cfg(feature = "arithmetic")]
pub fn verify_prehashed<C>(
q: &ProjectivePoint<C>,
z: &FieldBytes<C>,
sig: &Signature<C>,
) -> Result<()>
where
C: PrimeCurve + CurveArithmetic,
SignatureSize<C>: ArrayLength<u8>,
{
let z = Scalar::<C>::reduce_bytes(z);
let (r, s) = sig.split_scalars();
let s_inv = *s.invert_vartime();
let u1 = z * s_inv;
let u2 = *r * s_inv;
let x = ProjectivePoint::<C>::lincomb(&ProjectivePoint::<C>::generator(), &u1, q, &u2)
.to_affine()
.x();
if *r == Scalar::<C>::reduce_bytes(&x) {
Ok(())
} else {
Err(Error::new())
}
}
#[cfg(test)]
mod tests {
use super::bits2field;
use elliptic_curve::dev::MockCurve;
use hex_literal::hex;
#[test]
fn bits2field_too_small() {
assert!(bits2field::<MockCurve>(b"").is_err());
}
#[test]
fn bits2field_size_less() {
let prehash = hex!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
let field_bytes = bits2field::<MockCurve>(&prehash).unwrap();
assert_eq!(
field_bytes.as_slice(),
&hex!("00000000000000000000000000000000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
);
}
#[test]
fn bits2field_size_eq() {
let prehash = hex!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
let field_bytes = bits2field::<MockCurve>(&prehash).unwrap();
assert_eq!(field_bytes.as_slice(), &prehash);
}
#[test]
fn bits2field_size_greater() {
let prehash = hex!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
let field_bytes = bits2field::<MockCurve>(&prehash).unwrap();
assert_eq!(
field_bytes.as_slice(),
&hex!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
);
}
}

709
vendor/ecdsa/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,709 @@
#![no_std]
#![cfg_attr(docsrs, feature(doc_auto_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 normalized;
mod recovery;
#[cfg(feature = "der")]
pub mod der;
#[cfg(feature = "dev")]
pub mod dev;
#[cfg(feature = "hazmat")]
pub mod hazmat;
#[cfg(feature = "signing")]
mod signing;
#[cfg(feature = "verifying")]
mod verifying;
pub use crate::{normalized::NormalizedSignature, 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, SignatureEncoding};
#[cfg(feature = "signing")]
pub use crate::signing::SigningKey;
#[cfg(feature = "verifying")]
pub use crate::verifying::VerifyingKey;
use core::{fmt, ops::Add};
use elliptic_curve::{
generic_array::{typenum::Unsigned, ArrayLength, GenericArray},
FieldBytes, FieldBytesSize, ScalarPrimitive,
};
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(feature = "arithmetic")]
use {
core::str,
elliptic_curve::{scalar::IsHigh, CurveArithmetic, NonZeroScalar},
};
#[cfg(feature = "digest")]
use digest::{
const_oid::{AssociatedOid, ObjectIdentifier},
Digest,
};
#[cfg(feature = "pkcs8")]
use elliptic_curve::pkcs8::spki::{
der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier,
};
#[cfg(feature = "serde")]
use serdect::serde::{de, ser, Deserialize, Serialize};
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
use elliptic_curve::pkcs8::spki::{
self, AlgorithmIdentifierOwned, DynAssociatedAlgorithmIdentifier,
};
/// OID for ECDSA with SHA-224 digests.
///
/// ```text
/// ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
/// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 1 }
/// ```
// TODO(tarcieri): use `ObjectIdentifier::push_arc` when const unwrap is stable
#[cfg(feature = "digest")]
pub const ECDSA_SHA224_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.4.3.1");
/// OID for ECDSA with SHA-256 digests.
///
/// ```text
/// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
/// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
/// ```
#[cfg(feature = "digest")]
pub const ECDSA_SHA256_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.4.3.2");
/// OID for ECDSA with SHA-384 digests.
///
/// ```text
/// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
/// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
/// ```
#[cfg(feature = "digest")]
pub const ECDSA_SHA384_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.4.3.3");
/// OID for ECDSA with SHA-512 digests.
///
/// ```text
/// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
/// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
/// ```
#[cfg(feature = "digest")]
pub const ECDSA_SHA512_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.4.3.4");
#[cfg(feature = "digest")]
const SHA224_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.4");
#[cfg(feature = "digest")]
const SHA256_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.1");
#[cfg(feature = "digest")]
const SHA384_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.2");
#[cfg(feature = "digest")]
const SHA512_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.3");
/// Size of a fixed sized signature for the given elliptic curve.
pub type SignatureSize<C> = <FieldBytesSize<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
///
/// Both `r` and `s` MUST be non-zero.
///
/// For example, in a curve with a 256-bit modulus like NIST P-256 or
/// secp256k1, `r` and `s` will both be 32-bytes and serialized as big endian,
/// 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 hexadecimal encoding when used with
/// "human readable" text formats, and a binary encoding otherwise.
#[derive(Clone, Eq, PartialEq)]
pub struct Signature<C: PrimeCurve> {
r: ScalarPrimitive<C>,
s: ScalarPrimitive<C>,
}
impl<C> Signature<C>
where
C: PrimeCurve,
SignatureSize<C>: ArrayLength<u8>,
{
/// Parse a signature from fixed-width bytes, i.e. 2 * the size of
/// [`FieldBytes`] for a particular curve.
///
/// # Returns
/// - `Ok(signature)` if the `r` and `s` components are both in the valid
/// range `1..n` when serialized as concatenated big endian integers.
/// - `Err(err)` if the `r` and/or `s` component of the signature is
/// out-of-range when interpreted as a big endian integer.
pub fn from_bytes(bytes: &SignatureBytes<C>) -> Result<Self> {
let (r_bytes, s_bytes) = bytes.split_at(C::FieldBytesSize::USIZE);
let r = FieldBytes::<C>::clone_from_slice(r_bytes);
let s = FieldBytes::<C>::clone_from_slice(s_bytes);
Self::from_scalars(r, s)
}
/// Parse a signature from a byte slice.
pub fn from_slice(slice: &[u8]) -> Result<Self> {
if slice.len() == SignatureSize::<C>::USIZE {
Self::from_bytes(SignatureBytes::<C>::from_slice(slice))
} else {
Err(Error::new())
}
}
/// Parse a signature from ASN.1 DER.
#[cfg(feature = "der")]
pub fn from_der(bytes: &[u8]) -> Result<Self>
where
der::MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<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.
///
/// # Returns
/// - `Ok(signature)` if the `r` and `s` components are both in the valid
/// range `1..n` when serialized as concatenated big endian integers.
/// - `Err(err)` if the `r` and/or `s` component of the signature is
/// out-of-range when interpreted as a big endian integer.
pub fn from_scalars(r: impl Into<FieldBytes<C>>, s: impl Into<FieldBytes<C>>) -> Result<Self> {
let r = ScalarPrimitive::from_slice(&r.into()).map_err(|_| Error::new())?;
let s = ScalarPrimitive::from_slice(&s.into()).map_err(|_| Error::new())?;
if r.is_zero().into() || s.is_zero().into() {
return Err(Error::new());
}
Ok(Self { r, s })
}
/// Split the signature into its `r` and `s` components, represented as bytes.
pub fn split_bytes(&self) -> (FieldBytes<C>, FieldBytes<C>) {
(self.r.to_bytes(), self.s.to_bytes())
}
/// Serialize this signature as bytes.
pub fn to_bytes(&self) -> SignatureBytes<C> {
let mut bytes = SignatureBytes::<C>::default();
let (r_bytes, s_bytes) = bytes.split_at_mut(C::FieldBytesSize::USIZE);
r_bytes.copy_from_slice(&self.r.to_bytes());
s_bytes.copy_from_slice(&self.s.to_bytes());
bytes
}
/// Serialize this signature as ASN.1 DER.
#[cfg(feature = "der")]
pub fn to_der(&self) -> der::Signature<C>
where
der::MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>,
{
let (r, s) = self.split_bytes();
der::Signature::from_components(&r, &s).expect("DER encoding error")
}
/// Convert this signature into a byte vector.
#[cfg(feature = "alloc")]
pub fn to_vec(&self) -> Vec<u8> {
self.to_bytes().to_vec()
}
}
#[cfg(feature = "arithmetic")]
impl<C> Signature<C>
where
C: PrimeCurve + CurveArithmetic,
SignatureSize<C>: ArrayLength<u8>,
{
/// Get the `r` component of this signature
pub fn r(&self) -> NonZeroScalar<C> {
NonZeroScalar::new(self.r.into()).unwrap()
}
/// Get the `s` component of this signature
pub fn s(&self) -> NonZeroScalar<C> {
NonZeroScalar::new(self.s.into()).unwrap()
}
/// 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 mut result = self.clone();
result.s = ScalarPrimitive::from(-s);
Some(result)
} else {
None
}
}
}
impl<C> Copy for Signature<C>
where
C: PrimeCurve,
SignatureSize<C>: ArrayLength<u8>,
<SignatureSize<C> as ArrayLength<u8>>::ArrayType: Copy,
{
}
impl<C> From<Signature<C>> for SignatureBytes<C>
where
C: PrimeCurve,
SignatureSize<C>: ArrayLength<u8>,
{
fn from(signature: Signature<C>) -> SignatureBytes<C> {
signature.to_bytes()
}
}
impl<C> SignatureEncoding for Signature<C>
where
C: PrimeCurve,
SignatureSize<C>: ArrayLength<u8>,
{
type Repr = SignatureBytes<C>;
}
impl<C> TryFrom<&[u8]> for Signature<C>
where
C: PrimeCurve,
SignatureSize<C>: ArrayLength<u8>,
{
type Error = Error;
fn try_from(slice: &[u8]) -> Result<Self> {
Self::from_slice(slice)
}
}
impl<C> fmt::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.to_bytes() {
write!(f, "{:02X}", byte)?;
}
write!(f, ")")
}
}
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.to_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.to_bytes() {
write!(f, "{:02X}", byte)?;
}
Ok(())
}
}
#[cfg(feature = "arithmetic")]
impl<C> str::FromStr for Signature<C>
where
C: PrimeCurve + CurveArithmetic,
SignatureSize<C>: ArrayLength<u8>,
{
type Err = Error;
fn from_str(hex: &str) -> Result<Self> {
if hex.as_bytes().len() != C::FieldBytesSize::USIZE * 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::FieldBytesSize::USIZE * 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)
}
}
/// ECDSA [`ObjectIdentifier`] which identifies the digest used by default
/// with the `Signer` and `Verifier` traits.
///
/// To support non-default digest algorithms, use the [`SignatureWithOid`]
/// type instead.
#[cfg(all(feature = "digest", feature = "hazmat"))]
impl<C> AssociatedOid for Signature<C>
where
C: hazmat::DigestPrimitive,
C::Digest: AssociatedOid,
{
const OID: ObjectIdentifier = match ecdsa_oid_for_digest(C::Digest::OID) {
Some(oid) => oid,
None => panic!("no RFC5758 ECDSA OID defined for DigestPrimitive::Digest"),
};
}
/// ECDSA `AlgorithmIdentifier` which identifies the digest used by default
/// with the `Signer` and `Verifier` traits.
#[cfg(feature = "pkcs8")]
impl<C> AssociatedAlgorithmIdentifier for Signature<C>
where
C: PrimeCurve,
Self: AssociatedOid,
{
type Params = AnyRef<'static>;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = AlgorithmIdentifierRef {
oid: Self::OID,
parameters: None,
};
}
#[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.to_bytes(), serializer)
}
}
#[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)
}
}
/// An extended [`Signature`] type which is parameterized by an
/// `ObjectIdentifier` which identifies the ECDSA variant used by a
/// particular signature.
///
/// Valid `ObjectIdentifiers` are defined in [RFC5758 § 3.2]:
///
/// - SHA-224: [`ECDSA_SHA224_OID`] (1.2.840.10045.4.3.1)
/// - SHA-256: [`ECDSA_SHA256_OID`] (1.2.840.10045.4.3.2)
/// - SHA-384: [`ECDSA_SHA384_OID`] (1.2.840.10045.4.3.3)
/// - SHA-512: [`ECDSA_SHA512_OID`] (1.2.840.10045.4.3.4)
///
/// [RFC5758 § 3.2]: https://www.rfc-editor.org/rfc/rfc5758#section-3.2
#[cfg(feature = "digest")]
#[derive(Clone, Eq, PartialEq)]
pub struct SignatureWithOid<C: PrimeCurve> {
/// Inner signature type.
signature: Signature<C>,
/// OID which identifies the ECDSA variant used.
///
/// MUST be one of the ECDSA algorithm variants as defined in RFC5758.
///
/// These OIDs begin with `1.2.840.10045.4`.
oid: ObjectIdentifier,
}
#[cfg(feature = "digest")]
impl<C> SignatureWithOid<C>
where
C: PrimeCurve,
{
/// Create a new signature with an explicitly provided OID.
///
/// OID must begin with `1.2.840.10045.4`, the [RFC5758] OID prefix for
/// ECDSA variants.
///
/// [RFC5758]: https://www.rfc-editor.org/rfc/rfc5758#section-3.2
pub fn new(signature: Signature<C>, oid: ObjectIdentifier) -> Result<Self> {
// TODO(tarcieri): use `ObjectIdentifier::starts_with`
for (arc1, arc2) in ObjectIdentifier::new_unwrap("1.2.840.10045.4.3")
.arcs()
.zip(oid.arcs())
{
if arc1 != arc2 {
return Err(Error::new());
}
}
Ok(Self { signature, oid })
}
/// Create a new signature, determining the OID from the given digest.
///
/// Supports SHA-2 family digests as enumerated in [RFC5758 § 3.2], i.e.
/// SHA-224, SHA-256, SHA-384, or SHA-512.
///
/// [RFC5758 § 3.2]: https://www.rfc-editor.org/rfc/rfc5758#section-3.2
pub fn new_with_digest<D>(signature: Signature<C>) -> Result<Self>
where
D: AssociatedOid + Digest,
{
let oid = ecdsa_oid_for_digest(D::OID).ok_or_else(Error::new)?;
Ok(Self { signature, oid })
}
/// Parse a signature from fixed-with bytes.
pub fn from_bytes_with_digest<D>(bytes: &SignatureBytes<C>) -> Result<Self>
where
D: AssociatedOid + Digest,
SignatureSize<C>: ArrayLength<u8>,
{
Self::new_with_digest::<D>(Signature::<C>::from_bytes(bytes)?)
}
/// Parse a signature from a byte slice.
pub fn from_slice_with_digest<D>(slice: &[u8]) -> Result<Self>
where
D: AssociatedOid + Digest,
SignatureSize<C>: ArrayLength<u8>,
{
Self::new_with_digest::<D>(Signature::<C>::from_slice(slice)?)
}
/// Get the fixed-width ECDSA signature.
pub fn signature(&self) -> &Signature<C> {
&self.signature
}
/// Get the ECDSA OID for this signature.
pub fn oid(&self) -> ObjectIdentifier {
self.oid
}
/// Serialize this signature as bytes.
pub fn to_bytes(&self) -> SignatureBytes<C>
where
SignatureSize<C>: ArrayLength<u8>,
{
self.signature.to_bytes()
}
}
#[cfg(feature = "digest")]
impl<C> Copy for SignatureWithOid<C>
where
C: PrimeCurve,
SignatureSize<C>: ArrayLength<u8>,
<SignatureSize<C> as ArrayLength<u8>>::ArrayType: Copy,
{
}
#[cfg(feature = "digest")]
impl<C> From<SignatureWithOid<C>> for Signature<C>
where
C: PrimeCurve,
{
fn from(sig: SignatureWithOid<C>) -> Signature<C> {
sig.signature
}
}
#[cfg(feature = "digest")]
impl<C> From<SignatureWithOid<C>> for SignatureBytes<C>
where
C: PrimeCurve,
SignatureSize<C>: ArrayLength<u8>,
{
fn from(signature: SignatureWithOid<C>) -> SignatureBytes<C> {
signature.to_bytes()
}
}
/// NOTE: this implementation assumes the default digest for the given elliptic
/// curve as defined by [`hazmat::DigestPrimitive`].
///
/// When working with alternative digests, you will need to use e.g.
/// [`SignatureWithOid::new_with_digest`].
#[cfg(all(feature = "digest", feature = "hazmat"))]
impl<C> SignatureEncoding for SignatureWithOid<C>
where
C: hazmat::DigestPrimitive,
C::Digest: AssociatedOid,
SignatureSize<C>: ArrayLength<u8>,
{
type Repr = SignatureBytes<C>;
}
/// NOTE: this implementation assumes the default digest for the given elliptic
/// curve as defined by [`hazmat::DigestPrimitive`].
///
/// When working with alternative digests, you will need to use e.g.
/// [`SignatureWithOid::new_with_digest`].
#[cfg(all(feature = "digest", feature = "hazmat"))]
impl<C> TryFrom<&[u8]> for SignatureWithOid<C>
where
C: hazmat::DigestPrimitive,
C::Digest: AssociatedOid,
SignatureSize<C>: ArrayLength<u8>,
{
type Error = Error;
fn try_from(slice: &[u8]) -> Result<Self> {
Self::new(Signature::<C>::from_slice(slice)?, C::Digest::OID)
}
}
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
impl<C> DynAssociatedAlgorithmIdentifier for SignatureWithOid<C>
where
C: PrimeCurve,
{
fn algorithm_identifier(&self) -> spki::Result<AlgorithmIdentifierOwned> {
Ok(AlgorithmIdentifierOwned {
oid: self.oid,
parameters: None,
})
}
}
/// Get the ECDSA OID for a given digest OID.
#[cfg(feature = "digest")]
const fn ecdsa_oid_for_digest(digest_oid: ObjectIdentifier) -> Option<ObjectIdentifier> {
match digest_oid {
SHA224_OID => Some(ECDSA_SHA224_OID),
SHA256_OID => Some(ECDSA_SHA256_OID),
SHA384_OID => Some(ECDSA_SHA384_OID),
SHA512_OID => Some(ECDSA_SHA512_OID),
_ => None,
}
}

11
vendor/ecdsa/src/normalized.rs vendored Normal file
View File

@@ -0,0 +1,11 @@
//! Support for ECDSA signatures with low-S normalization.
use crate::Signature;
use elliptic_curve::PrimeCurve;
/// ECDSA signature with low-S normalization applied.
#[derive(Clone, Eq, PartialEq)]
#[repr(transparent)]
pub struct NormalizedSignature<C: PrimeCurve> {
inner: Signature<C>,
}

357
vendor/ecdsa/src/recovery.rs vendored Normal file
View File

@@ -0,0 +1,357 @@
//! Public key recovery support.
use crate::{Error, Result};
#[cfg(feature = "signing")]
use {
crate::{hazmat::SignPrimitive, SigningKey},
elliptic_curve::subtle::CtOption,
signature::{hazmat::PrehashSigner, DigestSigner, Signer},
};
#[cfg(feature = "verifying")]
use {
crate::{hazmat::VerifyPrimitive, VerifyingKey},
elliptic_curve::{
bigint::CheckedAdd,
ops::{LinearCombination, Reduce},
point::DecompressPoint,
sec1::{self, FromEncodedPoint, ToEncodedPoint},
AffinePoint, FieldBytesEncoding, FieldBytesSize, Group, PrimeField, ProjectivePoint,
},
signature::hazmat::PrehashVerifier,
};
#[cfg(any(feature = "signing", feature = "verifying"))]
use {
crate::{
hazmat::{bits2field, DigestPrimitive},
Signature, SignatureSize,
},
elliptic_curve::{
generic_array::ArrayLength, ops::Invert, CurveArithmetic, PrimeCurve, Scalar,
},
signature::digest::Digest,
};
/// 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
}
}
#[cfg(feature = "verifying")]
impl RecoveryId {
/// Given a public key, message, and signature, use trial recovery
/// to determine if a suitable recovery ID exists, or return an error
/// otherwise.
pub fn trial_recovery_from_msg<C>(
verifying_key: &VerifyingKey<C>,
msg: &[u8],
signature: &Signature<C>,
) -> Result<Self>
where
C: DigestPrimitive + PrimeCurve + CurveArithmetic,
AffinePoint<C>:
DecompressPoint<C> + FromEncodedPoint<C> + ToEncodedPoint<C> + VerifyPrimitive<C>,
FieldBytesSize<C>: sec1::ModulusSize,
SignatureSize<C>: ArrayLength<u8>,
{
Self::trial_recovery_from_digest(verifying_key, C::Digest::new_with_prefix(msg), signature)
}
/// Given a public key, message digest, and signature, use trial recovery
/// to determine if a suitable recovery ID exists, or return an error
/// otherwise.
pub fn trial_recovery_from_digest<C, D>(
verifying_key: &VerifyingKey<C>,
digest: D,
signature: &Signature<C>,
) -> Result<Self>
where
C: PrimeCurve + CurveArithmetic,
D: Digest,
AffinePoint<C>:
DecompressPoint<C> + FromEncodedPoint<C> + ToEncodedPoint<C> + VerifyPrimitive<C>,
FieldBytesSize<C>: sec1::ModulusSize,
SignatureSize<C>: ArrayLength<u8>,
{
Self::trial_recovery_from_prehash(verifying_key, &digest.finalize(), signature)
}
/// Given a public key, message digest, and signature, use trial recovery
/// to determine if a suitable recovery ID exists, or return an error
/// otherwise.
pub fn trial_recovery_from_prehash<C>(
verifying_key: &VerifyingKey<C>,
prehash: &[u8],
signature: &Signature<C>,
) -> Result<Self>
where
C: PrimeCurve + CurveArithmetic,
AffinePoint<C>:
DecompressPoint<C> + FromEncodedPoint<C> + ToEncodedPoint<C> + VerifyPrimitive<C>,
FieldBytesSize<C>: sec1::ModulusSize,
SignatureSize<C>: ArrayLength<u8>,
{
for id in 0..=Self::MAX {
let recovery_id = RecoveryId(id);
if let Ok(vk) = VerifyingKey::recover_from_prehash(prehash, signature, recovery_id) {
if verifying_key == &vk {
return Ok(recovery_id);
}
}
}
Err(Error::new())
}
}
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(feature = "signing")]
impl<C> SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
/// Sign the given message prehash, returning a signature and recovery ID.
pub fn sign_prehash_recoverable(&self, prehash: &[u8]) -> Result<(Signature<C>, RecoveryId)> {
let z = bits2field::<C>(prehash)?;
let (sig, recid) = self
.as_nonzero_scalar()
.try_sign_prehashed_rfc6979::<C::Digest>(&z, &[])?;
Ok((sig, recid.ok_or_else(Error::new)?))
}
/// Sign the given message digest, returning a signature and recovery ID.
pub fn sign_digest_recoverable<D>(&self, msg_digest: D) -> Result<(Signature<C>, RecoveryId)>
where
D: Digest,
{
self.sign_prehash_recoverable(&msg_digest.finalize())
}
/// Sign the given message, hashing it with the curve's default digest
/// function, and returning a signature and recovery ID.
pub fn sign_recoverable(&self, msg: &[u8]) -> Result<(Signature<C>, RecoveryId)> {
self.sign_digest_recoverable(C::Digest::new_with_prefix(msg))
}
}
#[cfg(feature = "signing")]
impl<C, D> DigestSigner<D, (Signature<C>, RecoveryId)> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
D: Digest,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn try_sign_digest(&self, msg_digest: D) -> Result<(Signature<C>, RecoveryId)> {
self.sign_digest_recoverable(msg_digest)
}
}
#[cfg(feature = "signing")]
impl<C> PrehashSigner<(Signature<C>, RecoveryId)> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn sign_prehash(&self, prehash: &[u8]) -> Result<(Signature<C>, RecoveryId)> {
self.sign_prehash_recoverable(prehash)
}
}
#[cfg(feature = "signing")]
impl<C> Signer<(Signature<C>, RecoveryId)> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn try_sign(&self, msg: &[u8]) -> Result<(Signature<C>, RecoveryId)> {
self.sign_recoverable(msg)
}
}
#[cfg(feature = "verifying")]
impl<C> VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
AffinePoint<C>:
DecompressPoint<C> + FromEncodedPoint<C> + ToEncodedPoint<C> + VerifyPrimitive<C>,
FieldBytesSize<C>: sec1::ModulusSize,
SignatureSize<C>: ArrayLength<u8>,
{
/// Recover a [`VerifyingKey`] from the given message, signature, and
/// [`RecoveryId`].
///
/// The message is first hashed using this curve's [`DigestPrimitive`].
pub fn recover_from_msg(
msg: &[u8],
signature: &Signature<C>,
recovery_id: RecoveryId,
) -> Result<Self>
where
C: DigestPrimitive,
{
Self::recover_from_digest(C::Digest::new_with_prefix(msg), signature, recovery_id)
}
/// Recover a [`VerifyingKey`] from the given message [`Digest`],
/// signature, and [`RecoveryId`].
pub fn recover_from_digest<D>(
msg_digest: D,
signature: &Signature<C>,
recovery_id: RecoveryId,
) -> Result<Self>
where
D: Digest,
{
Self::recover_from_prehash(&msg_digest.finalize(), signature, recovery_id)
}
/// Recover a [`VerifyingKey`] from the given `prehash` of a message, the
/// signature over that prehashed message, and a [`RecoveryId`].
#[allow(non_snake_case)]
pub fn recover_from_prehash(
prehash: &[u8],
signature: &Signature<C>,
recovery_id: RecoveryId,
) -> Result<Self> {
let (r, s) = signature.split_scalars();
let z = <Scalar<C> as Reduce<C::Uint>>::reduce_bytes(&bits2field::<C>(prehash)?);
let mut r_bytes = r.to_repr();
if recovery_id.is_x_reduced() {
match Option::<C::Uint>::from(
C::Uint::decode_field_bytes(&r_bytes).checked_add(&C::ORDER),
) {
Some(restored) => r_bytes = restored.encode_field_bytes(),
// No reduction should happen here if r was reduced
None => return Err(Error::new()),
};
}
let R = AffinePoint::<C>::decompress(&r_bytes, u8::from(recovery_id.is_y_odd()).into());
if R.is_none().into() {
return Err(Error::new());
}
let R = ProjectivePoint::<C>::from(R.unwrap());
let r_inv = *r.invert();
let u1 = -(r_inv * z);
let u2 = r_inv * *s;
let pk = ProjectivePoint::<C>::lincomb(&ProjectivePoint::<C>::generator(), &u1, &R, &u2);
let vk = Self::from_affine(pk.into())?;
// Ensure signature verifies with the recovered key
vk.verify_prehash(prehash, signature)?;
Ok(vk)
}
}
#[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);
}
}

598
vendor/ecdsa/src/signing.rs vendored Normal file
View File

@@ -0,0 +1,598 @@
//! ECDSA signing: producing signatures using a [`SigningKey`].
use crate::{
ecdsa_oid_for_digest,
hazmat::{bits2field, DigestPrimitive, SignPrimitive},
Error, Result, Signature, SignatureSize, SignatureWithOid,
};
use core::fmt::{self, Debug};
use digest::{const_oid::AssociatedOid, Digest, FixedOutput};
use elliptic_curve::{
generic_array::ArrayLength,
group::ff::PrimeField,
ops::Invert,
subtle::{Choice, ConstantTimeEq, CtOption},
zeroize::{Zeroize, ZeroizeOnDrop},
CurveArithmetic, FieldBytes, FieldBytesSize, NonZeroScalar, PrimeCurve, Scalar, SecretKey,
};
use signature::{
hazmat::{PrehashSigner, RandomizedPrehashSigner},
rand_core::CryptoRngCore,
DigestSigner, RandomizedDigestSigner, RandomizedSigner, Signer,
};
#[cfg(feature = "der")]
use {crate::der, core::ops::Add};
#[cfg(feature = "pem")]
use {
crate::elliptic_curve::pkcs8::{DecodePrivateKey, EncodePrivateKey, SecretDocument},
core::str::FromStr,
};
#[cfg(feature = "pkcs8")]
use crate::elliptic_curve::{
pkcs8::{
self,
der::AnyRef,
spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier, SignatureAlgorithmIdentifier},
ObjectIdentifier,
},
sec1::{self, FromEncodedPoint, ToEncodedPoint},
AffinePoint,
};
#[cfg(feature = "verifying")]
use {crate::VerifyingKey, elliptic_curve::PublicKey, signature::KeypairRef};
/// ECDSA secret key used for signing. Generic over prime order elliptic curves
/// (e.g. NIST P-curves)
///
/// Requires an [`elliptic_curve::CurveArithmetic`] impl on the curve, and a
/// [`SignPrimitive`] impl on its associated `Scalar` type.
///
/// ## Usage
///
/// The [`signature`] crate defines the following traits which are the
/// primary API for signing:
///
/// - [`Signer`]: sign a message using this key
/// - [`DigestSigner`]: sign the output of a [`Digest`] using this key
/// - [`PrehashSigner`]: sign the low-level raw output bytes of a message digest
///
/// See the [`p256` crate](https://docs.rs/p256/latest/p256/ecdsa/index.html)
/// for examples of using this type with a concrete elliptic curve.
#[derive(Clone)]
pub struct SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + 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 = "verifying")]
verifying_key: VerifyingKey<C>,
}
impl<C> SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
/// Generate a cryptographically random [`SigningKey`].
pub fn random(rng: &mut impl CryptoRngCore) -> Self {
NonZeroScalar::<C>::random(rng).into()
}
/// Initialize signing key from a raw scalar serialized as a byte array.
pub fn from_bytes(bytes: &FieldBytes<C>) -> Result<Self> {
SecretKey::<C>::from_bytes(bytes)
.map(Into::into)
.map_err(|_| Error::new())
}
/// Initialize signing key from a raw scalar serialized as a byte slice.
pub fn from_slice(bytes: &[u8]) -> Result<Self> {
SecretKey::<C>::from_slice(bytes)
.map(Into::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`].
#[cfg(feature = "verifying")]
pub fn verifying_key(&self) -> &VerifyingKey<C> {
&self.verifying_key
}
}
//
// `*Signer` trait impls
//
/// 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
impl<C, D> DigestSigner<D, Signature<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
D: Digest + FixedOutput<OutputSize = FieldBytesSize<C>>,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn try_sign_digest(&self, msg_digest: D) -> Result<Signature<C>> {
self.sign_prehash(&msg_digest.finalize_fixed())
}
}
/// Sign message prehash 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
impl<C> PrehashSigner<Signature<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn sign_prehash(&self, prehash: &[u8]) -> Result<Signature<C>> {
let z = bits2field::<C>(prehash)?;
Ok(self
.secret_scalar
.try_sign_prehashed_rfc6979::<C::Digest>(&z, &[])?
.0)
}
}
/// Sign message 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
impl<C> Signer<Signature<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + 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 + CurveArithmetic + DigestPrimitive,
D: Digest + FixedOutput<OutputSize = FieldBytesSize<C>>,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn try_sign_digest_with_rng(
&self,
rng: &mut impl CryptoRngCore,
msg_digest: D,
) -> Result<Signature<C>> {
self.sign_prehash_with_rng(rng, &msg_digest.finalize_fixed())
}
}
impl<C> RandomizedPrehashSigner<Signature<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn sign_prehash_with_rng(
&self,
rng: &mut impl CryptoRngCore,
prehash: &[u8],
) -> Result<Signature<C>> {
let z = bits2field::<C>(prehash)?;
let mut ad = FieldBytes::<C>::default();
rng.fill_bytes(&mut ad);
Ok(self
.secret_scalar
.try_sign_prehashed_rfc6979::<C::Digest>(&z, &ad)?
.0)
}
}
impl<C> RandomizedSigner<Signature<C>> for SigningKey<C>
where
Self: RandomizedDigestSigner<C::Digest, Signature<C>>,
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn try_sign_with_rng(&self, rng: &mut impl CryptoRngCore, msg: &[u8]) -> Result<Signature<C>> {
self.try_sign_digest_with_rng(rng, C::Digest::new_with_prefix(msg))
}
}
impl<C, D> DigestSigner<D, SignatureWithOid<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
D: AssociatedOid + Digest + FixedOutput<OutputSize = FieldBytesSize<C>>,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn try_sign_digest(&self, msg_digest: D) -> Result<SignatureWithOid<C>> {
let signature: Signature<C> = self.try_sign_digest(msg_digest)?;
let oid = ecdsa_oid_for_digest(D::OID).ok_or_else(Error::new)?;
SignatureWithOid::new(signature, oid)
}
}
impl<C> Signer<SignatureWithOid<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
C::Digest: AssociatedOid,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn try_sign(&self, msg: &[u8]) -> Result<SignatureWithOid<C>> {
self.try_sign_digest(C::Digest::new_with_prefix(msg))
}
}
#[cfg(feature = "der")]
impl<C> PrehashSigner<der::Signature<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
der::MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>,
{
fn sign_prehash(&self, prehash: &[u8]) -> Result<der::Signature<C>> {
PrehashSigner::<Signature<C>>::sign_prehash(self, prehash).map(Into::into)
}
}
#[cfg(feature = "der")]
impl<C> Signer<der::Signature<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
der::MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>,
{
fn try_sign(&self, msg: &[u8]) -> Result<der::Signature<C>> {
Signer::<Signature<C>>::try_sign(self, msg).map(Into::into)
}
}
#[cfg(feature = "der")]
impl<C, D> RandomizedDigestSigner<D, der::Signature<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
D: Digest + FixedOutput<OutputSize = FieldBytesSize<C>>,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
der::MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>,
{
fn try_sign_digest_with_rng(
&self,
rng: &mut impl CryptoRngCore,
msg_digest: D,
) -> Result<der::Signature<C>> {
RandomizedDigestSigner::<D, Signature<C>>::try_sign_digest_with_rng(self, rng, msg_digest)
.map(Into::into)
}
}
#[cfg(feature = "der")]
impl<C> RandomizedPrehashSigner<der::Signature<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
der::MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>,
{
fn sign_prehash_with_rng(
&self,
rng: &mut impl CryptoRngCore,
prehash: &[u8],
) -> Result<der::Signature<C>> {
RandomizedPrehashSigner::<Signature<C>>::sign_prehash_with_rng(self, rng, prehash)
.map(Into::into)
}
}
#[cfg(feature = "der")]
impl<C> RandomizedSigner<der::Signature<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
der::MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>,
{
fn try_sign_with_rng(
&self,
rng: &mut impl CryptoRngCore,
msg: &[u8],
) -> Result<der::Signature<C>> {
RandomizedSigner::<Signature<C>>::try_sign_with_rng(self, rng, msg).map(Into::into)
}
}
//
// Other trait impls
//
#[cfg(feature = "verifying")]
impl<C> AsRef<VerifyingKey<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn as_ref(&self) -> &VerifyingKey<C> {
&self.verifying_key
}
}
impl<C> ConstantTimeEq for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + 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 + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + 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 + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn drop(&mut self) {
self.secret_scalar.zeroize();
}
}
/// Constant-time comparison
impl<C> Eq for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
}
impl<C> PartialEq for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn eq(&self, other: &SigningKey<C>) -> bool {
self.ct_eq(other).into()
}
}
impl<C> From<NonZeroScalar<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn from(secret_scalar: NonZeroScalar<C>) -> Self {
#[cfg(feature = "verifying")]
let public_key = PublicKey::from_secret_scalar(&secret_scalar);
Self {
secret_scalar,
#[cfg(feature = "verifying")]
verifying_key: public_key.into(),
}
}
}
impl<C> From<SecretKey<C>> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + 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 + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + 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 + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + 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 + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn from(secret_key: &SigningKey<C>) -> Self {
secret_key.secret_scalar.into()
}
}
impl<C> TryFrom<&[u8]> for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
type Error = Error;
fn try_from(bytes: &[u8]) -> Result<Self> {
Self::from_slice(bytes)
}
}
impl<C> ZeroizeOnDrop for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
}
#[cfg(feature = "verifying")]
impl<C> From<SigningKey<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn from(signing_key: SigningKey<C>) -> VerifyingKey<C> {
signing_key.verifying_key
}
}
#[cfg(feature = "verifying")]
impl<C> From<&SigningKey<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn from(signing_key: &SigningKey<C>) -> VerifyingKey<C> {
signing_key.verifying_key
}
}
#[cfg(feature = "verifying")]
impl<C> KeypairRef for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
type VerifyingKey = VerifyingKey<C>;
}
#[cfg(feature = "pkcs8")]
impl<C> AssociatedAlgorithmIdentifier for SigningKey<C>
where
C: AssociatedOid + CurveArithmetic + PrimeCurve,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
type Params = ObjectIdentifier;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<ObjectIdentifier> =
SecretKey::<C>::ALGORITHM_IDENTIFIER;
}
#[cfg(feature = "pkcs8")]
impl<C> SignatureAlgorithmIdentifier for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
Signature<C>: AssociatedAlgorithmIdentifier<Params = AnyRef<'static>>,
{
type Params = AnyRef<'static>;
const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params> =
Signature::<C>::ALGORITHM_IDENTIFIER;
}
#[cfg(feature = "pkcs8")]
impl<C> TryFrom<pkcs8::PrivateKeyInfo<'_>> for SigningKey<C>
where
C: PrimeCurve + AssociatedOid + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + 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")]
impl<C> EncodePrivateKey for SigningKey<C>
where
C: AssociatedOid + PrimeCurve + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn to_pkcs8_der(&self) -> pkcs8::Result<SecretDocument> {
SecretKey::from(self.secret_scalar).to_pkcs8_der()
}
}
#[cfg(feature = "pem")]
impl<C> FromStr for SigningKey<C>
where
C: PrimeCurve + AssociatedOid + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + 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())
}
}

482
vendor/ecdsa/src/verifying.rs vendored Normal file
View File

@@ -0,0 +1,482 @@
//! ECDSA verifying: checking signatures are authentic using a [`VerifyingKey`].
use crate::{
hazmat::{bits2field, DigestPrimitive, VerifyPrimitive},
Error, Result, Signature, SignatureSize,
};
use core::{cmp::Ordering, fmt::Debug};
use elliptic_curve::{
generic_array::ArrayLength,
point::PointCompression,
sec1::{self, CompressedPoint, EncodedPoint, FromEncodedPoint, ToEncodedPoint},
AffinePoint, CurveArithmetic, FieldBytesSize, PrimeCurve, PublicKey,
};
use signature::{
digest::{Digest, FixedOutput},
hazmat::PrehashVerifier,
DigestVerifier, Verifier,
};
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "der")]
use {crate::der, core::ops::Add};
#[cfg(feature = "pem")]
use {
core::str::FromStr,
elliptic_curve::pkcs8::{DecodePublicKey, EncodePublicKey},
};
#[cfg(feature = "pkcs8")]
use elliptic_curve::pkcs8::{
self,
der::AnyRef,
spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier, SignatureAlgorithmIdentifier},
AssociatedOid, ObjectIdentifier,
};
#[cfg(feature = "sha2")]
use {
crate::{
SignatureWithOid, ECDSA_SHA224_OID, ECDSA_SHA256_OID, ECDSA_SHA384_OID, ECDSA_SHA512_OID,
},
sha2::{Sha224, Sha256, Sha384, Sha512},
};
#[cfg(all(feature = "pem", feature = "serde"))]
use serdect::serde::{de, ser, Deserialize, Serialize};
/// ECDSA public key used for verifying signatures. Generic over prime order
/// elliptic curves (e.g. NIST P-curves)
///
/// Requires an [`elliptic_curve::CurveArithmetic`] impl on the curve, and a
/// [`VerifyPrimitive`] impl on its associated `AffinePoint` type.
///
/// ## Usage
///
/// The [`signature`] crate defines the following traits which are the
/// primary API for verifying:
///
/// - [`Verifier`]: verify a message against a provided key and signature
/// - [`DigestVerifier`]: verify a message [`Digest`] against a provided key and signature
/// - [`PrehashVerifier`]: verify the low-level raw output bytes of a message digest
///
/// See the [`p256` crate](https://docs.rs/p256/latest/p256/ecdsa/index.html)
/// for examples of using this type with a concrete elliptic curve.
///
/// # `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.
#[derive(Clone, Debug)]
pub struct VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
{
pub(crate) inner: PublicKey<C>,
}
impl<C> VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<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)
}
/// Convert this [`VerifyingKey`] into the
/// `Elliptic-Curve-Point-to-Octet-String` encoding described in
/// SEC 1: Elliptic Curve Cryptography (Version 2.0) section 2.3.3
/// (page 10).
///
/// <http://www.secg.org/sec1-v2.pdf>
#[cfg(feature = "alloc")]
pub fn to_sec1_bytes(&self) -> Box<[u8]>
where
C: PointCompression,
{
self.inner.to_sec1_bytes()
}
/// Borrow the inner [`AffinePoint`] for this public key.
pub fn as_affine(&self) -> &AffinePoint<C> {
self.inner.as_affine()
}
}
//
// `*Verifier` trait impls
//
impl<C, D> DigestVerifier<D, Signature<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
D: Digest + FixedOutput<OutputSize = FieldBytesSize<C>>,
AffinePoint<C>: VerifyPrimitive<C>,
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 + CurveArithmetic,
AffinePoint<C>: VerifyPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn verify_prehash(&self, prehash: &[u8], signature: &Signature<C>) -> Result<()> {
let field = bits2field::<C>(prehash)?;
self.inner.as_affine().verify_prehashed(&field, signature)
}
}
impl<C> Verifier<Signature<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
AffinePoint<C>: VerifyPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn verify(&self, msg: &[u8], signature: &Signature<C>) -> Result<()> {
self.verify_digest(C::Digest::new_with_prefix(msg), signature)
}
}
#[cfg(feature = "sha2")]
impl<C> Verifier<SignatureWithOid<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
AffinePoint<C>: VerifyPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn verify(&self, msg: &[u8], sig: &SignatureWithOid<C>) -> Result<()> {
match sig.oid() {
ECDSA_SHA224_OID => self.verify_prehash(&Sha224::digest(msg), sig.signature()),
ECDSA_SHA256_OID => self.verify_prehash(&Sha256::digest(msg), sig.signature()),
ECDSA_SHA384_OID => self.verify_prehash(&Sha384::digest(msg), sig.signature()),
ECDSA_SHA512_OID => self.verify_prehash(&Sha512::digest(msg), sig.signature()),
_ => Err(Error::new()),
}
}
}
#[cfg(feature = "der")]
impl<C, D> DigestVerifier<D, der::Signature<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
D: Digest + FixedOutput<OutputSize = FieldBytesSize<C>>,
AffinePoint<C>: VerifyPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
der::MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>,
{
fn verify_digest(&self, msg_digest: D, signature: &der::Signature<C>) -> Result<()> {
let signature = Signature::<C>::try_from(signature.clone())?;
DigestVerifier::<D, Signature<C>>::verify_digest(self, msg_digest, &signature)
}
}
#[cfg(feature = "der")]
impl<C> PrehashVerifier<der::Signature<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
AffinePoint<C>: VerifyPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
der::MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>,
{
fn verify_prehash(&self, prehash: &[u8], signature: &der::Signature<C>) -> Result<()> {
let signature = Signature::<C>::try_from(signature.clone())?;
PrehashVerifier::<Signature<C>>::verify_prehash(self, prehash, &signature)
}
}
#[cfg(feature = "der")]
impl<C> Verifier<der::Signature<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
AffinePoint<C>: VerifyPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
der::MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArrayLength<u8>,
{
fn verify(&self, msg: &[u8], signature: &der::Signature<C>) -> Result<()> {
let signature = Signature::<C>::try_from(signature.clone())?;
Verifier::<Signature<C>>::verify(self, msg, &signature)
}
}
//
// Other trait impls
//
impl<C> AsRef<AffinePoint<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
{
fn as_ref(&self) -> &AffinePoint<C> {
self.as_affine()
}
}
impl<C> Copy for VerifyingKey<C> where C: PrimeCurve + CurveArithmetic {}
impl<C> From<VerifyingKey<C>> for CompressedPoint<C>
where
C: PrimeCurve + CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
{
fn from(verifying_key: VerifyingKey<C>) -> CompressedPoint<C> {
verifying_key.inner.into()
}
}
impl<C> From<&VerifyingKey<C>> for CompressedPoint<C>
where
C: PrimeCurve + CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
{
fn from(verifying_key: &VerifyingKey<C>) -> CompressedPoint<C> {
verifying_key.inner.into()
}
}
impl<C> From<VerifyingKey<C>> for EncodedPoint<C>
where
C: PrimeCurve + CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
{
fn from(verifying_key: VerifyingKey<C>) -> EncodedPoint<C> {
verifying_key.inner.into()
}
}
impl<C> From<&VerifyingKey<C>> for EncodedPoint<C>
where
C: PrimeCurve + CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
{
fn from(verifying_key: &VerifyingKey<C>) -> EncodedPoint<C> {
verifying_key.inner.into()
}
}
impl<C> Eq for VerifyingKey<C> where C: PrimeCurve + CurveArithmetic {}
impl<C> PartialEq for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
{
fn eq(&self, other: &Self) -> bool {
self.inner.eq(&other.inner)
}
}
impl<C> From<PublicKey<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
{
fn from(public_key: PublicKey<C>) -> VerifyingKey<C> {
VerifyingKey { inner: public_key }
}
}
impl<C> From<&PublicKey<C>> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
{
fn from(public_key: &PublicKey<C>) -> VerifyingKey<C> {
(*public_key).into()
}
}
impl<C> From<VerifyingKey<C>> for PublicKey<C>
where
C: PrimeCurve + CurveArithmetic,
{
fn from(verifying_key: VerifyingKey<C>) -> PublicKey<C> {
verifying_key.inner
}
}
impl<C> From<&VerifyingKey<C>> for PublicKey<C>
where
C: PrimeCurve + CurveArithmetic,
{
fn from(verifying_key: &VerifyingKey<C>) -> PublicKey<C> {
(*verifying_key).into()
}
}
impl<C> PartialOrd for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<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 + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
{
fn cmp(&self, other: &Self) -> Ordering {
self.inner.cmp(&other.inner)
}
}
impl<C> TryFrom<&[u8]> for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
{
type Error = Error;
fn try_from(bytes: &[u8]) -> Result<Self> {
Self::from_sec1_bytes(bytes)
}
}
#[cfg(feature = "pkcs8")]
impl<C> AssociatedAlgorithmIdentifier for VerifyingKey<C>
where
C: AssociatedOid + CurveArithmetic + PrimeCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
{
type Params = ObjectIdentifier;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<ObjectIdentifier> =
PublicKey::<C>::ALGORITHM_IDENTIFIER;
}
#[cfg(feature = "pkcs8")]
impl<C> SignatureAlgorithmIdentifier for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
Signature<C>: AssociatedAlgorithmIdentifier<Params = AnyRef<'static>>,
{
type Params = AnyRef<'static>;
const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params> =
Signature::<C>::ALGORITHM_IDENTIFIER;
}
#[cfg(feature = "pkcs8")]
impl<C> TryFrom<pkcs8::SubjectPublicKeyInfoRef<'_>> for VerifyingKey<C>
where
C: PrimeCurve + AssociatedOid + CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
{
type Error = pkcs8::spki::Error;
fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> pkcs8::spki::Result<Self> {
PublicKey::try_from(spki).map(|inner| Self { inner })
}
}
#[cfg(feature = "pem")]
impl<C> EncodePublicKey for VerifyingKey<C>
where
C: PrimeCurve + AssociatedOid + CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: sec1::ModulusSize,
{
fn to_public_key_der(&self) -> pkcs8::spki::Result<pkcs8::Document> {
self.inner.to_public_key_der()
}
}
#[cfg(feature = "pem")]
impl<C> FromStr for VerifyingKey<C>
where
C: PrimeCurve + AssociatedOid + CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<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"))]
impl<C> Serialize for VerifyingKey<C>
where
C: PrimeCurve + AssociatedOid + CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<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"))]
impl<'de, C> Deserialize<'de> for VerifyingKey<C>
where
C: PrimeCurve + AssociatedOid + CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<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)
}
}

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1 @@
{"name":"ecdsa","vers":"0.16.9","deps":[{"name":"der","req":"^0.7","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"digest","req":"^0.10.7","features":["oid"],"optional":true,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"elliptic-curve","req":"^0.13.6","features":["digest","sec1"],"optional":false,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"rfc6979","req":"^0.4","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"serdect","req":"^0.2","features":["alloc"],"optional":true,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"sha2","req":"^0.10","features":["oid"],"optional":true,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"signature","req":"^2.0, <2.3","features":["rand_core"],"optional":false,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"spki","req":"^0.7.2","features":[],"optional":true,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"elliptic-curve","req":"^0.13","features":["dev"],"optional":false,"default_features":false,"target":null,"kind":"dev","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"hex-literal","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"sha2","req":"^0.10","features":[],"optional":false,"default_features":false,"target":null,"kind":"dev","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false}],"features":{"alloc":["elliptic-curve/alloc","signature/alloc","spki/alloc"],"arithmetic":["elliptic-curve/arithmetic"],"default":["digest"],"dev":["arithmetic","digest","elliptic-curve/dev","hazmat"],"digest":["dep:digest","signature/digest"],"hazmat":[],"pem":["elliptic-curve/pem","pkcs8"],"pkcs8":["digest","elliptic-curve/pkcs8","der"],"serde":["elliptic-curve/serde","serdect"],"signing":["arithmetic","digest","hazmat","rfc6979"],"std":["alloc","elliptic-curve/std","signature/std"],"verifying":["arithmetic","digest","hazmat"]},"features2":null,"cksum":"0a2bfbe6ad30e131c9518682341a20bcf56d5559fe0e9add540e665b3f05fccc","yanked":null,"links":null,"rust_version":null,"v":2}

14
vendor/ecdsa/tests/lib.rs vendored Normal file
View File

@@ -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());
}