Skip to content

Commit 25b9e19

Browse files
committed
spki: make key param an attribute of spki
1 parent 1efe27a commit 25b9e19

File tree

6 files changed

+65
-38
lines changed

6 files changed

+65
-38
lines changed

der/src/asn1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ mod videotex_string;
2727

2828
pub use self::{
2929
any::AnyRef,
30-
bit_string::{BitStringIter, BitStringRef},
30+
bit_string::{BitStringIter, BitStringLike, BitStringRef},
3131
choice::Choice,
3232
context_specific::{ContextSpecific, ContextSpecificRef},
3333
generalized_time::GeneralizedTime,

der/src/asn1/bit_string.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! ASN.1 `BIT STRING` support.
22
33
use crate::{
4-
asn1::AnyRef, ByteSlice, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, Header,
5-
Length, Reader, Result, Tag, ValueOrd, Writer,
4+
asn1::AnyRef, ByteSlice, Decode, DecodeValue, DerOrd, Encode, EncodeValue, Error, ErrorKind,
5+
FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, Writer,
66
};
77
use core::{cmp::Ordering, iter::FusedIterator};
88

@@ -153,8 +153,8 @@ impl ValueOrd for BitStringRef<'_> {
153153
}
154154
}
155155

156-
impl<'a> From<&BitStringRef<'a>> for BitStringRef<'a> {
157-
fn from(value: &BitStringRef<'a>) -> BitStringRef<'a> {
156+
impl<'a, 'k> From<&'k BitStringRef<'a>> for BitStringRef<'a> {
157+
fn from(value: &'k BitStringRef<'a>) -> BitStringRef<'a> {
158158
*value
159159
}
160160
}
@@ -441,6 +441,18 @@ where
441441
}
442442
}
443443

444+
/// Trait used as a marker to ensure the type can hold the content of a Bit String
445+
pub trait BitStringLike<'pointer, 'slice: 'pointer>
446+
where
447+
Self: Decode<'slice> + Encode + FixedTag + 'pointer,
448+
{
449+
}
450+
451+
impl<'slice: 'pointer, 'pointer> BitStringLike<'pointer, 'slice> for BitStringRef<'slice> {}
452+
453+
#[cfg(feature = "alloc")]
454+
impl<'a> BitStringLike<'a, 'a> for BitString {}
455+
444456
#[cfg(test)]
445457
mod tests {
446458
use super::{BitStringRef, Result, Tag};

pkcs1/src/traits.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use {
1818
#[cfg(feature = "pkcs8")]
1919
use {
2020
crate::{ALGORITHM_ID, ALGORITHM_OID},
21-
der::asn1::BitString,
21+
der::asn1::BitStringRef,
2222
};
2323

2424
#[cfg(feature = "std")]
@@ -188,7 +188,7 @@ impl<T: pkcs8::DecodePublicKey> DecodeRsaPublicKey for T {
188188
fn from_pkcs1_der(public_key: &[u8]) -> Result<Self> {
189189
Ok(Self::try_from(pkcs8::SubjectPublicKeyInfoRef {
190190
algorithm: ALGORITHM_ID,
191-
subject_public_key: BitString::from_bytes(public_key)?,
191+
subject_public_key: BitStringRef::from_bytes(public_key)?,
192192
})?)
193193
}
194194
}

spki/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ pub use crate::{
4949
pub use der::{self, asn1::ObjectIdentifier};
5050

5151
#[cfg(feature = "alloc")]
52-
pub use {crate::traits::EncodePublicKey, der::Document};
52+
pub use {
53+
crate::{spki::SubjectPublicKeyInfoOwned, traits::EncodePublicKey},
54+
der::Document,
55+
};
5356

5457
#[cfg(feature = "fingerprint")]
5558
pub use crate::fingerprint::FingerprintBytes;

spki/src/spki.rs

+38-26
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
use crate::{AlgorithmIdentifier, Error, Result};
44
use core::cmp::Ordering;
55
use der::{
6-
asn1::{AnyRef, BitString, BitStringRef},
6+
asn1::{AnyRef, BitStringLike, BitStringRef},
77
Choice, Decode, DecodeValue, DerOrd, Encode, Header, Reader, Sequence, ValueOrd,
88
};
99

1010
#[cfg(feature = "alloc")]
11-
use der::Document;
11+
use der::{
12+
asn1::{Any, BitString},
13+
Document,
14+
};
1215

1316
#[cfg(feature = "fingerprint")]
1417
use crate::{fingerprint, FingerprintBytes};
@@ -22,8 +25,12 @@ use {
2225
#[cfg(feature = "pem")]
2326
use der::pem::PemLabel;
2427

25-
/// [`SubjectPublicKeyInfo`] with [`AnyRef`] algorithm parameters.
26-
pub type SubjectPublicKeyInfoRef<'a> = SubjectPublicKeyInfo<AnyRef<'a>>;
28+
/// [`SubjectPublicKeyInfo`] with [`AnyRef`] algorithm parameters, and [`BitStringRef`] params.
29+
pub type SubjectPublicKeyInfoRef<'a> = SubjectPublicKeyInfo<AnyRef<'a>, BitStringRef<'a>>;
30+
31+
/// [`SubjectPublicKeyInfo`] with [`Any`] algorithm parameters, and [`BitString`] params.
32+
#[cfg(feature = "alloc")]
33+
pub type SubjectPublicKeyInfoOwned = SubjectPublicKeyInfo<Any, BitString>;
2734

2835
/// X.509 `SubjectPublicKeyInfo` (SPKI) as defined in [RFC 5280 § 4.1.2.7].
2936
///
@@ -38,24 +45,19 @@ pub type SubjectPublicKeyInfoRef<'a> = SubjectPublicKeyInfo<AnyRef<'a>>;
3845
///
3946
/// [RFC 5280 § 4.1.2.7]: https://tools.ietf.org/html/rfc5280#section-4.1.2.7
4047
#[derive(Clone, Debug, Eq, PartialEq)]
41-
pub struct SubjectPublicKeyInfo<Params> {
48+
pub struct SubjectPublicKeyInfo<Params, Key> {
4249
/// X.509 [`AlgorithmIdentifier`] for the public key type
4350
pub algorithm: AlgorithmIdentifier<Params>,
4451

4552
/// Public key data
46-
pub subject_public_key: BitString,
47-
}
48-
49-
impl<Params> SubjectPublicKeyInfo<Params> {
50-
/// Get a [`BitString`] representing the `subject_public_key`
51-
fn bitstring(&self) -> BitStringRef<'_> {
52-
BitStringRef::from(&self.subject_public_key)
53-
}
53+
pub subject_public_key: Key,
5454
}
5555

56-
impl<'a, Params> SubjectPublicKeyInfo<Params>
56+
impl<'a: 'k, 'k, Params, Key: 'k> SubjectPublicKeyInfo<Params, Key>
5757
where
5858
Params: Choice<'a> + Encode,
59+
Key: BitStringLike<'k, 'a>,
60+
BitStringRef<'a>: From<&'k Key>,
5961
{
6062
/// Calculate the SHA-256 fingerprint of this [`SubjectPublicKeyInfo`] and
6163
/// encode it as a Base64 string.
@@ -84,35 +86,40 @@ where
8486
}
8587
}
8688

87-
impl<'a, Params> DecodeValue<'a> for SubjectPublicKeyInfo<Params>
89+
impl<'a: 'k, 'k, Params, Key: 'k> DecodeValue<'a> for SubjectPublicKeyInfo<Params, Key>
8890
where
8991
Params: Choice<'a> + Encode,
92+
Key: Decode<'a>,
9093
{
9194
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
9295
reader.read_nested(header.length, |reader| {
9396
Ok(Self {
9497
algorithm: reader.decode()?,
95-
subject_public_key: BitString::decode(reader)?,
98+
subject_public_key: Key::decode(reader)?,
9699
})
97100
})
98101
}
99102
}
100103

101-
impl<'a, Params> Sequence<'a> for SubjectPublicKeyInfo<Params>
104+
impl<'a: 'k, 'k, Params, Key: 'k> Sequence<'a> for SubjectPublicKeyInfo<Params, Key>
102105
where
103106
Params: Choice<'a> + Encode,
107+
Key: BitStringLike<'k, 'a>,
108+
BitStringRef<'a>: From<&'k Key>,
104109
{
105110
fn fields<F, T>(&self, f: F) -> der::Result<T>
106111
where
107112
F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
108113
{
109-
f(&[&self.algorithm, &self.bitstring()])
114+
f(&[&self.algorithm, &self.subject_public_key])
110115
}
111116
}
112117

113-
impl<'a, Params> TryFrom<&'a [u8]> for SubjectPublicKeyInfo<Params>
118+
impl<'a: 'k, 'k, Params, Key: 'k> TryFrom<&'a [u8]> for SubjectPublicKeyInfo<Params, Key>
114119
where
115120
Params: Choice<'a> + Encode,
121+
Key: BitStringLike<'k, 'a>,
122+
BitStringRef<'a>: From<&'k Key>,
116123
{
117124
type Error = Error;
118125

@@ -121,46 +128,51 @@ where
121128
}
122129
}
123130

124-
impl<'a, Params> ValueOrd for SubjectPublicKeyInfo<Params>
131+
impl<'a, Params, Key> ValueOrd for SubjectPublicKeyInfo<Params, Key>
125132
where
126133
Params: Choice<'a> + DerOrd + Encode,
134+
Key: ValueOrd,
127135
{
128136
fn value_cmp(&self, other: &Self) -> der::Result<Ordering> {
129137
match self.algorithm.der_cmp(&other.algorithm)? {
130-
Ordering::Equal => self.bitstring().der_cmp(&other.bitstring()),
138+
Ordering::Equal => self.subject_public_key.value_cmp(&other.subject_public_key),
131139
other => Ok(other),
132140
}
133141
}
134142
}
135143

136144
#[cfg(feature = "alloc")]
137145
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
138-
impl<'a, Params> TryFrom<SubjectPublicKeyInfo<Params>> for Document
146+
impl<'a: 'k, 'k, Params, Key: 'k> TryFrom<SubjectPublicKeyInfo<Params, Key>> for Document
139147
where
140148
Params: Choice<'a> + Encode,
149+
Key: BitStringLike<'k, 'a>,
150+
BitStringRef<'a>: From<&'k Key>,
141151
{
142152
type Error = Error;
143153

144-
fn try_from(spki: SubjectPublicKeyInfo<Params>) -> Result<Document> {
154+
fn try_from(spki: SubjectPublicKeyInfo<Params, Key>) -> Result<Document> {
145155
Self::try_from(&spki)
146156
}
147157
}
148158

149159
#[cfg(feature = "alloc")]
150160
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
151-
impl<'a, Params> TryFrom<&SubjectPublicKeyInfo<Params>> for Document
161+
impl<'a: 'k, 'k, Params, Key: 'k> TryFrom<&SubjectPublicKeyInfo<Params, Key>> for Document
152162
where
153163
Params: Choice<'a> + Encode,
164+
Key: BitStringLike<'k, 'a>,
165+
BitStringRef<'a>: From<&'k Key>,
154166
{
155167
type Error = Error;
156168

157-
fn try_from(spki: &SubjectPublicKeyInfo<Params>) -> Result<Document> {
169+
fn try_from(spki: &SubjectPublicKeyInfo<Params, Key>) -> Result<Document> {
158170
Ok(Self::encode_msg(spki)?)
159171
}
160172
}
161173

162174
#[cfg(feature = "pem")]
163175
#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
164-
impl<Params> PemLabel for SubjectPublicKeyInfo<Params> {
176+
impl<Params, Key> PemLabel for SubjectPublicKeyInfo<Params, Key> {
165177
const PEM_LABEL: &'static str = "PUBLIC KEY";
166178
}

spki/tests/spki.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ fn decode_ec_p256_der() {
5555
"1.2.840.10045.3.1.7".parse().unwrap()
5656
);
5757

58-
assert_eq!(spki.subject_public_key, &hex!("041CACFFB55F2F2CEFD89D89EB374B2681152452802DEEA09916068137D839CF7FC481A44492304D7EF66AC117BEFE83A8D08F155F2B52F9F618DD447029048E0F")[..]);
58+
assert_eq!(spki.subject_public_key.raw_bytes(), &hex!("041CACFFB55F2F2CEFD89D89EB374B2681152452802DEEA09916068137D839CF7FC481A44492304D7EF66AC117BEFE83A8D08F155F2B52F9F618DD447029048E0F")[..]);
5959
}
6060

6161
#[test]
@@ -67,7 +67,7 @@ fn decode_ed25519_and_fingerprint_spki() {
6767
assert_eq!(spki.algorithm.oid, "1.3.101.112".parse().unwrap());
6868
assert_eq!(spki.algorithm.parameters, None);
6969
assert_eq!(
70-
spki.subject_public_key,
70+
spki.subject_public_key.raw_bytes(),
7171
&hex!("4D29167F3F1912A6F7ADFA293A051A15C05EC67B8F17267B1C5550DCE853BD0D")[..]
7272
);
7373

@@ -87,7 +87,7 @@ fn decode_ed25519_and_fingerprint_base64() {
8787
assert_eq!(spki.algorithm.oid, "1.3.101.112".parse().unwrap());
8888
assert_eq!(spki.algorithm.parameters, None);
8989
assert_eq!(
90-
spki.subject_public_key,
90+
spki.subject_public_key.raw_bytes(),
9191
&hex!("4D29167F3F1912A6F7ADFA293A051A15C05EC67B8F17267B1C5550DCE853BD0D")[..]
9292
);
9393

@@ -104,7 +104,7 @@ fn decode_rsa_2048_der() {
104104

105105
assert_eq!(spki.algorithm.oid, "1.2.840.113549.1.1.1".parse().unwrap());
106106
assert!(spki.algorithm.parameters.unwrap().is_null());
107-
assert_eq!(spki.subject_public_key, &hex!("3082010A0282010100B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F0203010001")[..]);
107+
assert_eq!(spki.subject_public_key.raw_bytes(), &hex!("3082010A0282010100B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F0203010001")[..]);
108108
}
109109

110110
#[test]

0 commit comments

Comments
 (0)