Skip to content

Commit 311879a

Browse files
authored
Remove PKCS#8 blanket impls for PKCS#1 traits (#538)
Companion PR to RustCrypto/formats#1927 which properly composes the PKCS#8 impl in terms of the PKCS#1 impl
1 parent d7315e4 commit 311879a

File tree

4 files changed

+125
-70
lines changed

4 files changed

+125
-70
lines changed

Cargo.lock

Lines changed: 9 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ subtle = { version = "2.6.1", default-features = false }
2323
zeroize = { version = "1.5", features = ["alloc"] }
2424

2525
# optional dependencies
26-
pkcs1 = { version = "0.8.0-rc.2", optional = true, default-features = false, features = ["alloc", "pem", "pkcs8"] }
26+
pkcs1 = { version = "0.8.0-rc.2", optional = true, default-features = false, features = ["alloc", "pem"] }
2727
pkcs8 = { version = "0.11.0-rc.4", optional = true, default-features = false, features = ["alloc", "pem"] }
2828
serdect = { version = "0.3.0", optional = true }
2929
sha1 = { version = "0.11.0-rc.0", optional = true, default-features = false, features = ["oid"] }
@@ -68,3 +68,6 @@ opt-level = 2
6868

6969
[profile.bench]
7070
debug = true
71+
72+
[patch.crates-io]
73+
pkcs1 = { git = "https://github.com/RustCrypto/formats/" }

src/encoding.rs

Lines changed: 112 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -12,56 +12,48 @@ use crate::{
1212
use core::convert::{TryFrom, TryInto};
1313
use crypto_bigint::{BoxedUint, NonZero, Resize};
1414
use pkcs8::{
15-
der::{asn1::OctetStringRef, Encode},
15+
der::{asn1::OctetStringRef, Decode},
1616
Document, EncodePrivateKey, EncodePublicKey, ObjectIdentifier, SecretDocument,
1717
};
1818
use zeroize::Zeroizing;
1919

2020
/// ObjectID for the RSA PSS keys
2121
pub const ID_RSASSA_PSS: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10");
2222

23-
/// Verify that the `AlgorithmIdentifier` for a key is correct.
24-
pub(crate) fn verify_algorithm_id(algorithm: &pkcs8::AlgorithmIdentifierRef) -> spki::Result<()> {
25-
match algorithm.oid {
26-
pkcs1::ALGORITHM_OID => {
27-
if algorithm.parameters_any()? != pkcs8::der::asn1::Null.into() {
28-
return Err(spki::Error::KeyMalformed);
29-
}
30-
}
31-
ID_RSASSA_PSS => {
32-
if algorithm.parameters.is_some() {
33-
return Err(spki::Error::KeyMalformed);
34-
}
35-
}
36-
_ => return Err(spki::Error::OidUnknown { oid: algorithm.oid }),
37-
};
23+
// PKCS#1
3824

39-
Ok(())
25+
fn uint_from_slice(data: &[u8], bits: u32) -> pkcs1::Result<BoxedUint> {
26+
BoxedUint::from_be_slice(data, bits).map_err(|_| pkcs1::Error::KeyMalformed)
4027
}
4128

42-
fn uint_from_slice(data: &[u8], bits: u32) -> pkcs8::Result<BoxedUint> {
43-
BoxedUint::from_be_slice(data, bits).map_err(|_| pkcs8::Error::KeyMalformed)
29+
impl pkcs1::DecodeRsaPrivateKey for RsaPrivateKey {
30+
fn from_pkcs1_der(bytes: &[u8]) -> pkcs1::Result<Self> {
31+
pkcs1::RsaPrivateKey::from_der(bytes)?.try_into()
32+
}
4433
}
4534

46-
impl TryFrom<pkcs8::PrivateKeyInfoRef<'_>> for RsaPrivateKey {
47-
type Error = pkcs8::Error;
35+
impl pkcs1::DecodeRsaPublicKey for RsaPublicKey {
36+
fn from_pkcs1_der(bytes: &[u8]) -> pkcs1::Result<Self> {
37+
pkcs1::RsaPublicKey::from_der(bytes)?.try_into()
38+
}
39+
}
4840

49-
fn try_from(private_key_info: pkcs8::PrivateKeyInfoRef<'_>) -> pkcs8::Result<Self> {
50-
use pkcs8::Error::KeyMalformed;
51-
verify_algorithm_id(&private_key_info.algorithm)?;
41+
impl TryFrom<pkcs1::RsaPrivateKey<'_>> for RsaPrivateKey {
42+
type Error = pkcs1::Error;
5243

53-
let pkcs1_key = pkcs1::RsaPrivateKey::try_from(private_key_info.private_key)?;
44+
fn try_from(pkcs1_key: pkcs1::RsaPrivateKey<'_>) -> pkcs1::Result<RsaPrivateKey> {
45+
use pkcs1::Error::KeyMalformed;
5446

5547
// Multi-prime RSA keys not currently supported
5648
if pkcs1_key.version() != pkcs1::Version::TwoPrime {
57-
return Err(pkcs1::Error::Version.into());
49+
return Err(pkcs1::Error::Version);
5850
}
5951

6052
let bits = u32::try_from(pkcs1_key.modulus.as_bytes().len()).map_err(|_| KeyMalformed)? * 8;
6153

6254
let n = uint_from_slice(pkcs1_key.modulus.as_bytes(), bits)?;
6355
let bits_e = u32::try_from(pkcs1_key.public_exponent.as_bytes().len())
64-
.map_err(|_| KeyMalformed)?
56+
.map_err(|_| pkcs1::Error::KeyMalformed)?
6557
* 8;
6658
let e = uint_from_slice(pkcs1_key.public_exponent.as_bytes(), bits_e)?;
6759
let e = Option::from(e).ok_or(KeyMalformed)?;
@@ -75,16 +67,11 @@ impl TryFrom<pkcs8::PrivateKeyInfoRef<'_>> for RsaPrivateKey {
7567
}
7668
}
7769

78-
impl TryFrom<pkcs8::SubjectPublicKeyInfoRef<'_>> for RsaPublicKey {
79-
type Error = spki::Error;
80-
81-
fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> spki::Result<Self> {
82-
use spki::Error::KeyMalformed;
83-
84-
verify_algorithm_id(&spki.algorithm)?;
70+
impl TryFrom<pkcs1::RsaPublicKey<'_>> for RsaPublicKey {
71+
type Error = pkcs1::Error;
8572

86-
let pkcs1_key =
87-
pkcs1::RsaPublicKey::try_from(spki.subject_public_key.as_bytes().ok_or(KeyMalformed)?)?;
73+
fn try_from(pkcs1_key: pkcs1::RsaPublicKey<'_>) -> pkcs1::Result<Self> {
74+
use pkcs1::Error::KeyMalformed;
8875

8976
let bits = u32::try_from(pkcs1_key.modulus.as_bytes().len()).map_err(|_| KeyMalformed)? * 8;
9077
let n = uint_from_slice(pkcs1_key.modulus.as_bytes(), bits)?;
@@ -98,11 +85,11 @@ impl TryFrom<pkcs8::SubjectPublicKeyInfoRef<'_>> for RsaPublicKey {
9885
}
9986
}
10087

101-
impl EncodePrivateKey for RsaPrivateKey {
102-
fn to_pkcs8_der(&self) -> pkcs8::Result<SecretDocument> {
88+
impl pkcs1::EncodeRsaPrivateKey for RsaPrivateKey {
89+
fn to_pkcs1_der(&self) -> pkcs1::Result<SecretDocument> {
10390
// Check if the key is multi prime
10491
if self.primes.len() > 2 {
105-
return Err(pkcs1::Error::Version.into());
92+
return Err(pkcs1::Error::Crypto);
10693
}
10794

10895
let modulus = self.n().to_be_bytes();
@@ -134,7 +121,7 @@ impl EncodePrivateKey for RsaPrivateKey {
134121
.to_be_bytes(),
135122
);
136123

137-
let private_key = pkcs1::RsaPrivateKey {
124+
Ok(SecretDocument::encode_msg(&pkcs1::RsaPrivateKey {
138125
modulus: pkcs1::UintRef::new(&modulus)?,
139126
public_exponent: pkcs1::UintRef::new(&public_exponent)?,
140127
private_exponent: pkcs1::UintRef::new(&private_exponent)?,
@@ -144,27 +131,86 @@ impl EncodePrivateKey for RsaPrivateKey {
144131
exponent2: pkcs1::UintRef::new(&exponent2)?,
145132
coefficient: pkcs1::UintRef::new(&coefficient)?,
146133
other_prime_infos: None,
134+
})?)
135+
}
136+
}
137+
138+
impl pkcs1::EncodeRsaPublicKey for RsaPublicKey {
139+
fn to_pkcs1_der(&self) -> pkcs1::Result<Document> {
140+
let modulus = self.n().to_be_bytes();
141+
let public_exponent = self.e().to_be_bytes();
142+
143+
Ok(Document::encode_msg(&pkcs1::RsaPublicKey {
144+
modulus: pkcs1::UintRef::new(&modulus)?,
145+
public_exponent: pkcs1::UintRef::new(&public_exponent)?,
146+
})?)
147+
}
148+
}
149+
150+
// PKCS#8
151+
152+
/// Verify that the `AlgorithmIdentifier` for a key is correct.
153+
pub(crate) fn verify_algorithm_id(algorithm: &spki::AlgorithmIdentifierRef) -> spki::Result<()> {
154+
match algorithm.oid {
155+
pkcs1::ALGORITHM_OID => {
156+
if algorithm.parameters_any()? != pkcs8::der::asn1::Null.into() {
157+
return Err(spki::Error::KeyMalformed);
158+
}
159+
}
160+
ID_RSASSA_PSS => {
161+
if algorithm.parameters.is_some() {
162+
return Err(spki::Error::KeyMalformed);
163+
}
147164
}
148-
.to_der()?;
165+
_ => return Err(spki::Error::OidUnknown { oid: algorithm.oid }),
166+
};
167+
168+
Ok(())
169+
}
170+
171+
impl TryFrom<pkcs8::PrivateKeyInfoRef<'_>> for RsaPrivateKey {
172+
type Error = pkcs8::Error;
173+
174+
fn try_from(private_key_info: pkcs8::PrivateKeyInfoRef<'_>) -> pkcs8::Result<Self> {
175+
verify_algorithm_id(&private_key_info.algorithm)?;
176+
177+
pkcs1::RsaPrivateKey::try_from(private_key_info.private_key)
178+
.and_then(TryInto::try_into)
179+
.map_err(pkcs1_error_to_pkcs8)
180+
}
181+
}
182+
183+
impl TryFrom<pkcs8::SubjectPublicKeyInfoRef<'_>> for RsaPublicKey {
184+
type Error = spki::Error;
185+
186+
fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> spki::Result<Self> {
187+
use spki::Error::KeyMalformed;
188+
189+
verify_algorithm_id(&spki.algorithm)?;
190+
191+
pkcs1::RsaPublicKey::try_from(spki.subject_public_key.as_bytes().ok_or(KeyMalformed)?)
192+
.and_then(TryInto::try_into)
193+
.map_err(pkcs1_error_to_spki)
194+
}
195+
}
196+
197+
impl EncodePrivateKey for RsaPrivateKey {
198+
fn to_pkcs8_der(&self) -> pkcs8::Result<SecretDocument> {
199+
let private_key =
200+
pkcs1::EncodeRsaPrivateKey::to_pkcs1_der(self).map_err(pkcs1_error_to_pkcs8)?;
149201

150202
pkcs8::PrivateKeyInfoRef::new(
151203
pkcs1::ALGORITHM_ID,
152-
OctetStringRef::new(private_key.as_ref())?,
204+
OctetStringRef::new(private_key.as_bytes())?,
153205
)
154206
.try_into()
155207
}
156208
}
157209

158210
impl EncodePublicKey for RsaPublicKey {
159211
fn to_public_key_der(&self) -> spki::Result<Document> {
160-
let modulus = self.n().to_be_bytes();
161-
let public_exponent = self.e().to_be_bytes();
162-
163-
let subject_public_key = pkcs1::RsaPublicKey {
164-
modulus: pkcs1::UintRef::new(&modulus)?,
165-
public_exponent: pkcs1::UintRef::new(&public_exponent)?,
166-
}
167-
.to_der()?;
212+
let subject_public_key =
213+
pkcs1::EncodeRsaPublicKey::to_pkcs1_der(self).map_err(pkcs1_error_to_spki)?;
168214

169215
pkcs8::SubjectPublicKeyInfoRef {
170216
algorithm: pkcs1::ALGORITHM_ID,
@@ -176,3 +222,19 @@ impl EncodePublicKey for RsaPublicKey {
176222
.try_into()
177223
}
178224
}
225+
226+
/// Convert `pkcs1::Result` to `pkcs8::Result`.
227+
fn pkcs1_error_to_pkcs8(error: pkcs1::Error) -> pkcs8::Error {
228+
match error {
229+
pkcs1::Error::Asn1(e) => pkcs8::Error::Asn1(e),
230+
_ => pkcs8::Error::KeyMalformed,
231+
}
232+
}
233+
234+
/// Convert `pkcs1::Result` to `spki::Result`.
235+
fn pkcs1_error_to_spki(error: pkcs1::Error) -> spki::Error {
236+
match error {
237+
pkcs1::Error::Asn1(e) => spki::Error::Asn1(e),
238+
_ => spki::Error::KeyMalformed,
239+
}
240+
}

src/errors.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,16 +130,8 @@ impl From<crypto_bigint::DecodeError> for Error {
130130
}
131131
}
132132

133-
#[cfg(feature = "std")]
134133
impl From<Error> for signature::Error {
135134
fn from(err: Error) -> Self {
136135
Self::from_source(err)
137136
}
138137
}
139-
140-
#[cfg(not(feature = "std"))]
141-
impl From<Error> for signature::Error {
142-
fn from(_err: Error) -> Self {
143-
Self::new()
144-
}
145-
}

0 commit comments

Comments
 (0)