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/pkcs8/.cargo-checksum.json vendored Normal file
View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"917f92ae7b3b2533195821499fa2579f9214a9ff387c37174cb044aa68c509d4","CHANGELOG.md":"a01855ad0a36a81e3e82f56d3d68a844489c3b17a5cb902e235924be158aee58","Cargo.toml":"440cf271c696da0bcef123a4e005f9f47273d140b9b824f4b7b0d4fa4639cb12","Cargo.toml.orig":"223ec95e6e36ffd893d16ec33efebac26220f312e19ebcfa16e4cb3c2dbee266","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"ad64fcb9589f162720f3cc5010ad76ca6ad3764e11861f9192c489df176bb71d","README.md":"49fdb13fec069473cf11a797d4fe3dc2c3cb2c496652937ae7dab4a7b87cddfc","src/encrypted_private_key_info.rs":"33746a87bce68a79a8ae53951cd020b2145383afce6c5ca4e5bbc5eb642a642e","src/error.rs":"94b661093a3c5beac61ffaabcae36e4d156309eeb78f36154a7422ccda7d2422","src/lib.rs":"b5c2fedbf3cfa31cc56b9cc16c94a5083ee83d7facfa1a34837b5262f60f622a","src/private_key_info.rs":"bd3b7aaa41ddab5fd731e1d0d1d7bf25c81fe6291a9edf51cd792136c4a50556","src/traits.rs":"fe016f54123d8bdcfd728ccba902033eccd546457cdba0d4d51f17c589df108a","src/version.rs":"a1c31cf4c2dc9677637d2616f34300d0117be70b72258a78f47841e457ec983f","tests/encrypted_private_key.rs":"f9e173d9bc76c21db92d05f36852be14e321877896dc46237ce6e6af7026002c","tests/examples/ed25519-encpriv-aes128-pbkdf2-sha1.der":"b41702662d6a645cc81af5be79455509e02efbf6eb5166e91346c19334485e9a","tests/examples/ed25519-encpriv-aes256-pbkdf2-sha256.der":"72ea607c5f0e560f68ee914dca8a5a74bfa22a667333656864f7938960acd302","tests/examples/ed25519-encpriv-aes256-pbkdf2-sha256.pem":"0c8bd6713af3f28392f684c5ba8b1bd842d8b483d00c136cb1fb24976aab447a","tests/examples/ed25519-encpriv-aes256-scrypt.der":"81f29098750ab282fd071692173d4da09b2c81371e7a02da7a8a14d6bed7c8a0","tests/examples/ed25519-encpriv-aes256-scrypt.pem":"e643345b62b43ea255fccbad6efd21453c62a7bbbb4d94dfae151fe04562313d","tests/examples/ed25519-encpriv-des-pbkdf2-sha256.der":"2a2412eac2aebec977563ee503358513c179f0216d93701ecd901f0062df79dd","tests/examples/ed25519-encpriv-des3-pbkdf2-sha256.der":"e064ed2a875be1388a05be89948236c2765d85943ccf093ee3df6e9a16baa619","tests/examples/ed25519-priv-pkcs8v1.der":"c1c3b09c4d18e096209edf25bc8dfc2f11dc29896085e49e5f4e487fbd97dbb6","tests/examples/ed25519-priv-pkcs8v1.pem":"8e39c38052cd63ab3870831a9f6cab76645426ca21ef77e24e2ead445aa4df16","tests/examples/ed25519-priv-pkcs8v2.der":"78f1cd2051065b209431249093f218b0e01a5fd0b9e756db820d4893d9dbbf55","tests/examples/ed25519-priv-pkcs8v2.pem":"a7cc1efd420b972a1b0776cc8b703624c62617eb2be3705876cc145227bd8427","tests/examples/ed25519-pub.der":"55dd4c74b0e48534e2f4e173ceceb50df8f27a7ac2aa8991cc7ae914e030bced","tests/examples/ed25519-pub.pem":"36d717203cbca1812f05f30e0415251c928b659882092e653221a028571c6853","tests/examples/p256-priv.der":"8125ab208d2181ed3ef05ff0ab1906e5898c36a858277e5b987e78e505288769","tests/examples/p256-priv.pem":"f4171f5ea72bf95ee444ceb868872f5c5d2bbc5fca038ae801b06fb9ac6b9429","tests/examples/p256-pub.der":"b9968d56ed8d6aa3fb43b15fa01e355d7a3a0203b1408b3fd2733637c4d1642c","tests/examples/p256-pub.pem":"d1ff198dc495da63f5f909db0254d6e49cff519487fcb26d055a762fc3ca47a1","tests/examples/rsa2048-priv.der":"ea7fe20f854f4fb908c12f1344e6cffbb83f367bbd8bfebca20687402394266f","tests/examples/rsa2048-priv.pem":"4df5e3254935a4f7d71e3b693d1b874091717f8b6075cd33f80ce4338d2ab0f2","tests/examples/rsa2048-pub.der":"efeda9bfead9fd0594f6a5cf6fdf6c163116a3b1fad6d73cea05295b68fd1794","tests/examples/rsa2048-pub.pem":"078c3983093e86784590a2a454547acad1d50992419334be697e442e954f02f8","tests/examples/x25519-priv.der":"bc4561e57bcb0e5b8be9bbdf4fb51e5e34dc46047ce50239c35fe7f119f52f91","tests/examples/x25519-priv.pem":"c618022ab6a2e345b475830c1e0a9332458791df939d116b6e6d4da9c918771b","tests/private_key.rs":"ff7dd659b3bc3a5bfc8789164160a4759838ad58e1233cece020340f6bb45271","tests/traits.rs":"fcd1f1198ce579736862eed872ca55f081533146001fc9ec03ac35728fbd89a8"},"package":"f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"}

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

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "7736dd21389b8820dfeb396e8c4c932de93d3ddf"
},
"path_in_vcs": "pkcs8"
}

234
vendor/pkcs8/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,234 @@
# 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.10.2 (2023-04-04)
### Changed
- Bump `spki` to v0.7.1 ([#981])
[#981]: https://github.com/RustCrypto/formats/pull/981
## 0.10.1 (2023-03-05)
### Added
- `sha1-insecure` feature ([#913])
[#913]: https://github.com/RustCrypto/formats/pull/913
## 0.10.0 (2023-02-26) [YANKED]
### Changed
- Use blanket impls for `Decode*` traits ([#785])
- Bump `der` dependency to v0.7 ([#899])
- Bump `spki` dependency to v0.7 ([#900])
- Bump `pkcs5` dependency to v0.7 ([#901])
[#785]: https://github.com/RustCrypto/formats/pull/785
[#899]: https://github.com/RustCrypto/formats/pull/899
[#900]: https://github.com/RustCrypto/formats/pull/900
[#901]: https://github.com/RustCrypto/formats/pull/901
## 0.9.0 (2022-05-08)
### Added
- Error conversion support to `pkcs8::spki::Error` ([#335])
- Re-export `AssociatedOid` ([#645])
### Changed
- Use `finish_non_exhaustive` in `Debug` impls ([#245])
- Replace `PrivateKeyDocument` with `der::SecretDocument` ([#571])
- Bump `der` to v0.6 ([#653])
- Bump `spki` to v0.6 ([#654])
- Bump `pkcs5` to v0.5 ([#655])
### Removed
- `PrivateKeyDocument` ([#571])
[#245]: https://github.com/RustCrypto/formats/pull/245
[#335]: https://github.com/RustCrypto/formats/pull/335
[#571]: https://github.com/RustCrypto/formats/pull/571
[#645]: https://github.com/RustCrypto/formats/pull/645
[#653]: https://github.com/RustCrypto/formats/pull/653
[#654]: https://github.com/RustCrypto/formats/pull/654
[#655]: https://github.com/RustCrypto/formats/pull/655
## 0.8.0 (2021-11-16)
### Added
- Re-export `spki` crate ([#210])
### Changed
- Replace usages of `expect` with fallible methods ([#108])
- Impl `From*Key`/`To*Key` traits on `Document` types ([#110])
- Rename `From/ToPrivateKey` => `DecodePrivateKey`/`EncodePrivateKey` ([#121])
- Rust 2021 edition upgrade; MSRV 1.56 ([#136])
- Use `der::Document` to impl `*PrivateKeyDocument` ([#140])
- Rename `Error::Crypto` => `Error::EncryptedPrivateKey` ([#213], [#214])
- Bump `der` dependency to v0.5 ([#222])
- Bump `spki` dependency to v0.5 ([#223])
- Bump `pkcs5` dependency to v0.4 ([#224])
- Replace `from_pkcs8_private_key_info` with `TryFrom` ([#230])
### Removed
- `*_with_le` PEM encoding methods ([#109])
- PKCS#1 support; moved to `pkcs1` crate ([#124])
- I/O related errors from key format crates ([#158])
- `der::pem` export ([#211])
[#108]: https://github.com/RustCrypto/formats/pull/108
[#109]: https://github.com/RustCrypto/formats/pull/109
[#110]: https://github.com/RustCrypto/formats/pull/110
[#121]: https://github.com/RustCrypto/formats/pull/121
[#124]: https://github.com/RustCrypto/formats/pull/124
[#136]: https://github.com/RustCrypto/formats/pull/136
[#140]: https://github.com/RustCrypto/formats/pull/140
[#158]: https://github.com/RustCrypto/formats/pull/158
[#210]: https://github.com/RustCrypto/formats/pull/210
[#211]: https://github.com/RustCrypto/formats/pull/211
[#213]: https://github.com/RustCrypto/formats/pull/213
[#214]: https://github.com/RustCrypto/formats/pull/214
[#222]: https://github.com/RustCrypto/formats/pull/222
[#223]: https://github.com/RustCrypto/formats/pull/223
[#224]: https://github.com/RustCrypto/formats/pull/224
[#230]: https://github.com/RustCrypto/formats/pull/230
## 0.7.6 (2021-09-14)
### Added
- `3des` and `des-insecure` features
- `sha1` feature
- Support for AES-192-CBC
### Changed
- Moved to `formats` repo ([#2])
[#2]: https://github.com/RustCrypto/formats/pull/2
## 0.7.5 (2021-07-26)
### Added
- Support for customizing PEM `LineEnding`
### Changed
- Bump `pem-rfc7468` dependency to v0.2
## 0.7.4 (2021-07-25)
### Added
- PKCS#1 support
## 0.7.3 (2021-07-24)
### Changed
- Use `pem-rfc7468` crate
## 0.7.2 (2021-07-20)
### Added
- `Error::ParametersMalformed` variant
## 0.7.1 (2021-07-20)
### Added
- `Error::KeyMalformed` variant
## 0.7.0 (2021-06-07)
### Added
- ASN.1 error improvements
### Changed
- Merge `OneAsymmetricKey` into `PrivateKeyInfo`
- Use scrypt as the default PBES2 KDF
- Return `Result`(s) when encoding
- Bump `der` to v0.4
- Bump `spki` to v0.4
- Bump `pkcs5` to v0.3
## 0.6.1 (2021-05-24)
### Added
- Support for RFC5958's `OneAsymmetricKey`
### Changed
- Bump `der` to v0.3.5
## 0.6.0 (2021-03-22)
### Changed
- Bump `der` dependency to v0.3
- Bump `spki` dependency to v0.3
- Bump `pkcs5` dependency to v0.2
## 0.5.5 (2021-03-17)
### Changed
- Bump `base64ct` dependency to v1.0
## 0.5.4 (2021-02-24)
### Added
- Encryption helper methods for `FromPrivateKey`/`ToPrivateKey`
## 0.5.3 (2021-02-23)
### Added
- Support for decrypting/encrypting `EncryptedPrivateKeyInfo`
- PEM support for `EncryptedPrivateKeyInfo`
- `Error::Crypto` variant
## 0.5.2 (2021-02-20)
### Changed
- Use `pkcs5` crate
## 0.5.1 (2021-02-18) [YANKED]
### Added
- `pkcs5` feature
### Changed
- Bump `spki` dependency to v0.2.0
## 0.5.0 (2021-02-16) [YANKED]
### Added
- Initial `EncryptedPrivateKeyInfo` support
### Changed
- Extract SPKI-related types into the `spki` crate
## 0.4.1 (2021-02-01)
### Changed
- Bump `basec4ct` dependency to v0.2
## 0.4.0 (2021-01-26)
### Changed
- Bump `der` crate dependency to v0.2
- Use `base64ct` v0.1 for PEM encoding
## 0.3.3 (2020-12-21)
### Changed
- Use `der` crate for decoding/encoding ASN.1 DER
## 0.3.2 (2020-12-16)
### Added
- `AlgorithmIdentifier::parameters_oid` method
## 0.3.1 (2020-12-16)
### Changed
- Bump `const-oid` dependency to v0.4
## 0.3.0 (2020-12-16) [YANKED]
### Added
- `AlgorithmParameters` enum
## 0.2.2 (2020-12-14)
### Fixed
- Decoding/encoding support for Ed25519 keys
## 0.2.1 (2020-12-14)
### Added
- rustdoc improvements
## 0.2.0 (2020-12-14)
### Added
- File writing methods for public/private keys
- Methods for loading `*Document` types from files
- DER encoding support
- PEM encoding support
- `ToPrivateKey`/`ToPublicKey` traits
### Changed
- `Error` enum
- Rename `load_*_file` methods to `read_*_file`
## 0.1.1 (2020-12-06)
### Added
- Helper methods to load keys from the local filesystem
## 0.1.0 (2020-12-05)
- Initial release

108
vendor/pkcs8/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,108 @@
# 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 = "pkcs8"
version = "0.10.2"
authors = ["RustCrypto Developers"]
description = """
Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #8:
Private-Key Information Syntax Specification (RFC 5208), with additional
support for PKCS#8v2 asymmetric key packages (RFC 5958)
"""
readme = "README.md"
keywords = [
"crypto",
"key",
"pkcs",
"private",
]
categories = [
"cryptography",
"data-structures",
"encoding",
"no-std",
"parser-implementations",
]
license = "Apache-2.0 OR MIT"
repository = "https://github.com/RustCrypto/formats/tree/master/pkcs8"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = [
"--cfg",
"docsrs",
]
[dependencies.der]
version = "0.7"
features = ["oid"]
[dependencies.pkcs5]
version = "0.7"
optional = true
[dependencies.rand_core]
version = "0.6"
optional = true
default-features = false
[dependencies.spki]
version = "0.7.1"
[dependencies.subtle]
version = "2"
optional = true
default-features = false
[dev-dependencies.hex-literal]
version = "0.3"
[dev-dependencies.tempfile]
version = "3"
[features]
3des = [
"encryption",
"pkcs5/3des",
]
alloc = [
"der/alloc",
"der/zeroize",
"spki/alloc",
]
des-insecure = [
"encryption",
"pkcs5/des-insecure",
]
encryption = [
"alloc",
"pkcs5/alloc",
"pkcs5/pbes2",
"rand_core",
]
getrandom = ["rand_core/getrandom"]
pem = [
"alloc",
"der/pem",
"spki/pem",
]
sha1-insecure = [
"encryption",
"pkcs5/sha1-insecure",
]
std = [
"alloc",
"der/std",
"spki/std",
]

201
vendor/pkcs8/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 [yyyy] [name of copyright owner]
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/pkcs8/LICENSE-MIT vendored Normal file
View File

@@ -0,0 +1,25 @@
Copyright (c) 2020-2023 The RustCrypto Project 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.

94
vendor/pkcs8/README.md vendored Normal file
View File

@@ -0,0 +1,94 @@
# [RustCrypto]: PKCS#8 (Private Keys)
[![crate][crate-image]][crate-link]
[![Docs][docs-image]][docs-link]
[![Build Status][build-image]][build-link]
![Apache2/MIT licensed][license-image]
![Rust Version][rustc-image]
[![Project Chat][chat-image]][chat-link]
Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #8:
Private-Key Information Syntax Specification ([RFC 5208]).
[Documentation][docs-link]
## About PKCS#8
PKCS#8 is a format for cryptographic private keys, often containing pairs
of private and public keys.
You can identify a PKCS#8 private key encoded as PEM (i.e. text) by the
following:
```text
-----BEGIN PRIVATE KEY-----
```
PKCS#8 private keys can optionally be encrypted under a password using
key derivation algorithms like PBKDF2 and [scrypt], and encrypted with
ciphers like AES-CBC. When a PKCS#8 private key has been encrypted,
it starts with the following:
```text
-----BEGIN ENCRYPTED PRIVATE KEY-----
```
PKCS#8 private keys can also be serialized in an ASN.1-based binary format.
The PEM text encoding is a Base64 representation of this format.
## Supported Algorithms
This crate is implemented in an algorithm-agnostic manner with the goal of
enabling PKCS#8 support for any algorithm.
That said, it has been tested for interoperability against keys generated by
OpenSSL for the following algorithms:
- ECC (`id-ecPublicKey`)
- Ed25519 (`id-Ed25519`)
- RSA (`id-rsaEncryption`)
- X25519 (`id-X25519`)
Please open an issue if you encounter trouble using it with a particular
algorithm, including the ones listed above or other algorithms.
## 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
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/pkcs8
[crate-link]: https://crates.io/crates/pkcs8
[docs-image]: https://docs.rs/pkcs8/badge.svg
[docs-link]: https://docs.rs/pkcs8/
[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/300570-formats
[build-image]: https://github.com/RustCrypto/formats/workflows/pkcs8/badge.svg?branch=master&event=push
[build-link]: https://github.com/RustCrypto/formats/actions
[//]: # (links)
[RustCrypto]: https://github.com/rustcrypto
[RFC 5208]: https://tools.ietf.org/html/rfc5208
[scrypt]: https://en.wikipedia.org/wiki/Scrypt

View File

@@ -0,0 +1,165 @@
//! PKCS#8 `EncryptedPrivateKeyInfo`
use crate::{Error, Result};
use core::fmt;
use der::{
asn1::OctetStringRef, Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader,
Sequence, Writer,
};
use pkcs5::EncryptionScheme;
#[cfg(feature = "alloc")]
use der::SecretDocument;
#[cfg(feature = "encryption")]
use {
pkcs5::pbes2,
rand_core::{CryptoRng, RngCore},
};
#[cfg(feature = "pem")]
use der::pem::PemLabel;
/// PKCS#8 `EncryptedPrivateKeyInfo`.
///
/// ASN.1 structure containing a PKCS#5 [`EncryptionScheme`] identifier for a
/// password-based symmetric encryption scheme and encrypted private key data.
///
/// ## Schema
/// Structure described in [RFC 5208 Section 6]:
///
/// ```text
/// EncryptedPrivateKeyInfo ::= SEQUENCE {
/// encryptionAlgorithm EncryptionAlgorithmIdentifier,
/// encryptedData EncryptedData }
///
/// EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
///
/// EncryptedData ::= OCTET STRING
/// ```
///
/// [RFC 5208 Section 6]: https://tools.ietf.org/html/rfc5208#section-6
#[derive(Clone, Eq, PartialEq)]
pub struct EncryptedPrivateKeyInfo<'a> {
/// Algorithm identifier describing a password-based symmetric encryption
/// scheme used to encrypt the `encrypted_data` field.
pub encryption_algorithm: EncryptionScheme<'a>,
/// Private key data
pub encrypted_data: &'a [u8],
}
impl<'a> EncryptedPrivateKeyInfo<'a> {
/// Attempt to decrypt this encrypted private key using the provided
/// password to derive an encryption key.
#[cfg(feature = "encryption")]
pub fn decrypt(&self, password: impl AsRef<[u8]>) -> Result<SecretDocument> {
Ok(self
.encryption_algorithm
.decrypt(password, self.encrypted_data)?
.try_into()?)
}
/// Encrypt the given ASN.1 DER document using a symmetric encryption key
/// derived from the provided password.
#[cfg(feature = "encryption")]
pub(crate) fn encrypt(
mut rng: impl CryptoRng + RngCore,
password: impl AsRef<[u8]>,
doc: &[u8],
) -> Result<SecretDocument> {
let mut salt = [0u8; 16];
rng.fill_bytes(&mut salt);
let mut iv = [0u8; 16];
rng.fill_bytes(&mut iv);
let pbes2_params = pbes2::Parameters::scrypt_aes256cbc(Default::default(), &salt, &iv)?;
EncryptedPrivateKeyInfo::encrypt_with(pbes2_params, password, doc)
}
/// Encrypt this private key using a symmetric encryption key derived
/// from the provided password and [`pbes2::Parameters`].
#[cfg(feature = "encryption")]
pub(crate) fn encrypt_with(
pbes2_params: pbes2::Parameters<'a>,
password: impl AsRef<[u8]>,
doc: &[u8],
) -> Result<SecretDocument> {
let encrypted_data = pbes2_params.encrypt(password, doc)?;
EncryptedPrivateKeyInfo {
encryption_algorithm: pbes2_params.into(),
encrypted_data: &encrypted_data,
}
.try_into()
}
}
impl<'a> DecodeValue<'a> for EncryptedPrivateKeyInfo<'a> {
fn decode_value<R: Reader<'a>>(
reader: &mut R,
header: Header,
) -> der::Result<EncryptedPrivateKeyInfo<'a>> {
reader.read_nested(header.length, |reader| {
Ok(Self {
encryption_algorithm: reader.decode()?,
encrypted_data: OctetStringRef::decode(reader)?.as_bytes(),
})
})
}
}
impl EncodeValue for EncryptedPrivateKeyInfo<'_> {
fn value_len(&self) -> der::Result<Length> {
self.encryption_algorithm.encoded_len()?
+ OctetStringRef::new(self.encrypted_data)?.encoded_len()?
}
fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
self.encryption_algorithm.encode(writer)?;
OctetStringRef::new(self.encrypted_data)?.encode(writer)?;
Ok(())
}
}
impl<'a> Sequence<'a> for EncryptedPrivateKeyInfo<'a> {}
impl<'a> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo<'a> {
type Error = Error;
fn try_from(bytes: &'a [u8]) -> Result<Self> {
Ok(Self::from_der(bytes)?)
}
}
impl<'a> fmt::Debug for EncryptedPrivateKeyInfo<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EncryptedPrivateKeyInfo")
.field("encryption_algorithm", &self.encryption_algorithm)
.finish_non_exhaustive()
}
}
#[cfg(feature = "alloc")]
impl TryFrom<EncryptedPrivateKeyInfo<'_>> for SecretDocument {
type Error = Error;
fn try_from(encrypted_private_key: EncryptedPrivateKeyInfo<'_>) -> Result<SecretDocument> {
SecretDocument::try_from(&encrypted_private_key)
}
}
#[cfg(feature = "alloc")]
impl TryFrom<&EncryptedPrivateKeyInfo<'_>> for SecretDocument {
type Error = Error;
fn try_from(encrypted_private_key: &EncryptedPrivateKeyInfo<'_>) -> Result<SecretDocument> {
Ok(Self::encode_msg(encrypted_private_key)?)
}
}
#[cfg(feature = "pem")]
impl PemLabel for EncryptedPrivateKeyInfo<'_> {
const PEM_LABEL: &'static str = "ENCRYPTED PRIVATE KEY";
}

93
vendor/pkcs8/src/error.rs vendored Normal file
View File

@@ -0,0 +1,93 @@
//! Error types
use core::fmt;
#[cfg(feature = "pem")]
use der::pem;
/// Result type
pub type Result<T> = core::result::Result<T, Error>;
/// Error type
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Error {
/// ASN.1 DER-related errors.
Asn1(der::Error),
/// Errors relating to PKCS#5-encrypted keys.
#[cfg(feature = "pkcs5")]
EncryptedPrivateKey(pkcs5::Error),
/// Malformed cryptographic key contained in a PKCS#8 document.
///
/// This is intended for relaying errors related to the raw data contained
/// within [`PrivateKeyInfo::private_key`][`crate::PrivateKeyInfo::private_key`]
/// or [`SubjectPublicKeyInfo::subject_public_key`][`crate::SubjectPublicKeyInfo::subject_public_key`].
KeyMalformed,
/// [`AlgorithmIdentifier::parameters`][`crate::AlgorithmIdentifierRef::parameters`]
/// is malformed or otherwise encoded in an unexpected manner.
ParametersMalformed,
/// Public key errors propagated from the [`spki::Error`] type.
PublicKey(spki::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Asn1(err) => write!(f, "PKCS#8 ASN.1 error: {}", err),
#[cfg(feature = "pkcs5")]
Error::EncryptedPrivateKey(err) => write!(f, "{}", err),
Error::KeyMalformed => f.write_str("PKCS#8 cryptographic key data malformed"),
Error::ParametersMalformed => f.write_str("PKCS#8 algorithm parameters malformed"),
Error::PublicKey(err) => write!(f, "public key error: {}", err),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
impl From<der::Error> for Error {
fn from(err: der::Error) -> Error {
Error::Asn1(err)
}
}
impl From<der::ErrorKind> for Error {
fn from(err: der::ErrorKind) -> Error {
Error::Asn1(err.into())
}
}
#[cfg(feature = "pem")]
impl From<pem::Error> for Error {
fn from(err: pem::Error) -> Error {
der::Error::from(err).into()
}
}
#[cfg(feature = "pkcs5")]
impl From<pkcs5::Error> for Error {
fn from(err: pkcs5::Error) -> Error {
Error::EncryptedPrivateKey(err)
}
}
impl From<spki::Error> for Error {
fn from(err: spki::Error) -> Error {
Error::PublicKey(err)
}
}
impl From<Error> for spki::Error {
fn from(err: Error) -> spki::Error {
match err {
Error::Asn1(e) => spki::Error::Asn1(e),
Error::PublicKey(e) => e,
_ => spki::Error::KeyMalformed,
}
}
}

111
vendor/pkcs8/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,111 @@
#![no_std]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
)]
#![forbid(unsafe_code)]
#![warn(
clippy::mod_module_files,
clippy::unwrap_used,
missing_docs,
rust_2018_idioms,
unused_lifetimes,
unused_qualifications
)]
//! ## About this crate
//! This library provides generalized PKCS#8 support designed to work with a
//! number of different algorithms. It supports `no_std` platforms including
//! ones without a heap (albeit with reduced functionality).
//!
//! It supports decoding/encoding the following types:
//!
//! - [`EncryptedPrivateKeyInfo`]: (with `pkcs5` feature) encrypted key.
//! - [`PrivateKeyInfo`]: algorithm identifier and data representing a private key.
//! Optionally also includes public key data for asymmetric keys.
//! - [`SubjectPublicKeyInfo`]: algorithm identifier and data representing a public key
//! (re-exported from the [`spki`] crate)
//!
//! When the `pem` feature is enabled, it also supports decoding/encoding
//! documents from "PEM encoding" format as defined in RFC 7468.
//!
//! ## Encrypted Private Key Support
//! [`EncryptedPrivateKeyInfo`] supports decoding/encoding encrypted PKCS#8
//! private keys and is gated under the `pkcs5` feature.
//!
//! When the `encryption` feature of this crate is enabled, it provides
//! [`EncryptedPrivateKeyInfo::decrypt`] and [`PrivateKeyInfo::encrypt`]
//! functions which are able to decrypt/encrypt keys using the following
//! algorithms:
//!
//! - [PKCS#5v2 Password Based Encryption Scheme 2 (RFC 8018)]
//! - Key derivation functions:
//! - [scrypt] ([RFC 7914])
//! - PBKDF2 ([RFC 8018](https://datatracker.ietf.org/doc/html/rfc8018#section-5.2))
//! - SHA-2 based PRF with HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512
//! - SHA-1 based PRF with HMAC-SHA1, when the `sha1` feature of this crate is enabled.
//! - Symmetric encryption: AES-128-CBC, AES-192-CBC, or AES-256-CBC
//! (best available options for PKCS#5v2)
//!
//! ## Legacy DES-CBC and DES-EDE3-CBC (3DES) support (optional)
//! When the `des-insecure` and/or `3des` features are enabled this crate provides support for
//! private keys encrypted with with DES-CBC and DES-EDE3-CBC (3DES or Triple DES) symmetric
//! encryption, respectively.
//!
//! ⚠️ WARNING ⚠️
//!
//! DES support (gated behind the `des-insecure` feature) is implemented to
//! allow for decryption of legacy PKCS#8 files only.
//!
//! Such PKCS#8 documents should be considered *INSECURE* due to the short
//! 56-bit key size of DES.
//!
//! New keys should use AES instead.
//!
//! [RFC 5208]: https://tools.ietf.org/html/rfc5208
//! [RFC 5958]: https://tools.ietf.org/html/rfc5958
//! [RFC 7914]: https://datatracker.ietf.org/doc/html/rfc7914
//! [PKCS#5v2 Password Based Encryption Scheme 2 (RFC 8018)]: https://tools.ietf.org/html/rfc8018#section-6.2
//! [scrypt]: https://en.wikipedia.org/wiki/Scrypt
#[cfg(feature = "pem")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
mod error;
mod private_key_info;
mod traits;
mod version;
#[cfg(feature = "pkcs5")]
pub(crate) mod encrypted_private_key_info;
pub use crate::{
error::{Error, Result},
private_key_info::PrivateKeyInfo,
traits::DecodePrivateKey,
version::Version,
};
pub use der::{self, asn1::ObjectIdentifier, oid::AssociatedOid};
pub use spki::{
self, AlgorithmIdentifierRef, DecodePublicKey, SubjectPublicKeyInfo, SubjectPublicKeyInfoRef,
};
#[cfg(feature = "alloc")]
pub use {
crate::traits::EncodePrivateKey,
der::{Document, SecretDocument},
spki::EncodePublicKey,
};
#[cfg(feature = "pem")]
pub use der::pem::LineEnding;
#[cfg(feature = "pkcs5")]
pub use {encrypted_private_key_info::EncryptedPrivateKeyInfo, pkcs5};
#[cfg(feature = "rand_core")]
pub use rand_core;

295
vendor/pkcs8/src/private_key_info.rs vendored Normal file
View File

@@ -0,0 +1,295 @@
//! PKCS#8 `PrivateKeyInfo`.
use crate::{AlgorithmIdentifierRef, Error, Result, Version};
use core::fmt;
use der::{
asn1::{AnyRef, BitStringRef, ContextSpecific, OctetStringRef},
Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, TagMode, TagNumber,
Writer,
};
#[cfg(feature = "alloc")]
use der::SecretDocument;
#[cfg(feature = "encryption")]
use {
crate::EncryptedPrivateKeyInfo,
der::zeroize::Zeroizing,
pkcs5::pbes2,
rand_core::{CryptoRng, RngCore},
};
#[cfg(feature = "pem")]
use der::pem::PemLabel;
#[cfg(feature = "subtle")]
use subtle::{Choice, ConstantTimeEq};
/// Context-specific tag number for the public key.
const PUBLIC_KEY_TAG: TagNumber = TagNumber::N1;
/// PKCS#8 `PrivateKeyInfo`.
///
/// ASN.1 structure containing an `AlgorithmIdentifier`, private key
/// data in an algorithm specific format, and optional attributes
/// (ignored by this implementation).
///
/// Supports PKCS#8 v1 as described in [RFC 5208] and PKCS#8 v2 as described
/// in [RFC 5958]. PKCS#8 v2 keys include an additional public key field.
///
/// # PKCS#8 v1 `PrivateKeyInfo`
///
/// Described in [RFC 5208 Section 5]:
///
/// ```text
/// PrivateKeyInfo ::= SEQUENCE {
/// version Version,
/// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
/// privateKey PrivateKey,
/// attributes [0] IMPLICIT Attributes OPTIONAL }
///
/// Version ::= INTEGER
///
/// PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
///
/// PrivateKey ::= OCTET STRING
///
/// Attributes ::= SET OF Attribute
/// ```
///
/// # PKCS#8 v2 `OneAsymmetricKey`
///
/// PKCS#8 `OneAsymmetricKey` as described in [RFC 5958 Section 2]:
///
/// ```text
/// PrivateKeyInfo ::= OneAsymmetricKey
///
/// OneAsymmetricKey ::= SEQUENCE {
/// version Version,
/// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
/// privateKey PrivateKey,
/// attributes [0] Attributes OPTIONAL,
/// ...,
/// [[2: publicKey [1] PublicKey OPTIONAL ]],
/// ...
/// }
///
/// Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2)
///
/// PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
///
/// PrivateKey ::= OCTET STRING
///
/// Attributes ::= SET OF Attribute
///
/// PublicKey ::= BIT STRING
/// ```
///
/// [RFC 5208]: https://tools.ietf.org/html/rfc5208
/// [RFC 5958]: https://datatracker.ietf.org/doc/html/rfc5958
/// [RFC 5208 Section 5]: https://tools.ietf.org/html/rfc5208#section-5
/// [RFC 5958 Section 2]: https://datatracker.ietf.org/doc/html/rfc5958#section-2
#[derive(Clone)]
pub struct PrivateKeyInfo<'a> {
/// X.509 `AlgorithmIdentifier` for the private key type.
pub algorithm: AlgorithmIdentifierRef<'a>,
/// Private key data.
pub private_key: &'a [u8],
/// Public key data, optionally available if version is V2.
pub public_key: Option<&'a [u8]>,
}
impl<'a> PrivateKeyInfo<'a> {
/// Create a new PKCS#8 [`PrivateKeyInfo`] message.
///
/// This is a helper method which initializes `attributes` and `public_key`
/// to `None`, helpful if you aren't using those.
pub fn new(algorithm: AlgorithmIdentifierRef<'a>, private_key: &'a [u8]) -> Self {
Self {
algorithm,
private_key,
public_key: None,
}
}
/// Get the PKCS#8 [`Version`] for this structure.
///
/// [`Version::V1`] if `public_key` is `None`, [`Version::V2`] if `Some`.
pub fn version(&self) -> Version {
if self.public_key.is_some() {
Version::V2
} else {
Version::V1
}
}
/// Encrypt this private key using a symmetric encryption key derived
/// from the provided password.
///
/// Uses the following algorithms for encryption:
/// - PBKDF: scrypt with default parameters:
/// - log₂(N): 15
/// - r: 8
/// - p: 1
/// - Cipher: AES-256-CBC (best available option for PKCS#5 encryption)
#[cfg(feature = "encryption")]
pub fn encrypt(
&self,
rng: impl CryptoRng + RngCore,
password: impl AsRef<[u8]>,
) -> Result<SecretDocument> {
let der = Zeroizing::new(self.to_der()?);
EncryptedPrivateKeyInfo::encrypt(rng, password, der.as_ref())
}
/// Encrypt this private key using a symmetric encryption key derived
/// from the provided password and [`pbes2::Parameters`].
#[cfg(feature = "encryption")]
pub fn encrypt_with_params(
&self,
pbes2_params: pbes2::Parameters<'_>,
password: impl AsRef<[u8]>,
) -> Result<SecretDocument> {
let der = Zeroizing::new(self.to_der()?);
EncryptedPrivateKeyInfo::encrypt_with(pbes2_params, password, der.as_ref())
}
/// Get a `BIT STRING` representation of the public key, if present.
fn public_key_bit_string(&self) -> der::Result<Option<ContextSpecific<BitStringRef<'a>>>> {
self.public_key
.map(|pk| {
BitStringRef::from_bytes(pk).map(|value| ContextSpecific {
tag_number: PUBLIC_KEY_TAG,
tag_mode: TagMode::Implicit,
value,
})
})
.transpose()
}
}
impl<'a> DecodeValue<'a> for PrivateKeyInfo<'a> {
fn decode_value<R: Reader<'a>>(
reader: &mut R,
header: Header,
) -> der::Result<PrivateKeyInfo<'a>> {
reader.read_nested(header.length, |reader| {
// Parse and validate `version` INTEGER.
let version = Version::decode(reader)?;
let algorithm = reader.decode()?;
let private_key = OctetStringRef::decode(reader)?.into();
let public_key = reader
.context_specific::<BitStringRef<'_>>(PUBLIC_KEY_TAG, TagMode::Implicit)?
.map(|bs| {
bs.as_bytes()
.ok_or_else(|| der::Tag::BitString.value_error())
})
.transpose()?;
if version.has_public_key() != public_key.is_some() {
return Err(reader.error(
der::Tag::ContextSpecific {
constructed: true,
number: PUBLIC_KEY_TAG,
}
.value_error()
.kind(),
));
}
// Ignore any remaining extension fields
while !reader.is_finished() {
reader.decode::<ContextSpecific<AnyRef<'_>>>()?;
}
Ok(Self {
algorithm,
private_key,
public_key,
})
})
}
}
impl EncodeValue for PrivateKeyInfo<'_> {
fn value_len(&self) -> der::Result<Length> {
self.version().encoded_len()?
+ self.algorithm.encoded_len()?
+ OctetStringRef::new(self.private_key)?.encoded_len()?
+ self.public_key_bit_string()?.encoded_len()?
}
fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
self.version().encode(writer)?;
self.algorithm.encode(writer)?;
OctetStringRef::new(self.private_key)?.encode(writer)?;
self.public_key_bit_string()?.encode(writer)?;
Ok(())
}
}
impl<'a> Sequence<'a> for PrivateKeyInfo<'a> {}
impl<'a> TryFrom<&'a [u8]> for PrivateKeyInfo<'a> {
type Error = Error;
fn try_from(bytes: &'a [u8]) -> Result<Self> {
Ok(Self::from_der(bytes)?)
}
}
impl<'a> fmt::Debug for PrivateKeyInfo<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PrivateKeyInfo")
.field("version", &self.version())
.field("algorithm", &self.algorithm)
.field("public_key", &self.public_key)
.finish_non_exhaustive()
}
}
#[cfg(feature = "alloc")]
impl TryFrom<PrivateKeyInfo<'_>> for SecretDocument {
type Error = Error;
fn try_from(private_key: PrivateKeyInfo<'_>) -> Result<SecretDocument> {
SecretDocument::try_from(&private_key)
}
}
#[cfg(feature = "alloc")]
impl TryFrom<&PrivateKeyInfo<'_>> for SecretDocument {
type Error = Error;
fn try_from(private_key: &PrivateKeyInfo<'_>) -> Result<SecretDocument> {
Ok(Self::encode_msg(private_key)?)
}
}
#[cfg(feature = "pem")]
impl PemLabel for PrivateKeyInfo<'_> {
const PEM_LABEL: &'static str = "PRIVATE KEY";
}
#[cfg(feature = "subtle")]
impl<'a> ConstantTimeEq for PrivateKeyInfo<'a> {
fn ct_eq(&self, other: &Self) -> Choice {
// NOTE: public fields are not compared in constant time
let public_fields_eq =
self.algorithm == other.algorithm && self.public_key == other.public_key;
self.private_key.ct_eq(other.private_key) & Choice::from(public_fields_eq as u8)
}
}
#[cfg(feature = "subtle")]
impl<'a> Eq for PrivateKeyInfo<'a> {}
#[cfg(feature = "subtle")]
impl<'a> PartialEq for PrivateKeyInfo<'a> {
fn eq(&self, other: &Self) -> bool {
self.ct_eq(other).into()
}
}

140
vendor/pkcs8/src/traits.rs vendored Normal file
View File

@@ -0,0 +1,140 @@
//! Traits for parsing objects from PKCS#8 encoded documents
use crate::{Error, PrivateKeyInfo, Result};
#[cfg(feature = "alloc")]
use der::SecretDocument;
#[cfg(feature = "encryption")]
use {
crate::EncryptedPrivateKeyInfo,
rand_core::{CryptoRng, RngCore},
};
#[cfg(feature = "pem")]
use {crate::LineEnding, alloc::string::String, der::zeroize::Zeroizing};
#[cfg(feature = "pem")]
use der::pem::PemLabel;
#[cfg(feature = "std")]
use std::path::Path;
/// Parse a private key object from a PKCS#8 encoded document.
pub trait DecodePrivateKey: Sized {
/// Deserialize PKCS#8 private key from ASN.1 DER-encoded data
/// (binary format).
fn from_pkcs8_der(bytes: &[u8]) -> Result<Self>;
/// Deserialize encrypted PKCS#8 private key from ASN.1 DER-encoded data
/// (binary format) and attempt to decrypt it using the provided password.
#[cfg(feature = "encryption")]
fn from_pkcs8_encrypted_der(bytes: &[u8], password: impl AsRef<[u8]>) -> Result<Self> {
let doc = EncryptedPrivateKeyInfo::try_from(bytes)?.decrypt(password)?;
Self::from_pkcs8_der(doc.as_bytes())
}
/// Deserialize PKCS#8-encoded private key from PEM.
///
/// Keys in this format begin with the following delimiter:
///
/// ```text
/// -----BEGIN PRIVATE KEY-----
/// ```
#[cfg(feature = "pem")]
fn from_pkcs8_pem(s: &str) -> Result<Self> {
let (label, doc) = SecretDocument::from_pem(s)?;
PrivateKeyInfo::validate_pem_label(label)?;
Self::from_pkcs8_der(doc.as_bytes())
}
/// Deserialize encrypted PKCS#8-encoded private key from PEM and attempt
/// to decrypt it using the provided password.
///
/// Keys in this format begin with the following delimiter:
///
/// ```text
/// -----BEGIN ENCRYPTED PRIVATE KEY-----
/// ```
#[cfg(all(feature = "encryption", feature = "pem"))]
fn from_pkcs8_encrypted_pem(s: &str, password: impl AsRef<[u8]>) -> Result<Self> {
let (label, doc) = SecretDocument::from_pem(s)?;
EncryptedPrivateKeyInfo::validate_pem_label(label)?;
Self::from_pkcs8_encrypted_der(doc.as_bytes(), password)
}
/// Load PKCS#8 private key from an ASN.1 DER-encoded file on the local
/// filesystem (binary format).
#[cfg(feature = "std")]
fn read_pkcs8_der_file(path: impl AsRef<Path>) -> Result<Self> {
Self::from_pkcs8_der(SecretDocument::read_der_file(path)?.as_bytes())
}
/// Load PKCS#8 private key from a PEM-encoded file on the local filesystem.
#[cfg(all(feature = "pem", feature = "std"))]
fn read_pkcs8_pem_file(path: impl AsRef<Path>) -> Result<Self> {
let (label, doc) = SecretDocument::read_pem_file(path)?;
PrivateKeyInfo::validate_pem_label(&label)?;
Self::from_pkcs8_der(doc.as_bytes())
}
}
impl<T> DecodePrivateKey for T
where
T: for<'a> TryFrom<PrivateKeyInfo<'a>, Error = Error>,
{
fn from_pkcs8_der(bytes: &[u8]) -> Result<Self> {
Self::try_from(PrivateKeyInfo::try_from(bytes)?)
}
}
/// Serialize a private key object to a PKCS#8 encoded document.
#[cfg(feature = "alloc")]
pub trait EncodePrivateKey {
/// Serialize a [`SecretDocument`] containing a PKCS#8-encoded private key.
fn to_pkcs8_der(&self) -> Result<SecretDocument>;
/// Create an [`SecretDocument`] containing the ciphertext of
/// a PKCS#8 encoded private key encrypted under the given `password`.
#[cfg(feature = "encryption")]
fn to_pkcs8_encrypted_der(
&self,
rng: impl CryptoRng + RngCore,
password: impl AsRef<[u8]>,
) -> Result<SecretDocument> {
EncryptedPrivateKeyInfo::encrypt(rng, password, self.to_pkcs8_der()?.as_bytes())
}
/// Serialize this private key as PEM-encoded PKCS#8 with the given [`LineEnding`].
#[cfg(feature = "pem")]
fn to_pkcs8_pem(&self, line_ending: LineEnding) -> Result<Zeroizing<String>> {
let doc = self.to_pkcs8_der()?;
Ok(doc.to_pem(PrivateKeyInfo::PEM_LABEL, line_ending)?)
}
/// Serialize this private key as an encrypted PEM-encoded PKCS#8 private
/// key using the `provided` to derive an encryption key.
#[cfg(all(feature = "encryption", feature = "pem"))]
fn to_pkcs8_encrypted_pem(
&self,
rng: impl CryptoRng + RngCore,
password: impl AsRef<[u8]>,
line_ending: LineEnding,
) -> Result<Zeroizing<String>> {
let doc = self.to_pkcs8_encrypted_der(rng, password)?;
Ok(doc.to_pem(EncryptedPrivateKeyInfo::PEM_LABEL, line_ending)?)
}
/// Write ASN.1 DER-encoded PKCS#8 private key to the given path
#[cfg(feature = "std")]
fn write_pkcs8_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
Ok(self.to_pkcs8_der()?.write_der_file(path)?)
}
/// Write ASN.1 DER-encoded PKCS#8 private key to the given path
#[cfg(all(feature = "pem", feature = "std"))]
fn write_pkcs8_pem_file(&self, path: impl AsRef<Path>, line_ending: LineEnding) -> Result<()> {
let doc = self.to_pkcs8_der()?;
Ok(doc.write_pem_file(path, PrivateKeyInfo::PEM_LABEL, line_ending)?)
}
}

63
vendor/pkcs8/src/version.rs vendored Normal file
View File

@@ -0,0 +1,63 @@
//! PKCS#8 version identifier.
use crate::Error;
use der::{Decode, Encode, FixedTag, Reader, Tag, Writer};
/// Version identifier for PKCS#8 documents.
///
/// (RFC 5958 designates `0` and `1` as the only valid versions for PKCS#8 documents)
#[derive(Clone, Debug, Copy, PartialEq, Eq)]
pub enum Version {
/// Denotes PKCS#8 v1: no public key field.
V1 = 0,
/// Denotes PKCS#8 v2: `OneAsymmetricKey` with public key field.
V2 = 1,
}
impl Version {
/// Is this version expected to have a public key?
pub fn has_public_key(self) -> bool {
match self {
Version::V1 => false,
Version::V2 => true,
}
}
}
impl<'a> Decode<'a> for Version {
fn decode<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
Version::try_from(u8::decode(decoder)?).map_err(|_| Self::TAG.value_error())
}
}
impl Encode for Version {
fn encoded_len(&self) -> der::Result<der::Length> {
der::Length::from(1u8).for_tlv()
}
fn encode(&self, writer: &mut impl Writer) -> der::Result<()> {
u8::from(*self).encode(writer)
}
}
impl From<Version> for u8 {
fn from(version: Version) -> Self {
version as u8
}
}
impl TryFrom<u8> for Version {
type Error = Error;
fn try_from(byte: u8) -> Result<Version, Error> {
match byte {
0 => Ok(Version::V1),
1 => Ok(Version::V2),
_ => Err(Self::TAG.value_error().into()),
}
}
}
impl FixedTag for Version {
const TAG: Tag = Tag::Integer;
}

Binary file not shown.

View File

View File

@@ -0,0 +1 @@
{"name":"pkcs8","vers":"0.10.2","deps":[{"name":"der","req":"^0.7","features":["oid"],"optional":false,"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":"pkcs5","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":"rand_core","req":"^0.6","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":"spki","req":"^0.7.1","features":[],"optional":false,"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":"subtle","req":"^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":"hex-literal","req":"^0.3","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":"tempfile","req":"^3","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}],"features":{"3des":["encryption","pkcs5/3des"],"alloc":["der/alloc","der/zeroize","spki/alloc"],"des-insecure":["encryption","pkcs5/des-insecure"],"encryption":["alloc","pkcs5/alloc","pkcs5/pbes2","rand_core"],"getrandom":["rand_core/getrandom"],"pem":["alloc","der/pem","spki/pem"],"sha1-insecure":["encryption","pkcs5/sha1-insecure"],"std":["alloc","der/std","spki/std"]},"features2":null,"cksum":"22f240dfe37485fc43a68babc9be9e13cf6c7d41ad4a0fa1701f3b7aa92b5ed8","yanked":null,"links":null,"rust_version":null,"v":2}

Binary file not shown.

View File

@@ -0,0 +1,234 @@
//! Encrypted PKCS#8 private key tests.
#![cfg(feature = "pkcs5")]
use hex_literal::hex;
use pkcs8::{pkcs5::pbes2, EncryptedPrivateKeyInfo, PrivateKeyInfo};
#[cfg(feature = "alloc")]
use der::Encode;
#[cfg(feature = "pem")]
use der::EncodePem;
/// Ed25519 PKCS#8 private key plaintext encoded as ASN.1 DER
#[cfg(feature = "encryption")]
const ED25519_DER_PLAINTEXT_EXAMPLE: &[u8] = include_bytes!("examples/ed25519-priv-pkcs8v1.der");
/// Ed25519 PKCS#8 encrypted private key (PBES2 + AES-128-CBC + PBKDF2-SHA1) encoded as ASN.1 DER.
///
/// Generated using:
///
/// ```
/// $ openssl pkcs8 -v2 aes256-cbc -v2prf hmacWithSHA1 -topk8 -inform der -in ed25519-priv.der -outform der -out ed25519-encpriv-aes128-pbkdf2-sha1.der
/// ```
const ED25519_DER_AES128_PBKDF2_SHA1_EXAMPLE: &[u8] =
include_bytes!("examples/ed25519-encpriv-aes128-pbkdf2-sha1.der");
/// Ed25519 PKCS#8 encrypted private key (PBES2 + AES-256-CBC + PBKDF2-SHA256) encoded as ASN.1 DER.
///
/// Generated using:
///
/// ```
/// $ openssl pkcs8 -v2 aes256-cbc -v2prf hmacWithSHA256 -topk8 -inform der -in ed25519-priv.der -outform der -out ed25519-encpriv-aes256-pbkdf2-sha256.der
/// ```
const ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE: &[u8] =
include_bytes!("examples/ed25519-encpriv-aes256-pbkdf2-sha256.der");
/// Ed25519 PKCS#8 encrypted private key (PBES2 + AES-256-CBC + scrypt) encoded as ASN.1 DER.
///
/// Generated using:
///
/// ```
/// $ openssl pkcs8 -v2 aes256-cbc -scrypt -topk8 -inform der -in ed25519-priv.der -outform der -out ed25519-encpriv-aes256-scrypt.der
/// ```
#[cfg(feature = "encryption")]
const ED25519_DER_AES256_SCRYPT_EXAMPLE: &[u8] =
include_bytes!("examples/ed25519-encpriv-aes256-scrypt.der");
/// Ed25519 PKCS#8 encrypted private key encoded as PEM
#[cfg(feature = "pem")]
const ED25519_PEM_AES256_PBKDF2_SHA256_EXAMPLE: &str =
include_str!("examples/ed25519-encpriv-aes256-pbkdf2-sha256.pem");
/// Ed25519 PKCS#8 encrypted private key (PBES2 + 3DES + PBKDF2-SHA256) encoded as ASN.1 DER
///
/// Generated using:
///
/// ```
/// $ openssl pkcs8 -v2 des3 -topk8 -inform der -in ed25519-priv-pkcs8v1.der -outform der -out ed25519-encpriv-des3-pbkdf2-sha256.der
/// ```
#[cfg(feature = "3des")]
const ED25519_DER_DES3_PBKDF2_SHA256_EXAMPLE: &[u8] =
include_bytes!("examples/ed25519-encpriv-des3-pbkdf2-sha256.der");
/// Ed25519 PKCS#8 encrypted private key (PBES2 + DES + PBKDF2-SHA256) encoded as ASN.1 DER
///
/// Generated using:
///
/// ```
/// $ openssl pkcs8 -v2 des -topk8 -inform der -in ed25519-priv-pkcs8v1.der -outform der -out ed25519-encpriv-des3-pbkdf2-sha256.der
/// ```
#[cfg(feature = "des-insecure")]
const ED25519_DER_DES_PBKDF2_SHA256_EXAMPLE: &[u8] =
include_bytes!("examples/ed25519-encpriv-des-pbkdf2-sha256.der");
/// Password used to encrypt the keys.
#[cfg(feature = "encryption")]
const PASSWORD: &[u8] = b"hunter42"; // Bad password; don't actually use outside tests!
#[test]
fn decode_ed25519_encpriv_aes128_pbkdf2_sha1_der() {
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES128_PBKDF2_SHA1_EXAMPLE).unwrap();
assert_eq!(
pk.encryption_algorithm.oid(),
"1.2.840.113549.1.5.13".parse().unwrap()
); // PBES2
let pbes2_params = pk.encryption_algorithm.pbes2().unwrap();
let pbkdf2_params = pbes2_params.kdf.pbkdf2().unwrap();
assert_eq!(pbkdf2_params.salt, hex!("e8765e01e43b6bad"));
assert_eq!(pbkdf2_params.iteration_count, 2048);
assert_eq!(pbkdf2_params.key_length, None);
assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha1);
match pbes2_params.encryption {
pbes2::EncryptionScheme::Aes128Cbc { iv } => {
assert_eq!(iv, &hex!("223080a71bcd2b9a256d876c924979d2"));
}
other => panic!("unexpected encryption scheme: {:?}", other),
}
// Extracted with:
// $ openssl asn1parse -inform der -in tests/examples/ed25519-encpriv-aes128-sha1.der
assert_eq!(
pk.encrypted_data,
&hex!("4B4D091548EAC381EE7663B21234CD4FF3C9DF664D713394CACCEA7C9B982BD8F29910FABCA4BF7BE0431FAC5C4D657BE997C1F5BF40E2DA465AC1FCC2E30470")
);
}
#[test]
fn decode_ed25519_encpriv_aes256_pbkdf2_sha256_der() {
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
assert_eq!(
pk.encryption_algorithm.oid(),
"1.2.840.113549.1.5.13".parse().unwrap()
); // PBES2
let pbes2_params = pk.encryption_algorithm.pbes2().unwrap();
let pbkdf2_params = pbes2_params.kdf.pbkdf2().unwrap();
assert_eq!(pbkdf2_params.salt, hex!("79d982e70df91a88"));
assert_eq!(pbkdf2_params.iteration_count, 2048);
assert_eq!(pbkdf2_params.key_length, None);
assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha256);
match pbes2_params.encryption {
pbes2::EncryptionScheme::Aes256Cbc { iv } => {
assert_eq!(iv, &hex!("b2d02d78b2efd9dff694cf8e0af40925"));
}
other => panic!("unexpected encryption scheme: {:?}", other),
}
// Extracted with:
// $ openssl asn1parse -inform der -in tests/examples/ed25519-encpriv-aes256-sha256.der
assert_eq!(
pk.encrypted_data,
&hex!("D0CD6C770F4BB87176422305C17401809E226674CE74185D221BFDAA95069890C8882FCE02B05D41BCBF54B035595BCD4154B32593708469B86AACF8815A7B2B")
);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_ed25519_der_encpriv_aes256_pbkdf2_sha256() {
let enc_pk =
EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
let pk = enc_pk.decrypt(PASSWORD).unwrap();
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_ed25519_der_encpriv_aes256_scrypt() {
let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_SCRYPT_EXAMPLE).unwrap();
let pk = enc_pk.decrypt(PASSWORD).unwrap();
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
}
#[cfg(feature = "encryption")]
#[test]
fn encrypt_ed25519_der_encpriv_aes256_pbkdf2_sha256() {
let pbes2_params = pkcs5::pbes2::Parameters::pbkdf2_sha256_aes256cbc(
2048,
&hex!("79d982e70df91a88"),
&hex!("b2d02d78b2efd9dff694cf8e0af40925"),
)
.unwrap();
let pk_plaintext = PrivateKeyInfo::try_from(ED25519_DER_PLAINTEXT_EXAMPLE).unwrap();
let pk_encrypted = pk_plaintext
.encrypt_with_params(pbes2_params, PASSWORD)
.unwrap();
assert_eq!(
pk_encrypted.as_bytes(),
ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE
);
}
#[cfg(feature = "encryption")]
#[test]
fn encrypt_ed25519_der_encpriv_aes256_scrypt() {
let scrypt_params = pkcs5::pbes2::Parameters::scrypt_aes256cbc(
pkcs5::scrypt::Params::new(15, 8, 1, 32).unwrap(),
&hex!("E6211E2348AD69E0"),
&hex!("9BD0A6251F2254F9FD5963887C27CF01"),
)
.unwrap();
let pk_plaintext = PrivateKeyInfo::try_from(ED25519_DER_PLAINTEXT_EXAMPLE).unwrap();
let pk_encrypted = pk_plaintext
.encrypt_with_params(scrypt_params, PASSWORD)
.unwrap();
assert_eq!(pk_encrypted.as_bytes(), ED25519_DER_AES256_SCRYPT_EXAMPLE);
}
#[test]
#[cfg(feature = "alloc")]
fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_der() {
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
assert_eq!(
ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE,
&pk.to_der().unwrap()
);
}
#[test]
#[cfg(feature = "pem")]
fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_pem() {
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
assert_eq!(
ED25519_PEM_AES256_PBKDF2_SHA256_EXAMPLE,
pk.to_pem(Default::default()).unwrap()
);
}
#[test]
#[cfg(feature = "3des")]
fn decrypt_ed25519_der_encpriv_des3_pbkdf2_sha256() {
let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_DES3_PBKDF2_SHA256_EXAMPLE).unwrap();
let pk = enc_pk.decrypt(PASSWORD).unwrap();
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
}
#[test]
#[cfg(feature = "des-insecure")]
fn decrypt_ed25519_der_encpriv_des_pbkdf2_sha256() {
let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_DES_PBKDF2_SHA256_EXAMPLE).unwrap();
let pk = enc_pk.decrypt(PASSWORD).unwrap();
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
}

Binary file not shown.

View File

@@ -0,0 +1,6 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAh52YLnDfkaiAICCAAw
DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEELLQLXiy79nf9pTPjgr0CSUEQNDN
bHcPS7hxdkIjBcF0AYCeImZ0znQYXSIb/aqVBpiQyIgvzgKwXUG8v1SwNVlbzUFU
syWTcIRpuGqs+IFaeys=
-----END ENCRYPTED PRIVATE KEY-----

Binary file not shown.

View File

@@ -0,0 +1,6 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIGTME8GCSqGSIb3DQEFDTBCMCEGCSsGAQQB2kcECzAUBAjmIR4jSK1p4AICQAAC
AQgCAQEwHQYJYIZIAWUDBAEqBBCb0KYlHyJU+f1ZY4h8J88BBEDMYrp3PA9JX6s2
aOT8782wjnig7hXgoVAT9iq+CNqnQgZe6zZtbmyYzDsOfmm9yGHIiv648D26Hixt
mdBtFzYM
-----END ENCRYPTED PRIVATE KEY-----

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,3 @@
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIBftnHPp22SewYmmEoMcX8VwI4IHwaqd+9LFPj/15eqF
-----END PRIVATE KEY-----

Binary file not shown.

View File

@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MHICAQEwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC
oB8wHQYKKoZIhvcNAQkJFDEPDA1DdXJkbGUgQ2hhaXJzgSEAGb9ECWmEzf6FQbrB
Z9w7lshQhqowtrbLDFw4rXAxZuE=
-----END PRIVATE KEY-----

Binary file not shown.

View File

@@ -0,0 +1,3 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEATSkWfz8ZEqb3rfopOgUaFcBexnuPFyZ7HFVQ3OhTvQ0=
-----END PUBLIC KEY-----

Binary file not shown.

View File

@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgaWJBcVYaYzQN4OfY
afKgVJJVjhoEhotqn4VKhmeIGI2hRANCAAQcrP+1Xy8s79idies3SyaBFSRSgC3u
oJkWBoE32DnPf8SBpESSME1+9mrBF77+g6jQjxVfK1L59hjdRHApBI4P
-----END PRIVATE KEY-----

BIN
vendor/pkcs8/tests/examples/p256-pub.der vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHKz/tV8vLO/YnYnrN0smgRUkUoAt
7qCZFgaBN9g5z3/EgaREkjBNfvZqwRe+/oOo0I8VXytS+fYY3URwKQSODw==
-----END PUBLIC KEY-----

Binary file not shown.

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2xCxRXxCmqvKC
xj7b4kJDoXDz+iYzvUgzY39Hyk9vNuA6XSnvwxkayA85DYdLOeMPQU/Owfyg7YHl
R+3CzTgsdvYckBiXPbn6U3lyp8cB9rd+CYLfwV/AGSfuXnzZS09Zn/BwE6fIKBvf
Ity8mtfKu3xDEcmC9Y7bchOtRVizMiZtdDrtgZLRiEytuLFHOaja2mbclwgG2ces
RQyxPQ18V1+xmFNPxhvEG8DwV04OATDHu7+9/cn2puLj4q/xy+rIm6V4hFKNVc+w
gyeh6MifTgA88oiOkzJB2daVvLus3JC0Tj4JX6NwWOolsT9eKVy+rG3oOKuMUK9h
4piXW4cvAgMBAAECggEAfsyDYsDtsHQRZCFeIvdKudkboGkAcAz2NpDlEU2O5r3P
uy4/lhRpKmd6CD8Wil5S5ZaOZAe52XxuDkBk+C2gt1ihTxe5t9QfX0jijWVRcE9W
5p56qfpjD8dkKMBtJeRV3PxVt6wrT3ZkP97T/hX/eKuyfmWsxKrQvfbbJ+9gppEM
XEoIXtQydasZwdmXoyxu/8598tGTX25gHu3hYaErXMJ8oh+B0smcPR6gjpDjBTqw
m++nJN7w0MOjwel0DA2fdhJqFJ7Aqn2AeCBUhCVNlR2wfEz5H7ZFTAlliP1ZJNur
6zWcogJSaNAE+dZus9b3rcETm61A8W3eY54RZHN2wQKBgQDcwGEkLU6Sr67nKsUT
ymW593A2+b1+Dm5hRhp+92VCJewVPH5cMaYVem5aE/9uF46HWMHLM9nWu+MXnvGJ
mOQi7Ny+149Oz9vl9PzYrsLJ0NyGRzypvRbZ0jjSH7Xd776xQ8ph0L1qqNkfM6CX
eQ6WQNvJEIXcXyY0O6MTj2stZwKBgQDT8xR1fkDpVINvkr4kI2ry8NoEo0ZTwYCv
Z+lgCG2T/eZcsj79nQk3R2L1mB42GEmvaM3XU5T/ak4G62myCeQijbLfpw5A9/l1
ClKBdmR7eI0OV3eiy4si480mf/cLTzsC06r7DhjFkKVksDGIsKpfxIFWsHYiIUJD
vRIn76fy+QKBgQDOaLesGw0QDWNuVUiHU8XAmEP9s5DicF33aJRXyb2Nl2XjCXhh
fi78gEj0wyQgbbhgh7ZU6Xuz1GTn7j+M2D/hBDb33xjpqWPE5kkR1n7eNAQvLibj
06GtNGra1rm39ncIywlOYt7p/01dZmmvmIryJV0c6O0xfGp9hpHaNU0S2wKBgCX2
5ZRCIChrTfu/QjXA7lhD0hmAkYlRINbKeyALgm0+znOOLgBJj6wKKmypacfww8oa
sLxAKXEyvnU4177fTLDvxrmO99ulT1aqmaq85TTEnCeUfUZ4xRxjx4x84WhyMbTI
61h65u8EgMuvT8AXPP1Yen5nr1FfubnedREYOXIpAoGAMZlUBtQGIHyt6uo1s40E
DF+Kmhrggn6e0GsVPYO2ghk1tLNqgr6dVseRtYwnJxpXk9U6HWV8CJl5YLFDPlFx
mH9FLxRKfHIwbWPh0//Atxt1qwjy5FpILpiEUcvkeOEusijQdFbJJLZvbO0EjYU/
Uz4xpoYU8cPObY7JmDznKvc=
-----END PRIVATE KEY-----

Binary file not shown.

View File

@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtsQsUV8QpqrygsY+2+JC
Q6Fw8/omM71IM2N/R8pPbzbgOl0p78MZGsgPOQ2HSznjD0FPzsH8oO2B5Uftws04
LHb2HJAYlz25+lN5cqfHAfa3fgmC38FfwBkn7l582UtPWZ/wcBOnyCgb3yLcvJrX
yrt8QxHJgvWO23ITrUVYszImbXQ67YGS0YhMrbixRzmo2tpm3JcIBtnHrEUMsT0N
fFdfsZhTT8YbxBvA8FdODgEwx7u/vf3J9qbi4+Kv8cvqyJuleIRSjVXPsIMnoejI
n04APPKIjpMyQdnWlby7rNyQtE4+CV+jcFjqJbE/Xilcvqxt6DirjFCvYeKYl1uH
LwIDAQAB
-----END PUBLIC KEY-----

Binary file not shown.

View File

@@ -0,0 +1,3 @@
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VuBCIEIHBgJSkzrG56SpsOsmMsWgQKhyV624aaPszD0WtyTyZH
-----END PRIVATE KEY-----

187
vendor/pkcs8/tests/private_key.rs vendored Normal file
View File

@@ -0,0 +1,187 @@
//! PKCS#8 private key tests
use der::asn1::ObjectIdentifier;
use hex_literal::hex;
use pkcs8::{PrivateKeyInfo, Version};
#[cfg(feature = "alloc")]
use der::Encode;
#[cfg(feature = "pem")]
use der::{pem::LineEnding, EncodePem};
/// Elliptic Curve (P-256) PKCS#8 private key encoded as ASN.1 DER
const EC_P256_DER_EXAMPLE: &[u8] = include_bytes!("examples/p256-priv.der");
/// Ed25519 PKCS#8 v1 private key encoded as ASN.1 DER
const ED25519_DER_V1_EXAMPLE: &[u8] = include_bytes!("examples/ed25519-priv-pkcs8v1.der");
/// Ed25519 PKCS#8 v2 private key + public key encoded as ASN.1 DER
const ED25519_DER_V2_EXAMPLE: &[u8] = include_bytes!("examples/ed25519-priv-pkcs8v2.der");
/// RSA-2048 PKCS#8 private key encoded as ASN.1 DER
const RSA_2048_DER_EXAMPLE: &[u8] = include_bytes!("examples/rsa2048-priv.der");
/// X25519 PKCS#8 private key encoded as ASN.1 DER
const X25519_DER_EXAMPLE: &[u8] = include_bytes!("examples/x25519-priv.der");
/// Elliptic Curve (P-256) PKCS#8 private key encoded as PEM
#[cfg(feature = "pem")]
const EC_P256_PEM_EXAMPLE: &str = include_str!("examples/p256-priv.pem");
/// Ed25519 PKCS#8 private key encoded as PEM
#[cfg(feature = "pem")]
const ED25519_PEM_V1_EXAMPLE: &str = include_str!("examples/ed25519-priv-pkcs8v1.pem");
/// RSA-2048 PKCS#8 private key encoded as PEM
#[cfg(feature = "pem")]
const RSA_2048_PEM_EXAMPLE: &str = include_str!("examples/rsa2048-priv.pem");
/// X25519 PKCS#8 private key encoded as PEM
#[cfg(feature = "pem")]
const X25519_PEM_EXAMPLE: &str = include_str!("examples/x25519-priv.pem");
#[test]
fn decode_ec_p256_der() {
let pk = PrivateKeyInfo::try_from(EC_P256_DER_EXAMPLE).unwrap();
assert_eq!(pk.version(), Version::V1);
assert_eq!(pk.algorithm.oid, "1.2.840.10045.2.1".parse().unwrap());
assert_eq!(
pk.algorithm
.parameters
.unwrap()
.decode_as::<ObjectIdentifier>()
.unwrap(),
"1.2.840.10045.3.1.7".parse().unwrap()
);
// Extracted with:
// $ openssl asn1parse -inform der -in tests/examples/p256-priv.der
assert_eq!(pk.private_key, &hex!("306B020101042069624171561A63340DE0E7D869F2A05492558E1A04868B6A9F854A866788188DA144034200041CACFFB55F2F2CEFD89D89EB374B2681152452802DEEA09916068137D839CF7FC481A44492304D7EF66AC117BEFE83A8D08F155F2B52F9F618DD447029048E0F")[..]);
}
// Test vector from RFC8410 Section 10.3:
// https://datatracker.ietf.org/doc/html/rfc8410#section-10.3
#[test]
fn decode_ed25519_der_v1() {
let pk = PrivateKeyInfo::try_from(ED25519_DER_V1_EXAMPLE).unwrap();
assert_eq!(pk.version(), Version::V1);
assert_eq!(pk.algorithm.oid, "1.3.101.112".parse().unwrap());
assert_eq!(pk.algorithm.parameters, None);
// Extracted with:
// $ openssl asn1parse -inform der -in tests/examples/ed25519-priv.der
assert_eq!(
pk.private_key,
&hex!("042017ED9C73E9DB649EC189A612831C5FC570238207C1AA9DFBD2C53E3FF5E5EA85")[..]
);
}
// Test vector from RFC8410 Section 10.3:
// https://datatracker.ietf.org/doc/html/rfc8410#section-10.3
#[test]
fn decode_ed25519_der_v2() {
// Extracted with:
// $ openssl asn1parse -inform der -in tests/examples/ed25519-priv-pkcs8v2.der
const PRIV_KEY: [u8; 34] =
hex!("0420D4EE72DBF913584AD5B6D8F1F769F8AD3AFE7C28CBF1D4FBE097A88F44755842");
const PUB_KEY: [u8; 32] =
hex!("19BF44096984CDFE8541BAC167DC3B96C85086AA30B6B6CB0C5C38AD703166E1");
let pk = PrivateKeyInfo::try_from(ED25519_DER_V2_EXAMPLE).unwrap();
assert_eq!(pk.version(), Version::V2);
assert_eq!(pk.algorithm.oid, "1.3.101.112".parse().unwrap());
assert_eq!(pk.algorithm.parameters, None);
assert_eq!(pk.private_key, PRIV_KEY);
assert_eq!(pk.public_key, Some(&PUB_KEY[..]));
}
#[test]
fn decode_rsa_2048_der() {
let pk = PrivateKeyInfo::try_from(RSA_2048_DER_EXAMPLE).unwrap();
assert_eq!(pk.version(), Version::V1);
assert_eq!(pk.algorithm.oid, "1.2.840.113549.1.1.1".parse().unwrap());
assert!(pk.algorithm.parameters.unwrap().is_null());
// Extracted with:
// $ openssl asn1parse -inform der -in tests/examples/rsa2048-priv.der
assert_eq!(pk.private_key, &hex!("308204A30201000282010100B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F0203010001028201007ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C102818100DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D6702818100D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F902818100CE68B7AC1B0D100D636E55488753C5C09843FDB390E2705DF7689457C9BD8D9765E30978617E2EFC8048F4C324206DB86087B654E97BB3D464E7EE3F8CD83FE10436F7DF18E9A963C4E64911D67EDE34042F2E26E3D3A1AD346ADAD6B9B7F67708CB094E62DEE9FF4D5D6669AF988AF2255D1CE8ED317C6A7D8691DA354D12DB02818025F6E5944220286B4DFBBF4235C0EE5843D2198091895120D6CA7B200B826D3ECE738E2E00498FAC0A2A6CA969C7F0C3CA1AB0BC40297132BE7538D7BEDF4CB0EFC6B98EF7DBA54F56AA99AABCE534C49C27947D4678C51C63C78C7CE1687231B4C8EB587AE6EF0480CBAF4FC0173CFD587A7E67AF515FB9B9DE75111839722902818031995406D406207CADEAEA35B38D040C5F8A9A1AE0827E9ED06B153D83B6821935B4B36A82BE9D56C791B58C27271A5793D53A1D657C08997960B1433E5171987F452F144A7C72306D63E1D3FFC0B71B75AB08F2E45A482E988451CBE478E12EB228D07456C924B66F6CED048D853F533E31A68614F1C3CE6D8EC9983CE72AF7")[..]);
}
#[test]
fn decode_x25519_der() {
let pk = PrivateKeyInfo::try_from(X25519_DER_EXAMPLE).unwrap();
assert_eq!(pk.version(), Version::V1);
assert_eq!(pk.algorithm.oid, "1.3.101.110".parse().unwrap());
assert_eq!(pk.algorithm.parameters, None);
// Extracted with:
// $ openssl asn1parse -inform der -in tests/examples/x25519-priv.der
assert_eq!(
pk.private_key,
&hex!("04207060252933AC6E7A4A9B0EB2632C5A040A87257ADB869A3ECCC3D16B724F2647")[..]
);
}
#[test]
#[cfg(feature = "alloc")]
fn encode_ec_p256_der() {
let pk = PrivateKeyInfo::try_from(EC_P256_DER_EXAMPLE).unwrap();
let pk_encoded = pk.to_der().unwrap();
assert_eq!(EC_P256_DER_EXAMPLE, pk_encoded);
}
#[test]
#[cfg(feature = "alloc")]
fn encode_ed25519_der_v1() {
let pk = PrivateKeyInfo::try_from(ED25519_DER_V1_EXAMPLE).unwrap();
assert_eq!(ED25519_DER_V1_EXAMPLE, pk.to_der().unwrap());
}
#[test]
#[cfg(all(feature = "alloc", feature = "subtle"))]
fn encode_ed25519_der_v2() {
let private_key = PrivateKeyInfo::try_from(ED25519_DER_V2_EXAMPLE).unwrap();
let private_der = private_key.to_der().unwrap();
assert_eq!(
private_key,
PrivateKeyInfo::try_from(private_der.as_ref()).unwrap()
);
}
#[test]
#[cfg(feature = "alloc")]
fn encode_rsa_2048_der() {
let pk = PrivateKeyInfo::try_from(RSA_2048_DER_EXAMPLE).unwrap();
assert_eq!(RSA_2048_DER_EXAMPLE, &pk.to_der().unwrap());
}
#[test]
#[cfg(feature = "pem")]
fn encode_ec_p256_pem() {
let pk = PrivateKeyInfo::try_from(EC_P256_DER_EXAMPLE).unwrap();
assert_eq!(EC_P256_PEM_EXAMPLE, pk.to_pem(LineEnding::LF).unwrap());
}
#[test]
#[cfg(feature = "pem")]
fn encode_ed25519_pem() {
let pk = PrivateKeyInfo::try_from(ED25519_DER_V1_EXAMPLE).unwrap();
assert_eq!(ED25519_PEM_V1_EXAMPLE, pk.to_pem(LineEnding::LF).unwrap());
}
#[test]
#[cfg(feature = "pem")]
fn encode_rsa_2048_pem() {
let pk = PrivateKeyInfo::try_from(RSA_2048_DER_EXAMPLE).unwrap();
assert_eq!(RSA_2048_PEM_EXAMPLE, pk.to_pem(LineEnding::LF).unwrap());
}
#[test]
#[cfg(feature = "pem")]
fn encode_x25519_pem() {
let pk = PrivateKeyInfo::try_from(X25519_DER_EXAMPLE).unwrap();
assert_eq!(X25519_PEM_EXAMPLE, pk.to_pem(LineEnding::LF).unwrap());
}

102
vendor/pkcs8/tests/traits.rs vendored Normal file
View File

@@ -0,0 +1,102 @@
//! Tests for PKCS#8 encoding/decoding traits.
#![cfg(any(feature = "pem", feature = "std"))]
use der::Encode;
use pkcs8::{DecodePrivateKey, EncodePrivateKey, Error, PrivateKeyInfo, Result, SecretDocument};
#[cfg(feature = "pem")]
use pkcs8::der::pem::LineEnding;
#[cfg(feature = "std")]
use tempfile::tempdir;
#[cfg(all(feature = "pem", feature = "std"))]
use std::fs;
/// Ed25519 `PrivateKeyInfo` encoded as ASN.1 DER
const ED25519_DER_EXAMPLE: &[u8] = include_bytes!("examples/ed25519-priv-pkcs8v1.der");
/// Ed25519 private key encoded as PEM
#[cfg(feature = "pem")]
const ED25519_PEM_EXAMPLE: &str = include_str!("examples/ed25519-priv-pkcs8v1.pem");
/// Mock key type for testing trait impls against.
pub struct MockKey(Vec<u8>);
impl AsRef<[u8]> for MockKey {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl EncodePrivateKey for MockKey {
fn to_pkcs8_der(&self) -> Result<SecretDocument> {
Ok(SecretDocument::try_from(self.as_ref())?)
}
}
impl TryFrom<PrivateKeyInfo<'_>> for MockKey {
type Error = Error;
fn try_from(pkcs8: PrivateKeyInfo<'_>) -> Result<MockKey> {
Ok(MockKey(pkcs8.to_der()?))
}
}
#[cfg(feature = "pem")]
#[test]
fn from_pkcs8_pem() {
let key = MockKey::from_pkcs8_pem(ED25519_PEM_EXAMPLE).unwrap();
assert_eq!(key.as_ref(), ED25519_DER_EXAMPLE);
}
#[cfg(feature = "std")]
#[test]
fn read_pkcs8_der_file() {
let key = MockKey::read_pkcs8_der_file("tests/examples/ed25519-priv-pkcs8v1.der").unwrap();
assert_eq!(key.as_ref(), ED25519_DER_EXAMPLE);
}
#[cfg(all(feature = "pem", feature = "std"))]
#[test]
fn read_pkcs8_pem_file() {
let key = MockKey::read_pkcs8_pem_file("tests/examples/ed25519-priv-pkcs8v1.pem").unwrap();
assert_eq!(key.as_ref(), ED25519_DER_EXAMPLE);
}
#[cfg(feature = "pem")]
#[test]
fn to_pkcs8_pem() {
let pem = MockKey(ED25519_DER_EXAMPLE.to_vec())
.to_pkcs8_pem(LineEnding::LF)
.unwrap();
assert_eq!(&*pem, ED25519_PEM_EXAMPLE);
}
#[cfg(feature = "std")]
#[test]
fn write_pkcs8_der_file() {
let dir = tempdir().unwrap();
let path = dir.path().join("example.der");
MockKey(ED25519_DER_EXAMPLE.to_vec())
.write_pkcs8_der_file(&path)
.unwrap();
let key = MockKey::read_pkcs8_der_file(&path).unwrap();
assert_eq!(key.as_ref(), ED25519_DER_EXAMPLE);
}
#[cfg(all(feature = "pem", feature = "std"))]
#[test]
fn write_pkcs8_pem_file() {
let dir = tempdir().unwrap();
let path = dir.path().join("example.pem");
MockKey(ED25519_DER_EXAMPLE.to_vec())
.write_pkcs8_pem_file(&path, LineEnding::LF)
.unwrap();
let pem = fs::read_to_string(path).unwrap();
assert_eq!(&pem, ED25519_PEM_EXAMPLE);
}