Revert^2 "Upgrade pkcs8 to 0.10.2" am: 3bca4ade94 am: e5ce060c3c am: 92f72ca477

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/pkcs8/+/2881156

Change-Id: Ibc763f9331602ddc9d6b4807bc1cdada333848aa
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 68186e0..d445424 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "974c2c7c88bc8d0541895a6e200c3ea9f91a33af"
+    "sha1": "7736dd21389b8820dfeb396e8c4c932de93d3ddf"
   },
   "path_in_vcs": "pkcs8"
 }
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 005c9b5..cc61a68 100644
--- a/Android.bp
+++ b/Android.bp
@@ -35,7 +35,7 @@
     name: "libpkcs8",
     crate_name: "pkcs8",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.9.0",
+    cargo_pkg_version: "0.10.2",
     srcs: ["src/lib.rs"],
     edition: "2021",
     features: ["alloc"],
@@ -49,7 +49,7 @@
     name: "libpkcs8_nostd",
     crate_name: "pkcs8",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.9.0",
+    cargo_pkg_version: "0.10.2",
     srcs: ["src/lib.rs"],
     edition: "2021",
     features: ["alloc"],
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 15889d9..1f754d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,30 @@
 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])
diff --git a/Cargo.toml b/Cargo.toml
index 6de007a..d836551 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,9 +11,9 @@
 
 [package]
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 name = "pkcs8"
-version = "0.9.0"
+version = "0.10.2"
 authors = ["RustCrypto Developers"]
 description = """
 Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #8:
@@ -36,7 +36,6 @@
 ]
 license = "Apache-2.0 OR MIT"
 repository = "https://github.com/RustCrypto/formats/tree/master/pkcs8"
-resolver = "2"
 
 [package.metadata.docs.rs]
 all-features = true
@@ -46,11 +45,11 @@
 ]
 
 [dependencies.der]
-version = "0.6"
+version = "0.7"
 features = ["oid"]
 
 [dependencies.pkcs5]
-version = "0.5"
+version = "0.7"
 optional = true
 
 [dependencies.rand_core]
@@ -59,7 +58,7 @@
 default-features = false
 
 [dependencies.spki]
-version = "0.6"
+version = "0.7.1"
 
 [dependencies.subtle]
 version = "2"
@@ -98,9 +97,9 @@
     "der/pem",
     "spki/pem",
 ]
-sha1 = [
+sha1-insecure = [
     "encryption",
-    "pkcs5/sha1",
+    "pkcs5/sha1-insecure",
 ]
 std = [
     "alloc",
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index c5e821a..9ffae2b 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "pkcs8"
-version = "0.9.0" # Also update html_root_url in lib.rs when bumping this
+version = "0.10.2"
 description = """
 Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #8:
 Private-Key Information Syntax Specification (RFC 5208), with additional
@@ -13,15 +13,15 @@
 keywords = ["crypto", "key", "pkcs", "private"]
 readme = "README.md"
 edition = "2021"
-rust-version = "1.57"
+rust-version = "1.65"
 
 [dependencies]
-der = { version = "0.6", features = ["oid"], path = "../der" }
-spki = { version = "0.6", path = "../spki" }
+der = { version = "0.7", features = ["oid"], path = "../der" }
+spki = { version = "0.7.1", path = "../spki" }
 
 # optional dependencies
 rand_core = { version = "0.6", optional = true, default-features = false }
-pkcs5 = { version = "0.5", optional = true, path = "../pkcs5" }
+pkcs5 = { version = "0.7", optional = true, path = "../pkcs5" }
 subtle = { version = "2", optional = true, default-features = false }
 
 [dev-dependencies]
@@ -30,13 +30,14 @@
 
 [features]
 alloc = ["der/alloc", "der/zeroize", "spki/alloc"]
+std = ["alloc", "der/std", "spki/std"]
+
 3des = ["encryption", "pkcs5/3des"]
 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 = ["encryption", "pkcs5/sha1"]
-std = ["alloc", "der/std", "spki/std"]
+sha1-insecure = ["encryption", "pkcs5/sha1-insecure"]
 
 [package.metadata.docs.rs]
 all-features = true
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..e0d0827
--- /dev/null
+++ b/LICENSE-MIT
@@ -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.
diff --git a/METADATA b/METADATA
index 38059a2..3b0922c 100644
--- a/METADATA
+++ b/METADATA
@@ -1,20 +1,20 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/pkcs8
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
+
 name: "pkcs8"
 description: "Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #8: Private-Key Information Syntax Specification (RFC 5208)."
 third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://crates.io/crates/pkcs8"
-  }
-  url {
-    type: ARCHIVE
-    value: "https://static.crates.io/crates/pkcs8/pkcs8-0.9.0.crate"
-  }
-  version: "0.9.0"
-  # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same.
   license_type: NOTICE
   last_upgrade_date {
-    year: 2022
-    month: 9
-    day: 6
+    year: 2023
+    month: 12
+    day: 15
+  }
+  homepage: "https://crates.io/crates/pkcs8"
+  identifier {
+    type: "Archive"
+    value: "https://static.crates.io/crates/pkcs8/pkcs8-0.10.2.crate"
+    version: "0.10.2"
   }
 }
diff --git a/README.md b/README.md
index 2fa301c..c158543 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@
 
 ## Minimum Supported Rust Version
 
-This crate requires **Rust 1.57** at a minimum.
+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.
@@ -81,7 +81,7 @@
 [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.57+-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
diff --git a/src/encrypted_private_key_info.rs b/src/encrypted_private_key_info.rs
index 460e3f6..d55949c 100644
--- a/src/encrypted_private_key_info.rs
+++ b/src/encrypted_private_key_info.rs
@@ -2,7 +2,10 @@
 
 use crate::{Error, Result};
 use core::fmt;
-use der::{asn1::OctetStringRef, Decode, DecodeValue, Encode, Header, Reader, Sequence};
+use der::{
+    asn1::OctetStringRef, Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader,
+    Sequence, Writer,
+};
 use pkcs5::EncryptionScheme;
 
 #[cfg(feature = "alloc")]
@@ -36,7 +39,6 @@
 /// ```
 ///
 /// [RFC 5208 Section 6]: https://tools.ietf.org/html/rfc5208#section-6
-#[cfg_attr(docsrs, doc(cfg(feature = "pkcs5")))]
 #[derive(Clone, Eq, PartialEq)]
 pub struct EncryptedPrivateKeyInfo<'a> {
     /// Algorithm identifier describing a password-based symmetric encryption
@@ -51,7 +53,6 @@
     /// Attempt to decrypt this encrypted private key using the provided
     /// password to derive an encryption key.
     #[cfg(feature = "encryption")]
-    #[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
     pub fn decrypt(&self, password: impl AsRef<[u8]>) -> Result<SecretDocument> {
         Ok(self
             .encryption_algorithm
@@ -62,7 +63,6 @@
     /// Encrypt the given ASN.1 DER document using a symmetric encryption key
     /// derived from the provided password.
     #[cfg(feature = "encryption")]
-    #[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
     pub(crate) fn encrypt(
         mut rng: impl CryptoRng + RngCore,
         password: impl AsRef<[u8]>,
@@ -81,7 +81,6 @@
     /// Encrypt this private key using a symmetric encryption key derived
     /// from the provided password and [`pbes2::Parameters`].
     #[cfg(feature = "encryption")]
-    #[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
     pub(crate) fn encrypt_with(
         pbes2_params: pbes2::Parameters<'a>,
         password: impl AsRef<[u8]>,
@@ -111,18 +110,21 @@
     }
 }
 
-impl<'a> Sequence<'a> for EncryptedPrivateKeyInfo<'a> {
-    fn fields<F, T>(&self, f: F) -> der::Result<T>
-    where
-        F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
-    {
-        f(&[
-            &self.encryption_algorithm,
-            &OctetStringRef::new(self.encrypted_data)?,
-        ])
+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;
 
@@ -140,7 +142,6 @@
 }
 
 #[cfg(feature = "alloc")]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "pkcs5"))))]
 impl TryFrom<EncryptedPrivateKeyInfo<'_>> for SecretDocument {
     type Error = Error;
 
@@ -150,7 +151,6 @@
 }
 
 #[cfg(feature = "alloc")]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "pkcs5"))))]
 impl TryFrom<&EncryptedPrivateKeyInfo<'_>> for SecretDocument {
     type Error = Error;
 
@@ -160,7 +160,6 @@
 }
 
 #[cfg(feature = "pem")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
 impl PemLabel for EncryptedPrivateKeyInfo<'_> {
     const PEM_LABEL: &'static str = "ENCRYPTED PRIVATE KEY";
 }
diff --git a/src/error.rs b/src/error.rs
index bc4c2ea..70c60ae 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -26,7 +26,7 @@
     /// or [`SubjectPublicKeyInfo::subject_public_key`][`crate::SubjectPublicKeyInfo::subject_public_key`].
     KeyMalformed,
 
-    /// [`AlgorithmIdentifier::parameters`][`crate::AlgorithmIdentifier::parameters`]
+    /// [`AlgorithmIdentifier::parameters`][`crate::AlgorithmIdentifierRef::parameters`]
     /// is malformed or otherwise encoded in an unexpected manner.
     ParametersMalformed,
 
diff --git a/src/lib.rs b/src/lib.rs
index 9fcae3a..53730d4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,13 +1,19 @@
 #![no_std]
-#![cfg_attr(docsrs, feature(doc_cfg))]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
 #![doc = include_str!("../README.md")]
 #![doc(
-    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
-    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
-    html_root_url = "https://docs.rs/pkcs8/0.9.0-pre"
+    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, clippy::unwrap_used)]
-#![warn(missing_docs, rust_2018_idioms, unused_qualifications)]
+#![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
@@ -88,7 +94,9 @@
     version::Version,
 };
 pub use der::{self, asn1::ObjectIdentifier, oid::AssociatedOid};
-pub use spki::{self, AlgorithmIdentifier, DecodePublicKey, SubjectPublicKeyInfo};
+pub use spki::{
+    self, AlgorithmIdentifierRef, DecodePublicKey, SubjectPublicKeyInfo, SubjectPublicKeyInfoRef,
+};
 
 #[cfg(feature = "alloc")]
 pub use {
@@ -98,7 +106,6 @@
 };
 
 #[cfg(feature = "pem")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
 pub use der::pem::LineEnding;
 
 #[cfg(feature = "pkcs5")]
diff --git a/src/private_key_info.rs b/src/private_key_info.rs
index 52f0878..ecae624 100644
--- a/src/private_key_info.rs
+++ b/src/private_key_info.rs
@@ -1,10 +1,11 @@
 //! PKCS#8 `PrivateKeyInfo`.
 
-use crate::{AlgorithmIdentifier, Error, Result, Version};
+use crate::{AlgorithmIdentifierRef, Error, Result, Version};
 use core::fmt;
 use der::{
     asn1::{AnyRef, BitStringRef, ContextSpecific, OctetStringRef},
-    Decode, DecodeValue, Encode, Header, Reader, Sequence, TagMode, TagNumber,
+    Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, TagMode, TagNumber,
+    Writer,
 };
 
 #[cfg(feature = "alloc")]
@@ -29,7 +30,7 @@
 
 /// PKCS#8 `PrivateKeyInfo`.
 ///
-/// ASN.1 structure containing an [`AlgorithmIdentifier`], private key
+/// ASN.1 structure containing an `AlgorithmIdentifier`, private key
 /// data in an algorithm specific format, and optional attributes
 /// (ignored by this implementation).
 ///
@@ -90,8 +91,8 @@
 /// [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: AlgorithmIdentifier<'a>,
+    /// X.509 `AlgorithmIdentifier` for the private key type.
+    pub algorithm: AlgorithmIdentifierRef<'a>,
 
     /// Private key data.
     pub private_key: &'a [u8],
@@ -105,7 +106,7 @@
     ///
     /// This is a helper method which initializes `attributes` and `public_key`
     /// to `None`, helpful if you aren't using those.
-    pub fn new(algorithm: AlgorithmIdentifier<'a>, private_key: &'a [u8]) -> Self {
+    pub fn new(algorithm: AlgorithmIdentifierRef<'a>, private_key: &'a [u8]) -> Self {
         Self {
             algorithm,
             private_key,
@@ -134,28 +135,39 @@
     ///   - p: 1
     /// - Cipher: AES-256-CBC (best available option for PKCS#5 encryption)
     #[cfg(feature = "encryption")]
-    #[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
     pub fn encrypt(
         &self,
         rng: impl CryptoRng + RngCore,
         password: impl AsRef<[u8]>,
     ) -> Result<SecretDocument> {
-        let der = Zeroizing::new(self.to_vec()?);
+        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")]
-    #[cfg_attr(docsrs, doc(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_vec()?);
+        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> {
@@ -201,29 +213,25 @@
     }
 }
 
-impl<'a> Sequence<'a> for PrivateKeyInfo<'a> {
-    fn fields<F, T>(&self, f: F) -> der::Result<T>
-    where
-        F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
-    {
-        f(&[
-            &u8::from(self.version()),
-            &self.algorithm,
-            &OctetStringRef::new(self.private_key)?,
-            &self
-                .public_key
-                .map(|pk| {
-                    BitStringRef::from_bytes(pk).map(|value| ContextSpecific {
-                        tag_number: PUBLIC_KEY_TAG,
-                        tag_mode: TagMode::Implicit,
-                        value,
-                    })
-                })
-                .transpose()?,
-        ])
+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;
 
@@ -243,7 +251,6 @@
 }
 
 #[cfg(feature = "alloc")]
-#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
 impl TryFrom<PrivateKeyInfo<'_>> for SecretDocument {
     type Error = Error;
 
@@ -253,7 +260,6 @@
 }
 
 #[cfg(feature = "alloc")]
-#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
 impl TryFrom<&PrivateKeyInfo<'_>> for SecretDocument {
     type Error = Error;
 
@@ -263,13 +269,11 @@
 }
 
 #[cfg(feature = "pem")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
 impl PemLabel for PrivateKeyInfo<'_> {
     const PEM_LABEL: &'static str = "PRIVATE KEY";
 }
 
 #[cfg(feature = "subtle")]
-#[cfg_attr(docsrs, doc(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
@@ -281,11 +285,9 @@
 }
 
 #[cfg(feature = "subtle")]
-#[cfg_attr(docsrs, doc(cfg(feature = "subtle")))]
 impl<'a> Eq for PrivateKeyInfo<'a> {}
 
 #[cfg(feature = "subtle")]
-#[cfg_attr(docsrs, doc(cfg(feature = "subtle")))]
 impl<'a> PartialEq for PrivateKeyInfo<'a> {
     fn eq(&self, other: &Self) -> bool {
         self.ct_eq(other).into()
diff --git a/src/traits.rs b/src/traits.rs
index dd86b90..b4f80b2 100644
--- a/src/traits.rs
+++ b/src/traits.rs
@@ -21,17 +21,14 @@
 use std::path::Path;
 
 /// Parse a private key object from a PKCS#8 encoded document.
-pub trait DecodePrivateKey: for<'a> TryFrom<PrivateKeyInfo<'a>, Error = Error> + Sized {
+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> {
-        Self::try_from(PrivateKeyInfo::try_from(bytes)?)
-    }
+    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")]
-    #[cfg_attr(docsrs, doc(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())
@@ -45,7 +42,6 @@
     /// -----BEGIN PRIVATE KEY-----
     /// ```
     #[cfg(feature = "pem")]
-    #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
     fn from_pkcs8_pem(s: &str) -> Result<Self> {
         let (label, doc) = SecretDocument::from_pem(s)?;
         PrivateKeyInfo::validate_pem_label(label)?;
@@ -61,7 +57,6 @@
     /// -----BEGIN ENCRYPTED PRIVATE KEY-----
     /// ```
     #[cfg(all(feature = "encryption", feature = "pem"))]
-    #[cfg_attr(docsrs, doc(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)?;
@@ -71,15 +66,12 @@
     /// Load PKCS#8 private key from an ASN.1 DER-encoded file on the local
     /// filesystem (binary format).
     #[cfg(feature = "std")]
-    #[cfg_attr(docsrs, doc(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"))]
-    #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
-    #[cfg_attr(docsrs, doc(cfg(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)?;
@@ -87,9 +79,17 @@
     }
 }
 
+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")]
-#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
 pub trait EncodePrivateKey {
     /// Serialize a [`SecretDocument`] containing a PKCS#8-encoded private key.
     fn to_pkcs8_der(&self) -> Result<SecretDocument>;
@@ -97,7 +97,6 @@
     /// Create an [`SecretDocument`] containing the ciphertext of
     /// a PKCS#8 encoded private key encrypted under the given `password`.
     #[cfg(feature = "encryption")]
-    #[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
     fn to_pkcs8_encrypted_der(
         &self,
         rng: impl CryptoRng + RngCore,
@@ -108,7 +107,6 @@
 
     /// Serialize this private key as PEM-encoded PKCS#8 with the given [`LineEnding`].
     #[cfg(feature = "pem")]
-    #[cfg_attr(docsrs, doc(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)?)
@@ -117,7 +115,6 @@
     /// 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"))]
-    #[cfg_attr(docsrs, doc(cfg(all(feature = "encryption", feature = "pem"))))]
     fn to_pkcs8_encrypted_pem(
         &self,
         rng: impl CryptoRng + RngCore,
@@ -130,14 +127,12 @@
 
     /// Write ASN.1 DER-encoded PKCS#8 private key to the given path
     #[cfg(feature = "std")]
-    #[cfg_attr(docsrs, doc(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"))]
-    #[cfg_attr(docsrs, doc(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)?)
diff --git a/src/version.rs b/src/version.rs
index 3393683..0ca80bc 100644
--- a/src/version.rs
+++ b/src/version.rs
@@ -6,7 +6,7 @@
 /// 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)]
+#[derive(Clone, Debug, Copy, PartialEq, Eq)]
 pub enum Version {
     /// Denotes PKCS#8 v1: no public key field.
     V1 = 0,
@@ -36,7 +36,7 @@
         der::Length::from(1u8).for_tlv()
     }
 
-    fn encode(&self, writer: &mut dyn Writer) -> der::Result<()> {
+    fn encode(&self, writer: &mut impl Writer) -> der::Result<()> {
         u8::from(*self).encode(writer)
     }
 }
diff --git a/tests/encrypted_private_key.rs b/tests/encrypted_private_key.rs
index 2bd72ae..dbe0a18 100644
--- a/tests/encrypted_private_key.rs
+++ b/tests/encrypted_private_key.rs
@@ -183,7 +183,7 @@
 #[test]
 fn encrypt_ed25519_der_encpriv_aes256_scrypt() {
     let scrypt_params = pkcs5::pbes2::Parameters::scrypt_aes256cbc(
-        Default::default(),
+        pkcs5::scrypt::Params::new(15, 8, 1, 32).unwrap(),
         &hex!("E6211E2348AD69E0"),
         &hex!("9BD0A6251F2254F9FD5963887C27CF01"),
     )
@@ -203,7 +203,7 @@
     let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
     assert_eq!(
         ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE,
-        &pk.to_vec().unwrap()
+        &pk.to_der().unwrap()
     );
 }
 
diff --git a/tests/private_key.rs b/tests/private_key.rs
index 15d6694..1ef0f73 100644
--- a/tests/private_key.rs
+++ b/tests/private_key.rs
@@ -1,5 +1,6 @@
 //! PKCS#8 private key tests
 
+use der::asn1::ObjectIdentifier;
 use hex_literal::hex;
 use pkcs8::{PrivateKeyInfo, Version};
 
@@ -48,7 +49,11 @@
     assert_eq!(pk.algorithm.oid, "1.2.840.10045.2.1".parse().unwrap());
 
     assert_eq!(
-        pk.algorithm.parameters.unwrap().oid().unwrap(),
+        pk.algorithm
+            .parameters
+            .unwrap()
+            .decode_as::<ObjectIdentifier>()
+            .unwrap(),
         "1.2.840.10045.3.1.7".parse().unwrap()
     );
 
@@ -124,7 +129,7 @@
 #[cfg(feature = "alloc")]
 fn encode_ec_p256_der() {
     let pk = PrivateKeyInfo::try_from(EC_P256_DER_EXAMPLE).unwrap();
-    let pk_encoded = pk.to_vec().unwrap();
+    let pk_encoded = pk.to_der().unwrap();
     assert_eq!(EC_P256_DER_EXAMPLE, pk_encoded);
 }
 
@@ -132,14 +137,14 @@
 #[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_vec().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_vec().unwrap();
+    let private_der = private_key.to_der().unwrap();
     assert_eq!(
         private_key,
         PrivateKeyInfo::try_from(private_der.as_ref()).unwrap()
@@ -150,7 +155,7 @@
 #[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_vec().unwrap());
+    assert_eq!(RSA_2048_DER_EXAMPLE, &pk.to_der().unwrap());
 }
 
 #[test]
diff --git a/tests/traits.rs b/tests/traits.rs
index 1c8a969..4a603bb 100644
--- a/tests/traits.rs
+++ b/tests/traits.rs
@@ -30,12 +30,6 @@
     }
 }
 
-impl DecodePrivateKey for MockKey {
-    fn from_pkcs8_der(bytes: &[u8]) -> Result<MockKey> {
-        Ok(MockKey(bytes.to_vec()))
-    }
-}
-
 impl EncodePrivateKey for MockKey {
     fn to_pkcs8_der(&self) -> Result<SecretDocument> {
         Ok(SecretDocument::try_from(self.as_ref())?)
@@ -46,7 +40,7 @@
     type Error = Error;
 
     fn try_from(pkcs8: PrivateKeyInfo<'_>) -> Result<MockKey> {
-        Ok(MockKey(pkcs8.to_vec()?))
+        Ok(MockKey(pkcs8.to_der()?))
     }
 }