Skip to content

Commit 6c69e47

Browse files
authored
pkcs1+sec1: remove pkcs8 integration/feature (#1927)
Both `pkcs1` and `sec1` used some "clever" tricks to write blanket impls of their traits for any types which impl the `pkcs8` traits. However, we've received some complaints this makes the impls of these traits more confusing and less discoverable (#1611), and adds a maintenance burden in that the blanket impl relationship is fundamentally "backwards" in that PKCS#8 builds on PKCS#1 and SEC1, not the other way around. These could potentially be replaced with a macro that writes impls of the `pkcs8` traits for types which impl the `pkcs1`/`sec1` traits. However, for now, each of these is only used in one place (i.e. the `rsa` and `elliptic-curve` crates respectively), so we can start by moving the relevant code there for now.
1 parent d877d76 commit 6c69e47

File tree

11 files changed

+33
-191
lines changed

11 files changed

+33
-191
lines changed

Cargo.lock

Lines changed: 1 addition & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,4 @@ x509-ocsp = { path = "./x509-ocsp" }
6262

6363
elliptic-curve = { git = "https://github.com/RustCrypto/traits.git" }
6464
ecdsa = { git = "https://github.com/RustCrypto/signatures.git" }
65+
rsa = { git = "https://github.com/RustCrypto/RSA.git", branch = "pkcs1/remove-blanket-impl" }

pkcs1/Cargo.toml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,21 @@ rust-version = "1.85"
1919
der = { version = "0.8.0-rc.6", features = ["oid"] }
2020
spki = { version = "0.8.0-rc.3" }
2121

22-
# optional dependencies
23-
pkcs8 = { version = "0.11.0-rc.5", optional = true, default-features = false }
24-
2522
[dev-dependencies]
2623
const-oid = { version = "0.10", features = ["db"] }
2724
hex-literal = "1"
2825
tempfile = "3"
2926

3027
[features]
31-
zeroize = ["der/zeroize"]
32-
alloc = ["der/alloc", "zeroize", "pkcs8?/alloc"]
33-
pem = ["alloc", "der/pem", "pkcs8?/pem"]
28+
alloc = ["der/alloc", "zeroize"]
3429
std = ["der/std", "alloc"]
3530

31+
pem = ["alloc", "der/pem"]
32+
zeroize = ["der/zeroize"]
33+
34+
# TODO(tarcieri): stub! (for `rsa` crate for now) remove before release
35+
pkcs8 = []
36+
3637
[package.metadata.docs.rs]
3738
all-features = true
3839
rustdoc-args = ["--cfg", "docsrs"]

pkcs1/src/error.rs

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,30 @@ pub enum Error {
2323
/// a number expected to be a prime was not a prime.
2424
Crypto,
2525

26-
/// PKCS#8 errors.
27-
#[cfg(feature = "pkcs8")]
28-
Pkcs8(pkcs8::Error),
26+
/// Malformed cryptographic key contained in a PKCS#1 document.
27+
///
28+
/// This is intended for relaying errors when decoding fields of a PKCS#1 document.
29+
KeyMalformed,
2930

3031
/// Version errors
3132
Version,
3233
}
3334

35+
impl core::error::Error for Error {
36+
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
37+
match self {
38+
Error::Asn1(err) => Some(err),
39+
_ => None,
40+
}
41+
}
42+
}
43+
3444
impl fmt::Display for Error {
3545
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3646
match self {
3747
Error::Asn1(err) => write!(f, "PKCS#1 ASN.1 error: {err}"),
48+
Error::KeyMalformed => f.write_str("PKCS#1 cryptographic key data malformed"),
3849
Error::Crypto => f.write_str("PKCS#1 cryptographic error"),
39-
#[cfg(feature = "pkcs8")]
40-
Error::Pkcs8(err) => write!(f, "{err}"),
4150
Error::Version => f.write_str("PKCS#1 version error"),
4251
}
4352
}
@@ -55,41 +64,3 @@ impl From<pem::Error> for Error {
5564
der::Error::from(err).into()
5665
}
5766
}
58-
59-
#[cfg(feature = "pkcs8")]
60-
impl From<Error> for pkcs8::Error {
61-
fn from(err: Error) -> pkcs8::Error {
62-
match err {
63-
Error::Asn1(e) => pkcs8::Error::Asn1(e),
64-
Error::Crypto | Error::Version => pkcs8::Error::KeyMalformed,
65-
Error::Pkcs8(e) => e,
66-
}
67-
}
68-
}
69-
70-
#[cfg(feature = "pkcs8")]
71-
impl From<pkcs8::Error> for Error {
72-
fn from(err: pkcs8::Error) -> Error {
73-
Error::Pkcs8(err)
74-
}
75-
}
76-
77-
#[cfg(feature = "pkcs8")]
78-
impl From<Error> for spki::Error {
79-
fn from(err: Error) -> spki::Error {
80-
match err {
81-
Error::Asn1(e) => spki::Error::Asn1(e),
82-
_ => spki::Error::KeyMalformed,
83-
}
84-
}
85-
}
86-
87-
#[cfg(feature = "pkcs8")]
88-
impl From<spki::Error> for Error {
89-
fn from(err: spki::Error) -> Error {
90-
Error::Pkcs8(pkcs8::Error::PublicKey(err))
91-
}
92-
}
93-
94-
#[cfg(feature = "std")]
95-
impl std::error::Error for Error {}

pkcs1/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,10 @@ pub use crate::{
5151
pub use der::pem::{self, LineEnding};
5252

5353
/// `rsaEncryption` Object Identifier (OID)
54-
#[cfg(feature = "pkcs8")]
5554
pub const ALGORITHM_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1");
5655

5756
/// `AlgorithmIdentifier` for RSA.
58-
#[cfg(feature = "pkcs8")]
59-
pub const ALGORITHM_ID: pkcs8::AlgorithmIdentifierRef<'static> = pkcs8::AlgorithmIdentifierRef {
57+
pub const ALGORITHM_ID: spki::AlgorithmIdentifierRef<'static> = spki::AlgorithmIdentifierRef {
6058
oid: ALGORITHM_OID,
6159
parameters: Some(der::asn1::AnyRef::NULL),
6260
};

pkcs1/src/traits.rs

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,10 @@ use {
1212
der::{pem::PemLabel, zeroize::Zeroizing},
1313
};
1414

15-
#[cfg(feature = "pkcs8")]
16-
use {
17-
crate::{ALGORITHM_ID, ALGORITHM_OID},
18-
der::asn1::{BitStringRef, OctetStringRef},
19-
};
20-
2115
#[cfg(feature = "std")]
2216
use std::path::Path;
2317

24-
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
25-
use der::Decode;
26-
27-
#[cfg(all(feature = "alloc", any(feature = "pem", feature = "pkcs8")))]
18+
#[cfg(all(feature = "alloc", feature = "pem"))]
2819
use crate::{RsaPrivateKey, RsaPublicKey};
2920

3021
/// Parse an [`RsaPrivateKey`] from a PKCS#1-encoded document.
@@ -153,51 +144,3 @@ pub trait EncodeRsaPublicKey {
153144
Ok(doc.write_pem_file(path, RsaPublicKey::PEM_LABEL, line_ending)?)
154145
}
155146
}
156-
157-
#[cfg(feature = "pkcs8")]
158-
impl<T> DecodeRsaPrivateKey for T
159-
where
160-
T: for<'a> TryFrom<pkcs8::PrivateKeyInfoRef<'a>, Error = pkcs8::Error>,
161-
{
162-
fn from_pkcs1_der(private_key: &[u8]) -> Result<Self> {
163-
let private_key = OctetStringRef::new(private_key)?;
164-
Ok(Self::try_from(pkcs8::PrivateKeyInfoRef {
165-
algorithm: ALGORITHM_ID,
166-
private_key,
167-
public_key: None,
168-
})?)
169-
}
170-
}
171-
172-
#[cfg(feature = "pkcs8")]
173-
impl<T> DecodeRsaPublicKey for T
174-
where
175-
T: for<'a> TryFrom<pkcs8::SubjectPublicKeyInfoRef<'a>, Error = spki::Error>,
176-
{
177-
fn from_pkcs1_der(public_key: &[u8]) -> Result<Self> {
178-
Ok(Self::try_from(pkcs8::SubjectPublicKeyInfoRef {
179-
algorithm: ALGORITHM_ID,
180-
subject_public_key: BitStringRef::from_bytes(public_key)?,
181-
})?)
182-
}
183-
}
184-
185-
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
186-
impl<T: pkcs8::EncodePrivateKey> EncodeRsaPrivateKey for T {
187-
fn to_pkcs1_der(&self) -> Result<SecretDocument> {
188-
let pkcs8_doc = self.to_pkcs8_der()?;
189-
let pkcs8_key = pkcs8::PrivateKeyInfoRef::from_der(pkcs8_doc.as_bytes())?;
190-
pkcs8_key.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;
191-
RsaPrivateKey::from_der(pkcs8_key.private_key.as_bytes())?.try_into()
192-
}
193-
}
194-
195-
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
196-
impl<T: pkcs8::EncodePublicKey> EncodeRsaPublicKey for T {
197-
fn to_pkcs1_der(&self) -> Result<Document> {
198-
let doc = self.to_public_key_der()?;
199-
let spki = pkcs8::SubjectPublicKeyInfoRef::from_der(doc.as_bytes())?;
200-
spki.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;
201-
RsaPublicKey::from_der(spki.subject_public_key.raw_bytes())?.try_into()
202-
}
203-
}

sec1/Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ rust-version = "1.85"
2020
base16ct = { version = "0.2", optional = true, default-features = false }
2121
der = { version = "0.8.0-rc.6", optional = true, features = ["oid"] }
2222
hybrid-array = { version = "0.3", optional = true, default-features = false }
23-
pkcs8 = { version = "0.11.0-rc.5", optional = true, default-features = false }
2423
serdect = { version = "0.3", optional = true, default-features = false, features = ["alloc"] }
2524
subtle = { version = "2", optional = true, default-features = false }
2625
zeroize = { version = "1", optional = true, default-features = false }
@@ -31,11 +30,11 @@ tempfile = "3"
3130

3231
[features]
3332
default = ["der", "point"]
34-
alloc = ["der?/alloc", "pkcs8?/alloc", "zeroize?/alloc"]
33+
alloc = ["der?/alloc", "zeroize?/alloc"]
3534
std = ["alloc", "der?/std"]
3635

3736
der = ["dep:der", "zeroize"]
38-
pem = ["alloc", "der/pem", "pkcs8/pem"]
37+
pem = ["alloc", "der/pem"]
3938
point = ["dep:base16ct", "dep:hybrid-array"]
4039
serde = ["dep:serdect"]
4140
zeroize = ["dep:zeroize", "der?/zeroize"]

sec1/src/error.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ pub enum Error {
2424
/// a number expected to be a prime was not a prime.
2525
Crypto,
2626

27-
/// PKCS#8 errors.
28-
#[cfg(feature = "pkcs8")]
29-
Pkcs8(pkcs8::Error),
30-
3127
/// Errors relating to the `Elliptic-Curve-Point-to-Octet-String` or
3228
/// `Octet-String-to-Elliptic-Curve-Point` encodings.
3329
PointEncoding,
@@ -44,8 +40,6 @@ impl fmt::Display for Error {
4440
#[cfg(feature = "der")]
4541
Error::Asn1(err) => write!(f, "SEC1 ASN.1 error: {err}"),
4642
Error::Crypto => f.write_str("SEC1 cryptographic error"),
47-
#[cfg(feature = "pkcs8")]
48-
Error::Pkcs8(err) => write!(f, "{err}"),
4943
Error::PointEncoding => f.write_str("elliptic curve point encoding error"),
5044
Error::Version => f.write_str("SEC1 version error"),
5145
}
@@ -65,17 +59,3 @@ impl From<pem::Error> for Error {
6559
der::Error::from(err).into()
6660
}
6761
}
68-
69-
#[cfg(feature = "pkcs8")]
70-
impl From<pkcs8::Error> for Error {
71-
fn from(err: pkcs8::Error) -> Error {
72-
Error::Pkcs8(err)
73-
}
74-
}
75-
76-
#[cfg(feature = "pkcs8")]
77-
impl From<pkcs8::spki::Error> for Error {
78-
fn from(err: pkcs8::spki::Error) -> Error {
79-
Error::Pkcs8(pkcs8::Error::PublicKey(err))
80-
}
81-
}

sec1/src/lib.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,14 @@ pub use crate::traits::EncodeEcPrivateKey;
6060
#[cfg(feature = "pem")]
6161
pub use der::pem::{self, LineEnding};
6262

63-
#[cfg(feature = "pkcs8")]
64-
pub use pkcs8;
65-
66-
#[cfg(feature = "pkcs8")]
67-
use pkcs8::ObjectIdentifier;
63+
#[cfg(feature = "der")]
64+
use der::asn1::ObjectIdentifier;
6865

6966
#[cfg(all(doc, feature = "serde"))]
7067
use serdect::serde;
7168

72-
/// Algorithm [`ObjectIdentifier`] for elliptic curve public key cryptography
73-
/// (`id-ecPublicKey`).
69+
/// Algorithm [`ObjectIdentifier`] for elliptic curve public key cryptography (`id-ecPublicKey`).
7470
///
7571
/// <http://oid-info.com/get/1.2.840.10045.2.1>
76-
#[cfg(feature = "pkcs8")]
72+
#[cfg(feature = "der")]
7773
pub const ALGORITHM_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.2.1");

sec1/src/traits.rs

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,11 @@ use der::SecretDocument;
88
#[cfg(feature = "pem")]
99
use {crate::LineEnding, alloc::string::String, der::pem::PemLabel};
1010

11-
#[cfg(feature = "pkcs8")]
12-
use {
13-
crate::{ALGORITHM_OID, EcPrivateKey},
14-
der::{Decode, asn1::OctetStringRef},
15-
};
16-
1711
#[cfg(feature = "std")]
1812
use std::path::Path;
1913

2014
#[cfg(feature = "pem")]
21-
use zeroize::Zeroizing;
15+
use {crate::EcPrivateKey, zeroize::Zeroizing};
2216

2317
/// Parse an [`EcPrivateKey`] from a SEC1-encoded document.
2418
pub trait DecodeEcPrivateKey: Sized {
@@ -84,41 +78,3 @@ pub trait EncodeEcPrivateKey {
8478
Ok(doc.write_pem_file(path, EcPrivateKey::PEM_LABEL, line_ending)?)
8579
}
8680
}
87-
88-
#[cfg(feature = "pkcs8")]
89-
impl<T> DecodeEcPrivateKey for T
90-
where
91-
T: for<'a> TryFrom<pkcs8::PrivateKeyInfoRef<'a>, Error = pkcs8::Error>,
92-
{
93-
fn from_sec1_der(private_key: &[u8]) -> Result<Self> {
94-
let params_oid = EcPrivateKey::from_der(private_key)?
95-
.parameters
96-
.and_then(|params| params.named_curve());
97-
98-
let algorithm = pkcs8::AlgorithmIdentifierRef {
99-
oid: ALGORITHM_OID,
100-
parameters: params_oid.as_ref().map(Into::into),
101-
};
102-
103-
let private_key = OctetStringRef::new(private_key)?;
104-
105-
Ok(Self::try_from(pkcs8::PrivateKeyInfoRef {
106-
algorithm,
107-
private_key,
108-
public_key: None,
109-
})?)
110-
}
111-
}
112-
113-
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
114-
impl<T: pkcs8::EncodePrivateKey> EncodeEcPrivateKey for T {
115-
fn to_sec1_der(&self) -> Result<SecretDocument> {
116-
let doc = self.to_pkcs8_der()?;
117-
let pkcs8_key = pkcs8::PrivateKeyInfoRef::from_der(doc.as_bytes())?;
118-
pkcs8_key.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;
119-
120-
let mut pkcs1_key = EcPrivateKey::from_der(pkcs8_key.private_key.as_bytes())?;
121-
pkcs1_key.parameters = Some(pkcs8_key.algorithm.parameters_oid()?.into());
122-
pkcs1_key.try_into()
123-
}
124-
}

0 commit comments

Comments
 (0)