aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Walbran <qwandor@google.com>2023-12-19 15:48:03 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-12-19 15:48:03 +0000
commitd7946f9cd47e451c5537d6af2810147cca7d8061 (patch)
treea987a8ff806ac1245c717d8db937fde45321c833
parent3df3407340e8690bb66055632d75c05065fec9a8 (diff)
parentc57198c400a0aa00ce012db2b0593a7b24a02721 (diff)
downloadpkcs1-d7946f9cd47e451c5537d6af2810147cca7d8061.tar.gz
Revert^2 "Upgrade pkcs1 to 0.7.5" am: 3262afcb03 am: fbe2cf2ee6 am: c57198c400
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/pkcs1/+/2881162 Change-Id: I29b5a9e43ebac375ae786c22a15aa9f3df79405d Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp10
-rw-r--r--CHANGELOG.md52
-rw-r--r--Cargo.toml24
-rw-r--r--Cargo.toml.orig20
-rw-r--r--LICENSE-MIT2
-rw-r--r--METADATA21
-rw-r--r--README.md4
-rw-r--r--src/lib.rs20
-rw-r--r--src/params.rs314
-rw-r--r--src/private_key.rs93
-rw-r--r--src/private_key/other_prime_info.rs29
-rw-r--r--src/public_key.rs29
-rw-r--r--src/traits.rs53
-rw-r--r--src/version.rs2
-rw-r--r--tests/params.rs137
16 files changed, 513 insertions, 299 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 8acf345..5350233 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
{
"git": {
- "sha1": "40fbcf36aa1d1e20685424576da37b7df0279d3b"
+ "sha1": "750ae946d284810f582a9c9ad428549561b1ee03"
},
"path_in_vcs": "pkcs1"
} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index ce274cc..51289d5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -35,19 +35,16 @@ rust_library_host {
name: "libpkcs1",
crate_name: "pkcs1",
cargo_env_compat: true,
- cargo_pkg_version: "0.4.1",
+ cargo_pkg_version: "0.7.5",
srcs: ["src/lib.rs"],
edition: "2021",
features: [
"alloc",
- "pkcs8",
"zeroize",
],
rustlibs: [
"libder",
- "libpkcs8",
"libspki",
- "libzeroize",
],
}
@@ -55,19 +52,16 @@ rust_library_rlib {
name: "libpkcs1_nostd",
crate_name: "pkcs1",
cargo_env_compat: true,
- cargo_pkg_version: "0.4.1",
+ cargo_pkg_version: "0.7.5",
srcs: ["src/lib.rs"],
edition: "2021",
features: [
"alloc",
- "pkcs8",
"zeroize",
],
rustlibs: [
"libder_nostd",
- "libpkcs8_nostd",
"libspki_nostd",
- "libzeroize_nostd",
],
apex_available: [
"//apex_available:platform",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7e95122..e6b79c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,58 @@ 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.7.5 (2023-04-24)
+### Fixed
+- Import failure ([#1021])
+
+[#1021]: https://github.com/RustCrypto/formats/pull/1021
+
+## 0.7.4 (2023-04-21)
+### Changed
+- Have `alloc` feature only weakly activate `pkcs8?/alloc` ([#1013])
+- Have `pem` feature only weakly activate `pkcs8?/pem` ([#1013])
+
+[#1013]: https://github.com/RustCrypto/formats/pull/1013
+
+## 0.7.3 (2023-04-18)
+### Added
+- Provide functions to construct `RsaPss` and `RsaOaepParams` ([#1010])
+
+### Changed
+- Use `NULL` parameters for SHA `AlgorithmIdentifier`s ([#1010])
+
+[#1010]: https://github.com/RustCrypto/formats/pull/1010
+
+## 0.7.2 (2023-04-04)
+### Added
+- `RsaPssParams::SALT_LEN_DEFAULT` ([#953])
+
+[#953]: https://github.com/RustCrypto/formats/pull/953
+
+## 0.7.1 (2023-03-05)
+### Fixed
+- `DecodeRsaPublicKey` blanket impl ([#916])
+
+[#916]: https://github.com/RustCrypto/formats/pull/916
+
+## 0.7.0 (2023-02-26) [YANKED]
+### Changed
+- Make PSS/OAEP params use generic `AlgorithmIdentifier` ([#799])
+- Bump `der` dependency to v0.7 ([#899])
+- Bump `spki` dependency to v0.7 ([#900])
+- Bump `pkcs8` to v0.10 ([#902])
+
+[#799]: https://github.com/RustCrypto/formats/pull/799
+[#899]: https://github.com/RustCrypto/formats/pull/899
+[#900]: https://github.com/RustCrypto/formats/pull/900
+[#902]: https://github.com/RustCrypto/formats/pull/902
+
+## 0.6.0 (Skipped)
+- Skipped to synchronize version number with `der` and `spki`
+
+## 0.5.0 (Skipped)
+- Skipped to synchronize version number with `der` and `spki`
+
## 0.4.1 (2022-10-10)
### Added
- `RsaPssParams` support ([#698])
diff --git a/Cargo.toml b/Cargo.toml
index b73c625..4365648 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.57"
+rust-version = "1.60"
name = "pkcs1"
-version = "0.4.1"
+version = "0.7.5"
authors = ["RustCrypto Developers"]
description = """
Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #1:
@@ -45,28 +45,23 @@ rustdoc-args = [
]
[dependencies.der]
-version = "0.6"
+version = "0.7"
features = ["oid"]
[dependencies.pkcs8]
-version = "0.9"
+version = "0.10"
optional = true
default-features = false
[dependencies.spki]
-version = "0.6"
-
-[dependencies.zeroize]
-version = "1"
-optional = true
-default-features = false
+version = "0.7"
[dev-dependencies.const-oid]
version = "0.9"
features = ["db"]
[dev-dependencies.hex-literal]
-version = "0.3"
+version = "0.4"
[dev-dependencies.tempfile]
version = "3"
@@ -74,15 +69,16 @@ version = "3"
[features]
alloc = [
"der/alloc",
- "pkcs8/alloc",
- "zeroize/alloc",
+ "zeroize",
+ "pkcs8?/alloc",
]
pem = [
"alloc",
"der/pem",
- "pkcs8/pem",
+ "pkcs8?/pem",
]
std = [
"der/std",
"alloc",
]
+zeroize = ["der/zeroize"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index fb1fa3f..cdc15b4 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "pkcs1"
-version = "0.4.1"
+version = "0.7.5"
description = """
Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #1:
RSA Cryptography Specifications Version 2.2 (RFC 8017)
@@ -12,24 +12,24 @@ categories = ["cryptography", "data-structures", "encoding", "no-std", "parser-i
keywords = ["crypto", "key", "pem", "pkcs", "rsa"]
readme = "README.md"
edition = "2021"
-rust-version = "1.57"
+rust-version = "1.60"
[dependencies]
-der = { version = "0.6", features = ["oid"], path = "../der" }
-spki = { version = "0.6", path = "../spki" }
+der = { version = "0.7", features = ["oid"] }
+spki = { version = "0.7" }
# optional dependencies
-pkcs8 = { version = "0.9", optional = true, default-features = false, path = "../pkcs8" }
-zeroize = { version = "1", optional = true, default-features = false }
+pkcs8 = { version = "0.10", optional = true, default-features = false }
[dev-dependencies]
-hex-literal = "0.3"
+const-oid = { version = "0.9", features = ["db"] } # TODO: path = "../const-oid"
+hex-literal = "0.4"
tempfile = "3"
-const-oid = { version = "0.9", path = "../const-oid", features = ["db"] }
[features]
-alloc = ["der/alloc", "pkcs8/alloc", "zeroize/alloc"]
-pem = ["alloc", "der/pem", "pkcs8/pem"]
+zeroize = ["der/zeroize"]
+alloc = ["der/alloc", "zeroize", "pkcs8?/alloc"]
+pem = ["alloc", "der/pem", "pkcs8?/pem"]
std = ["der/std", "alloc"]
[package.metadata.docs.rs]
diff --git a/LICENSE-MIT b/LICENSE-MIT
index 68ddaa3..3294d74 100644
--- a/LICENSE-MIT
+++ b/LICENSE-MIT
@@ -1,4 +1,4 @@
-Copyright (c) 2021-2022 The RustCrypto Project Developers
+Copyright (c) 2021-2023 The RustCrypto Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
diff --git a/METADATA b/METADATA
index 51c2998..434f1c5 100644
--- a/METADATA
+++ b/METADATA
@@ -1,23 +1,20 @@
# This project was upgraded with external_updater.
# Usage: tools/external_updater/updater.sh update rust/crates/pkcs1
-# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
name: "pkcs1"
description: "Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.2 (RFC 8017)."
third_party {
- url {
- type: HOMEPAGE
- value: "https://crates.io/crates/pkcs1"
- }
- url {
- type: ARCHIVE
- value: "https://static.crates.io/crates/pkcs1/pkcs1-0.4.1.crate"
- }
- version: "0.4.1"
license_type: NOTICE
last_upgrade_date {
- year: 2022
+ year: 2023
month: 12
- day: 13
+ day: 15
+ }
+ homepage: "https://crates.io/crates/pkcs1"
+ identifier {
+ type: "Archive"
+ value: "https://static.crates.io/crates/pkcs1/pkcs1-0.7.5.crate"
+ version: "0.7.5"
}
}
diff --git a/README.md b/README.md
index 8342e20..597a1b2 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ PEM encoded RSA public keys begin with:
## 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.
@@ -58,7 +58,7 @@ dual licensed as above, without any additional terms or conditions.
[docs-image]: https://docs.rs/pkcs1/badge.svg
[docs-link]: https://docs.rs/pkcs1/
[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/pkcs1/badge.svg?branch=master&event=push
diff --git a/src/lib.rs b/src/lib.rs
index 9176c8d..e389cab 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,12 +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/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
+)]
/// Local Android change: Use std to allow building as a dylib.
#[cfg(android_dylib)]
@@ -26,7 +33,7 @@ mod version;
pub use der::{
self,
- asn1::{ObjectIdentifier, UIntRef},
+ asn1::{ObjectIdentifier, UintRef},
};
pub use crate::{
@@ -45,18 +52,15 @@ pub use crate::{
};
#[cfg(feature = "pem")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
pub use der::pem::{self, LineEnding};
/// `rsaEncryption` Object Identifier (OID)
#[cfg(feature = "pkcs8")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
pub const ALGORITHM_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1");
/// `AlgorithmIdentifier` for RSA.
#[cfg(feature = "pkcs8")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
-pub const ALGORITHM_ID: pkcs8::AlgorithmIdentifier<'static> = pkcs8::AlgorithmIdentifier {
+pub const ALGORITHM_ID: pkcs8::AlgorithmIdentifierRef<'static> = pkcs8::AlgorithmIdentifierRef {
oid: ALGORITHM_OID,
parameters: Some(der::asn1::AnyRef::NULL),
};
diff --git a/src/params.rs b/src/params.rs
index e803473..74a1ee4 100644
--- a/src/params.rs
+++ b/src/params.rs
@@ -1,27 +1,23 @@
//! PKCS#1 RSA parameters.
use crate::{Error, Result};
-use der::asn1::{AnyRef, ObjectIdentifier};
use der::{
- asn1::ContextSpecificRef, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Reader, Sequence,
- Tag, TagMode, TagNumber, Writer,
+ asn1::{AnyRef, ContextSpecificRef, ObjectIdentifier},
+ oid::AssociatedOid,
+ Decode, DecodeValue, Encode, EncodeValue, FixedTag, Length, Reader, Sequence, Tag, TagMode,
+ TagNumber, Writer,
};
-use spki::AlgorithmIdentifier;
+use spki::{AlgorithmIdentifier, AlgorithmIdentifierRef};
const OID_SHA_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26");
const OID_MGF_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.8");
const OID_PSPECIFIED: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.9");
-// TODO(tarcieri): make `AlgorithmIdentifier` generic around params; use `OID_SHA_1`
-const SEQ_OID_SHA_1_DER: &[u8] = &[0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a];
-
-const SHA_1_AI: AlgorithmIdentifier<'_> = AlgorithmIdentifier {
+const SHA_1_AI: AlgorithmIdentifierRef<'_> = AlgorithmIdentifierRef {
oid: OID_SHA_1,
- parameters: None,
+ parameters: Some(AnyRef::NULL),
};
-const SALT_LEN_DEFAULT: u8 = 20;
-
/// `TrailerField` as defined in [RFC 8017 Appendix 2.3].
/// ```text
/// TrailerField ::= INTEGER { trailerFieldBC(1) }
@@ -50,11 +46,11 @@ impl<'a> DecodeValue<'a> for TrailerField {
}
impl EncodeValue for TrailerField {
- fn value_len(&self) -> der::Result<der::Length> {
- Ok(der::Length::ONE)
+ fn value_len(&self) -> der::Result<Length> {
+ Ok(Length::ONE)
}
- fn encode_value(&self, writer: &mut dyn Writer) -> der::Result<()> {
+ fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
(*self as u8).encode_value(writer)
}
}
@@ -81,10 +77,10 @@ impl FixedTag for TrailerField {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RsaPssParams<'a> {
/// Hash Algorithm
- pub hash: AlgorithmIdentifier<'a>,
+ pub hash: AlgorithmIdentifierRef<'a>,
/// Mask Generation Function (MGF)
- pub mask_gen: AlgorithmIdentifier<'a>,
+ pub mask_gen: AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>,
/// Salt length
pub salt_len: u8,
@@ -93,12 +89,89 @@ pub struct RsaPssParams<'a> {
pub trailer_field: TrailerField,
}
+impl<'a> RsaPssParams<'a> {
+ /// Default RSA PSS Salt length in RsaPssParams
+ pub const SALT_LEN_DEFAULT: u8 = 20;
+
+ /// Create new RsaPssParams for the provided digest and salt len
+ pub fn new<D>(salt_len: u8) -> Self
+ where
+ D: AssociatedOid,
+ {
+ Self {
+ hash: AlgorithmIdentifierRef {
+ oid: D::OID,
+ parameters: Some(AnyRef::NULL),
+ },
+ mask_gen: AlgorithmIdentifier {
+ oid: OID_MGF_1,
+ parameters: Some(AlgorithmIdentifierRef {
+ oid: D::OID,
+ parameters: Some(AnyRef::NULL),
+ }),
+ },
+ salt_len,
+ trailer_field: Default::default(),
+ }
+ }
+
+ fn context_specific_hash(&self) -> Option<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
+ if self.hash == SHA_1_AI {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N0,
+ tag_mode: TagMode::Explicit,
+ value: &self.hash,
+ })
+ }
+ }
+
+ fn context_specific_mask_gen(
+ &self,
+ ) -> Option<ContextSpecificRef<'_, AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>>> {
+ if self.mask_gen == default_mgf1_sha1() {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N1,
+ tag_mode: TagMode::Explicit,
+ value: &self.mask_gen,
+ })
+ }
+ }
+
+ fn context_specific_salt_len(&self) -> Option<ContextSpecificRef<'_, u8>> {
+ if self.salt_len == RsaPssParams::SALT_LEN_DEFAULT {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N2,
+ tag_mode: TagMode::Explicit,
+ value: &self.salt_len,
+ })
+ }
+ }
+
+ fn context_specific_trailer_field(&self) -> Option<ContextSpecificRef<'_, TrailerField>> {
+ if self.trailer_field == TrailerField::default() {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N3,
+ tag_mode: TagMode::Explicit,
+ value: &self.trailer_field,
+ })
+ }
+ }
+}
+
impl<'a> Default for RsaPssParams<'a> {
fn default() -> Self {
Self {
hash: SHA_1_AI,
mask_gen: default_mgf1_sha1(),
- salt_len: SALT_LEN_DEFAULT,
+ salt_len: RsaPssParams::SALT_LEN_DEFAULT,
trailer_field: Default::default(),
}
}
@@ -116,7 +189,7 @@ impl<'a> DecodeValue<'a> for RsaPssParams<'a> {
.unwrap_or_else(default_mgf1_sha1),
salt_len: reader
.context_specific(TagNumber::N2, TagMode::Explicit)?
- .unwrap_or(SALT_LEN_DEFAULT),
+ .unwrap_or(RsaPssParams::SALT_LEN_DEFAULT),
trailer_field: reader
.context_specific(TagNumber::N3, TagMode::Explicit)?
.unwrap_or_default(),
@@ -125,52 +198,25 @@ impl<'a> DecodeValue<'a> for RsaPssParams<'a> {
}
}
-impl<'a> Sequence<'a> for RsaPssParams<'a> {
- fn fields<F, T>(&self, f: F) -> der::Result<T>
- where
- F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
- {
- f(&[
- &if self.hash == SHA_1_AI {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N0,
- tag_mode: TagMode::Explicit,
- value: &self.hash,
- })
- },
- &if self.mask_gen == default_mgf1_sha1() {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N1,
- tag_mode: TagMode::Explicit,
- value: &self.mask_gen,
- })
- },
- &if self.salt_len == SALT_LEN_DEFAULT {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N2,
- tag_mode: TagMode::Explicit,
- value: &self.salt_len,
- })
- },
- &if self.trailer_field == TrailerField::default() {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N3,
- tag_mode: TagMode::Explicit,
- value: &self.trailer_field,
- })
- },
- ])
+impl EncodeValue for RsaPssParams<'_> {
+ fn value_len(&self) -> der::Result<Length> {
+ self.context_specific_hash().encoded_len()?
+ + self.context_specific_mask_gen().encoded_len()?
+ + self.context_specific_salt_len().encoded_len()?
+ + self.context_specific_trailer_field().encoded_len()?
+ }
+
+ fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
+ self.context_specific_hash().encode(writer)?;
+ self.context_specific_mask_gen().encode(writer)?;
+ self.context_specific_salt_len().encode(writer)?;
+ self.context_specific_trailer_field().encode(writer)?;
+ Ok(())
}
}
+impl<'a> Sequence<'a> for RsaPssParams<'a> {}
+
impl<'a> TryFrom<&'a [u8]> for RsaPssParams<'a> {
type Error = Error;
@@ -180,13 +226,10 @@ impl<'a> TryFrom<&'a [u8]> for RsaPssParams<'a> {
}
/// Default Mask Generation Function (MGF): SHA-1.
-fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<'a> {
- AlgorithmIdentifier {
+fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<AlgorithmIdentifierRef<'a>> {
+ AlgorithmIdentifier::<AlgorithmIdentifierRef<'a>> {
oid: OID_MGF_1,
- parameters: Some(
- AnyRef::new(Tag::Sequence, SEQ_OID_SHA_1_DER)
- .expect("error creating default MGF1 params"),
- ),
+ parameters: Some(SHA_1_AI),
}
}
@@ -208,13 +251,84 @@ fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<'a> {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RsaOaepParams<'a> {
/// Hash Algorithm
- pub hash: AlgorithmIdentifier<'a>,
+ pub hash: AlgorithmIdentifierRef<'a>,
/// Mask Generation Function (MGF)
- pub mask_gen: AlgorithmIdentifier<'a>,
+ pub mask_gen: AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>,
/// The source (and possibly the value) of the label L
- pub p_source: AlgorithmIdentifier<'a>,
+ pub p_source: AlgorithmIdentifierRef<'a>,
+}
+
+impl<'a> RsaOaepParams<'a> {
+ /// Create new RsaPssParams for the provided digest and default (empty) label
+ pub fn new<D>() -> Self
+ where
+ D: AssociatedOid,
+ {
+ Self::new_with_label::<D>(&[])
+ }
+
+ /// Create new RsaPssParams for the provided digest and specified label
+ pub fn new_with_label<D>(label: &'a impl AsRef<[u8]>) -> Self
+ where
+ D: AssociatedOid,
+ {
+ Self {
+ hash: AlgorithmIdentifierRef {
+ oid: D::OID,
+ parameters: Some(AnyRef::NULL),
+ },
+ mask_gen: AlgorithmIdentifier {
+ oid: OID_MGF_1,
+ parameters: Some(AlgorithmIdentifierRef {
+ oid: D::OID,
+ parameters: Some(AnyRef::NULL),
+ }),
+ },
+ p_source: pspecicied_algorithm_identifier(label),
+ }
+ }
+
+ fn context_specific_hash(&self) -> Option<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
+ if self.hash == SHA_1_AI {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N0,
+ tag_mode: TagMode::Explicit,
+ value: &self.hash,
+ })
+ }
+ }
+
+ fn context_specific_mask_gen(
+ &self,
+ ) -> Option<ContextSpecificRef<'_, AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>>> {
+ if self.mask_gen == default_mgf1_sha1() {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N1,
+ tag_mode: TagMode::Explicit,
+ value: &self.mask_gen,
+ })
+ }
+ }
+
+ fn context_specific_p_source(
+ &self,
+ ) -> Option<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
+ if self.p_source == default_pempty_string() {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N2,
+ tag_mode: TagMode::Explicit,
+ value: &self.p_source,
+ })
+ }
+ }
}
impl<'a> Default for RsaOaepParams<'a> {
@@ -245,43 +359,23 @@ impl<'a> DecodeValue<'a> for RsaOaepParams<'a> {
}
}
-impl<'a> Sequence<'a> for RsaOaepParams<'a> {
- fn fields<F, T>(&self, f: F) -> der::Result<T>
- where
- F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
- {
- f(&[
- &if self.hash == SHA_1_AI {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N0,
- tag_mode: TagMode::Explicit,
- value: &self.hash,
- })
- },
- &if self.mask_gen == default_mgf1_sha1() {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N1,
- tag_mode: TagMode::Explicit,
- value: &self.mask_gen,
- })
- },
- &if self.p_source == default_pempty_string() {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N2,
- tag_mode: TagMode::Explicit,
- value: &self.p_source,
- })
- },
- ])
+impl EncodeValue for RsaOaepParams<'_> {
+ fn value_len(&self) -> der::Result<Length> {
+ self.context_specific_hash().encoded_len()?
+ + self.context_specific_mask_gen().encoded_len()?
+ + self.context_specific_p_source().encoded_len()?
+ }
+
+ fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
+ self.context_specific_hash().encode(writer)?;
+ self.context_specific_mask_gen().encode(writer)?;
+ self.context_specific_p_source().encode(writer)?;
+ Ok(())
}
}
+impl<'a> Sequence<'a> for RsaOaepParams<'a> {}
+
impl<'a> TryFrom<&'a [u8]> for RsaOaepParams<'a> {
type Error = Error;
@@ -290,12 +384,16 @@ impl<'a> TryFrom<&'a [u8]> for RsaOaepParams<'a> {
}
}
-/// Default Source Algorithm, empty string
-fn default_pempty_string<'a>() -> AlgorithmIdentifier<'a> {
- AlgorithmIdentifier {
+fn pspecicied_algorithm_identifier(label: &impl AsRef<[u8]>) -> AlgorithmIdentifierRef<'_> {
+ AlgorithmIdentifierRef {
oid: OID_PSPECIFIED,
parameters: Some(
- AnyRef::new(Tag::OctetString, &[]).expect("error creating default OAEP params"),
+ AnyRef::new(Tag::OctetString, label.as_ref()).expect("error creating OAEP params"),
),
}
}
+
+/// Default Source Algorithm, empty string
+fn default_pempty_string<'a>() -> AlgorithmIdentifierRef<'a> {
+ pspecicied_algorithm_identifier(&[])
+}
diff --git a/src/private_key.rs b/src/private_key.rs
index 043ed02..b913c47 100644
--- a/src/private_key.rs
+++ b/src/private_key.rs
@@ -5,7 +5,10 @@ pub(crate) mod other_prime_info;
use crate::{Error, Result, RsaPublicKey, Version};
use core::fmt;
-use der::{asn1::UIntRef, Decode, DecodeValue, Encode, Header, Reader, Sequence, Tag};
+use der::{
+ asn1::UintRef, Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, Tag,
+ Writer,
+};
#[cfg(feature = "alloc")]
use {self::other_prime_info::OtherPrimeInfo, alloc::vec::Vec, der::SecretDocument};
@@ -39,28 +42,28 @@ use der::pem::PemLabel;
#[derive(Clone)]
pub struct RsaPrivateKey<'a> {
/// `n`: RSA modulus.
- pub modulus: UIntRef<'a>,
+ pub modulus: UintRef<'a>,
/// `e`: RSA public exponent.
- pub public_exponent: UIntRef<'a>,
+ pub public_exponent: UintRef<'a>,
/// `d`: RSA private exponent.
- pub private_exponent: UIntRef<'a>,
+ pub private_exponent: UintRef<'a>,
/// `p`: first prime factor of `n`.
- pub prime1: UIntRef<'a>,
+ pub prime1: UintRef<'a>,
/// `q`: Second prime factor of `n`.
- pub prime2: UIntRef<'a>,
+ pub prime2: UintRef<'a>,
/// First exponent: `d mod (p-1)`.
- pub exponent1: UIntRef<'a>,
+ pub exponent1: UintRef<'a>,
/// Second exponent: `d mod (q-1)`.
- pub exponent2: UIntRef<'a>,
+ pub exponent2: UintRef<'a>,
/// CRT coefficient: `(inverse of q) mod p`.
- pub coefficient: UIntRef<'a>,
+ pub coefficient: UintRef<'a>,
/// Additional primes `r_3`, ..., `r_u`, in order, if this is a multi-prime
/// RSA key (i.e. `version` is `multi`).
@@ -116,27 +119,37 @@ impl<'a> DecodeValue<'a> for RsaPrivateKey<'a> {
}
}
-impl<'a> Sequence<'a> for RsaPrivateKey<'a> {
- fn fields<F, T>(&self, f: F) -> der::Result<T>
- where
- F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
- {
- f(&[
- &self.version(),
- &self.modulus,
- &self.public_exponent,
- &self.private_exponent,
- &self.prime1,
- &self.prime2,
- &self.exponent1,
- &self.exponent2,
- &self.coefficient,
- #[cfg(feature = "alloc")]
- &self.other_prime_infos,
- ])
+impl EncodeValue for RsaPrivateKey<'_> {
+ fn value_len(&self) -> der::Result<Length> {
+ self.version().encoded_len()?
+ + self.modulus.encoded_len()?
+ + self.public_exponent.encoded_len()?
+ + self.private_exponent.encoded_len()?
+ + self.prime1.encoded_len()?
+ + self.prime2.encoded_len()?
+ + self.exponent1.encoded_len()?
+ + self.exponent2.encoded_len()?
+ + self.coefficient.encoded_len()?
+ + self.other_prime_infos.encoded_len()?
+ }
+
+ fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
+ self.version().encode(writer)?;
+ self.modulus.encode(writer)?;
+ self.public_exponent.encode(writer)?;
+ self.private_exponent.encode(writer)?;
+ self.prime1.encode(writer)?;
+ self.prime2.encode(writer)?;
+ self.exponent1.encode(writer)?;
+ self.exponent2.encode(writer)?;
+ self.coefficient.encode(writer)?;
+ self.other_prime_infos.encode(writer)?;
+ Ok(())
}
}
+impl<'a> Sequence<'a> for RsaPrivateKey<'a> {}
+
impl<'a> From<RsaPrivateKey<'a>> for RsaPublicKey<'a> {
fn from(private_key: RsaPrivateKey<'a>) -> RsaPublicKey<'a> {
private_key.public_key()
@@ -168,7 +181,6 @@ impl fmt::Debug for RsaPrivateKey<'_> {
}
#[cfg(feature = "alloc")]
-#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl TryFrom<RsaPrivateKey<'_>> for SecretDocument {
type Error = Error;
@@ -178,7 +190,6 @@ impl TryFrom<RsaPrivateKey<'_>> for SecretDocument {
}
#[cfg(feature = "alloc")]
-#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl TryFrom<&RsaPrivateKey<'_>> for SecretDocument {
type Error = Error;
@@ -188,12 +199,13 @@ impl TryFrom<&RsaPrivateKey<'_>> for SecretDocument {
}
#[cfg(feature = "pem")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
impl PemLabel for RsaPrivateKey<'_> {
const PEM_LABEL: &'static str = "RSA PRIVATE KEY";
}
/// Placeholder struct for `OtherPrimeInfos` in the no-`alloc` case.
+///
+/// This type is unconstructable by design, but supports the same traits.
#[cfg(not(feature = "alloc"))]
#[derive(Clone)]
#[non_exhaustive]
@@ -202,15 +214,30 @@ pub struct OtherPrimeInfos<'a> {
}
#[cfg(not(feature = "alloc"))]
-impl<'a> Decode<'a> for OtherPrimeInfos<'a> {
- fn decode<R: Reader<'a>>(reader: &mut R) -> der::Result<Self> {
+impl<'a> DecodeValue<'a> for OtherPrimeInfos<'a> {
+ fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
// Placeholder decoder that always returns an error.
- // Use `Tag::Integer` to signal an unsupported version.
+ // Uses `Tag::Integer` to signal an unsupported version.
Err(reader.error(der::ErrorKind::Value { tag: Tag::Integer }))
}
}
#[cfg(not(feature = "alloc"))]
+impl EncodeValue for OtherPrimeInfos<'_> {
+ fn value_len(&self) -> der::Result<Length> {
+ // Placeholder decoder that always returns an error.
+ // Uses `Tag::Integer` to signal an unsupported version.
+ Err(der::ErrorKind::Value { tag: Tag::Integer }.into())
+ }
+
+ fn encode_value(&self, _writer: &mut impl Writer) -> der::Result<()> {
+ // Placeholder decoder that always returns an error.
+ // Uses `Tag::Integer` to signal an unsupported version.
+ Err(der::ErrorKind::Value { tag: Tag::Integer }.into())
+ }
+}
+
+#[cfg(not(feature = "alloc"))]
impl<'a> der::FixedTag for OtherPrimeInfos<'a> {
const TAG: Tag = Tag::Sequence;
}
diff --git a/src/private_key/other_prime_info.rs b/src/private_key/other_prime_info.rs
index 8980aa1..35194a5 100644
--- a/src/private_key/other_prime_info.rs
+++ b/src/private_key/other_prime_info.rs
@@ -1,6 +1,8 @@
//! PKCS#1 OtherPrimeInfo support.
-use der::{asn1::UIntRef, DecodeValue, Encode, Header, Reader, Sequence};
+use der::{
+ asn1::UintRef, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, Writer,
+};
/// PKCS#1 OtherPrimeInfo as defined in [RFC 8017 Appendix 1.2].
///
@@ -16,16 +18,15 @@ use der::{asn1::UIntRef, DecodeValue, Encode, Header, Reader, Sequence};
///
/// [RFC 8017 Appendix 1.2]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.1.2
#[derive(Clone)]
-#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub struct OtherPrimeInfo<'a> {
/// Prime factor `r_i` of `n`, where `i` >= 3.
- pub prime: UIntRef<'a>,
+ pub prime: UintRef<'a>,
/// Exponent: `d_i = d mod (r_i - 1)`.
- pub exponent: UIntRef<'a>,
+ pub exponent: UintRef<'a>,
/// CRT coefficient: `t_i = (r_1 * r_2 * ... * r_(i-1))^(-1) mod r_i`.
- pub coefficient: UIntRef<'a>,
+ pub coefficient: UintRef<'a>,
}
impl<'a> DecodeValue<'a> for OtherPrimeInfo<'a> {
@@ -40,11 +41,17 @@ impl<'a> DecodeValue<'a> for OtherPrimeInfo<'a> {
}
}
-impl<'a> Sequence<'a> for OtherPrimeInfo<'a> {
- fn fields<F, T>(&self, f: F) -> der::Result<T>
- where
- F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
- {
- f(&[&self.prime, &self.exponent, &self.coefficient])
+impl EncodeValue for OtherPrimeInfo<'_> {
+ fn value_len(&self) -> der::Result<Length> {
+ self.prime.encoded_len()? + self.exponent.encoded_len()? + self.coefficient.encoded_len()?
+ }
+
+ fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
+ self.prime.encode(writer)?;
+ self.exponent.encode(writer)?;
+ self.coefficient.encode(writer)?;
+ Ok(())
}
}
+
+impl<'a> Sequence<'a> for OtherPrimeInfo<'a> {}
diff --git a/src/public_key.rs b/src/public_key.rs
index b6b8c87..3281744 100644
--- a/src/public_key.rs
+++ b/src/public_key.rs
@@ -1,7 +1,10 @@
//! PKCS#1 RSA Public Keys.
use crate::{Error, Result};
-use der::{asn1::UIntRef, Decode, DecodeValue, Encode, Header, Reader, Sequence};
+use der::{
+ asn1::UintRef, Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence,
+ Writer,
+};
#[cfg(feature = "alloc")]
use der::Document;
@@ -24,10 +27,10 @@ use der::pem::PemLabel;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct RsaPublicKey<'a> {
/// `n`: RSA modulus
- pub modulus: UIntRef<'a>,
+ pub modulus: UintRef<'a>,
/// `e`: RSA public exponent
- pub public_exponent: UIntRef<'a>,
+ pub public_exponent: UintRef<'a>,
}
impl<'a> DecodeValue<'a> for RsaPublicKey<'a> {
@@ -41,15 +44,20 @@ impl<'a> DecodeValue<'a> for RsaPublicKey<'a> {
}
}
-impl<'a> Sequence<'a> for RsaPublicKey<'a> {
- fn fields<F, T>(&self, f: F) -> der::Result<T>
- where
- F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
- {
- f(&[&self.modulus, &self.public_exponent])
+impl EncodeValue for RsaPublicKey<'_> {
+ fn value_len(&self) -> der::Result<Length> {
+ self.modulus.encoded_len()? + self.public_exponent.encoded_len()?
+ }
+
+ fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
+ self.modulus.encode(writer)?;
+ self.public_exponent.encode(writer)?;
+ Ok(())
}
}
+impl<'a> Sequence<'a> for RsaPublicKey<'a> {}
+
impl<'a> TryFrom<&'a [u8]> for RsaPublicKey<'a> {
type Error = Error;
@@ -59,7 +67,6 @@ impl<'a> TryFrom<&'a [u8]> for RsaPublicKey<'a> {
}
#[cfg(feature = "alloc")]
-#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl TryFrom<RsaPublicKey<'_>> for Document {
type Error = Error;
@@ -69,7 +76,6 @@ impl TryFrom<RsaPublicKey<'_>> for Document {
}
#[cfg(feature = "alloc")]
-#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl TryFrom<&RsaPublicKey<'_>> for Document {
type Error = Error;
@@ -79,7 +85,6 @@ impl TryFrom<&RsaPublicKey<'_>> for Document {
}
#[cfg(feature = "pem")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
impl PemLabel for RsaPublicKey<'_> {
const PEM_LABEL: &'static str = "RSA PUBLIC KEY";
}
diff --git a/src/traits.rs b/src/traits.rs
index c70820c..cd3d04e 100644
--- a/src/traits.rs
+++ b/src/traits.rs
@@ -3,10 +3,7 @@
use crate::Result;
#[cfg(feature = "alloc")]
-use {
- crate::{RsaPrivateKey, RsaPublicKey},
- der::SecretDocument,
-};
+use der::{Document, SecretDocument};
#[cfg(feature = "pem")]
use {
@@ -16,13 +13,19 @@ use {
};
#[cfg(feature = "pkcs8")]
-use crate::{ALGORITHM_ID, ALGORITHM_OID};
+use {
+ crate::{ALGORITHM_ID, ALGORITHM_OID},
+ der::asn1::BitStringRef,
+};
#[cfg(feature = "std")]
use std::path::Path;
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
-use der::{Decode, Document};
+use der::Decode;
+
+#[cfg(all(feature = "alloc", any(feature = "pem", feature = "pkcs8")))]
+use crate::{RsaPrivateKey, RsaPublicKey};
/// Parse an [`RsaPrivateKey`] from a PKCS#1-encoded document.
pub trait DecodeRsaPrivateKey: Sized {
@@ -38,7 +41,6 @@ pub trait DecodeRsaPrivateKey: Sized {
/// -----BEGIN RSA PRIVATE KEY-----
/// ```
#[cfg(feature = "pem")]
- #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
fn from_pkcs1_pem(s: &str) -> Result<Self> {
let (label, doc) = SecretDocument::from_pem(s)?;
RsaPrivateKey::validate_pem_label(label)?;
@@ -48,15 +50,12 @@ pub trait DecodeRsaPrivateKey: Sized {
/// Load PKCS#1 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_pkcs1_der_file(path: impl AsRef<Path>) -> Result<Self> {
Self::from_pkcs1_der(SecretDocument::read_der_file(path)?.as_bytes())
}
/// Load PKCS#1 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_pkcs1_pem_file(path: impl AsRef<Path>) -> Result<Self> {
let (label, doc) = SecretDocument::read_pem_file(path)?;
RsaPrivateKey::validate_pem_label(&label)?;
@@ -78,7 +77,6 @@ pub trait DecodeRsaPublicKey: Sized {
/// -----BEGIN RSA PUBLIC KEY-----
/// ```
#[cfg(feature = "pem")]
- #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
fn from_pkcs1_pem(s: &str) -> Result<Self> {
let (label, doc) = Document::from_pem(s)?;
RsaPublicKey::validate_pem_label(label)?;
@@ -88,7 +86,6 @@ pub trait DecodeRsaPublicKey: Sized {
/// Load [`RsaPublicKey`] 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_pkcs1_der_file(path: impl AsRef<Path>) -> Result<Self> {
let doc = Document::read_der_file(path)?;
Self::from_pkcs1_der(doc.as_bytes())
@@ -96,8 +93,6 @@ pub trait DecodeRsaPublicKey: Sized {
/// Load [`RsaPublicKey`] 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_pkcs1_pem_file(path: impl AsRef<Path>) -> Result<Self> {
let (label, doc) = Document::read_pem_file(path)?;
RsaPublicKey::validate_pem_label(&label)?;
@@ -107,14 +102,12 @@ pub trait DecodeRsaPublicKey: Sized {
/// Serialize a [`RsaPrivateKey`] to a PKCS#1 encoded document.
#[cfg(feature = "alloc")]
-#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub trait EncodeRsaPrivateKey {
/// Serialize a [`SecretDocument`] containing a PKCS#1-encoded private key.
fn to_pkcs1_der(&self) -> Result<SecretDocument>;
/// Serialize this private key as PEM-encoded PKCS#1 with the given [`LineEnding`].
#[cfg(feature = "pem")]
- #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
fn to_pkcs1_pem(&self, line_ending: LineEnding) -> Result<Zeroizing<String>> {
let doc = self.to_pkcs1_der()?;
Ok(doc.to_pem(RsaPrivateKey::PEM_LABEL, line_ending)?)
@@ -122,14 +115,12 @@ pub trait EncodeRsaPrivateKey {
/// Write ASN.1 DER-encoded PKCS#1 private key to the given path.
#[cfg(feature = "std")]
- #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
fn write_pkcs1_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
Ok(self.to_pkcs1_der()?.write_der_file(path)?)
}
/// Write ASN.1 DER-encoded PKCS#1 private key to the given path.
#[cfg(all(feature = "pem", feature = "std"))]
- #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))]
fn write_pkcs1_pem_file(&self, path: impl AsRef<Path>, line_ending: LineEnding) -> Result<()> {
let doc = self.to_pkcs1_der()?;
Ok(doc.write_pem_file(path, RsaPrivateKey::PEM_LABEL, line_ending)?)
@@ -138,14 +129,12 @@ pub trait EncodeRsaPrivateKey {
/// Serialize a [`RsaPublicKey`] to a PKCS#1-encoded document.
#[cfg(feature = "alloc")]
-#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub trait EncodeRsaPublicKey {
/// Serialize a [`Document`] containing a PKCS#1-encoded public key.
fn to_pkcs1_der(&self) -> Result<Document>;
/// Serialize this public key as PEM-encoded PKCS#1 with the given line ending.
#[cfg(feature = "pem")]
- #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
fn to_pkcs1_pem(&self, line_ending: LineEnding) -> Result<String> {
let doc = self.to_pkcs1_der()?;
Ok(doc.to_pem(RsaPublicKey::PEM_LABEL, line_ending)?)
@@ -153,14 +142,12 @@ pub trait EncodeRsaPublicKey {
/// Write ASN.1 DER-encoded public key to the given path.
#[cfg(feature = "std")]
- #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
fn write_pkcs1_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
Ok(self.to_pkcs1_der()?.write_der_file(path)?)
}
/// Write ASN.1 DER-encoded public key to the given path.
#[cfg(all(feature = "pem", feature = "std"))]
- #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))]
fn write_pkcs1_pem_file(&self, path: impl AsRef<Path>, line_ending: LineEnding) -> Result<()> {
let doc = self.to_pkcs1_der()?;
Ok(doc.write_pem_file(path, RsaPublicKey::PEM_LABEL, line_ending)?)
@@ -168,8 +155,10 @@ pub trait EncodeRsaPublicKey {
}
#[cfg(feature = "pkcs8")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
-impl<T: pkcs8::DecodePrivateKey> DecodeRsaPrivateKey for T {
+impl<T> DecodeRsaPrivateKey for T
+where
+ T: for<'a> TryFrom<pkcs8::PrivateKeyInfo<'a>, Error = pkcs8::Error>,
+{
fn from_pkcs1_der(private_key: &[u8]) -> Result<Self> {
Ok(Self::try_from(pkcs8::PrivateKeyInfo {
algorithm: ALGORITHM_ID,
@@ -180,18 +169,19 @@ impl<T: pkcs8::DecodePrivateKey> DecodeRsaPrivateKey for T {
}
#[cfg(feature = "pkcs8")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
-impl<T: pkcs8::DecodePublicKey> DecodeRsaPublicKey for T {
+impl<T> DecodeRsaPublicKey for T
+where
+ T: for<'a> TryFrom<pkcs8::SubjectPublicKeyInfoRef<'a>, Error = pkcs8::spki::Error>,
+{
fn from_pkcs1_der(public_key: &[u8]) -> Result<Self> {
- Ok(Self::try_from(pkcs8::SubjectPublicKeyInfo {
+ Ok(Self::try_from(pkcs8::SubjectPublicKeyInfoRef {
algorithm: ALGORITHM_ID,
- subject_public_key: public_key,
+ subject_public_key: BitStringRef::from_bytes(public_key)?,
})?)
}
}
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "pkcs8"))))]
impl<T: pkcs8::EncodePrivateKey> EncodeRsaPrivateKey for T {
fn to_pkcs1_der(&self) -> Result<SecretDocument> {
let pkcs8_doc = self.to_pkcs8_der()?;
@@ -202,12 +192,11 @@ impl<T: pkcs8::EncodePrivateKey> EncodeRsaPrivateKey for T {
}
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "pkcs8"))))]
impl<T: pkcs8::EncodePublicKey> EncodeRsaPublicKey for T {
fn to_pkcs1_der(&self) -> Result<Document> {
let doc = self.to_public_key_der()?;
- let spki = pkcs8::SubjectPublicKeyInfo::from_der(doc.as_bytes())?;
+ let spki = pkcs8::SubjectPublicKeyInfoRef::from_der(doc.as_bytes())?;
spki.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;
- RsaPublicKey::from_der(spki.subject_public_key)?.try_into()
+ RsaPublicKey::from_der(spki.subject_public_key.raw_bytes())?.try_into()
}
}
diff --git a/src/version.rs b/src/version.rs
index 6b253e8..2fdb198 100644
--- a/src/version.rs
+++ b/src/version.rs
@@ -62,7 +62,7 @@ impl Encode for Version {
der::Length::ONE.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/params.rs b/tests/params.rs
index 6954934..d47fbb5 100644
--- a/tests/params.rs
+++ b/tests/params.rs
@@ -2,8 +2,9 @@
use const_oid::db;
use der::{
- asn1::{ObjectIdentifier, OctetStringRef},
- Decode, Encode,
+ asn1::{AnyRef, ObjectIdentifier, OctetStringRef},
+ oid::AssociatedOid,
+ Encode,
};
use hex_literal::hex;
use pkcs1::{RsaOaepParams, RsaPssParams, TrailerField};
@@ -11,12 +12,22 @@ use pkcs1::{RsaOaepParams, RsaPssParams, TrailerField};
/// Default PSS parameters using all default values (SHA1, MGF1)
const RSA_PSS_PARAMETERS_DEFAULTS: &[u8] = &hex!("3000");
/// Example PSS parameters using SHA256 instead of SHA1
-const RSA_PSS_PARAMETERS_SHA2_256: &[u8] = &hex!("3030a00d300b0609608648016503040201a11a301806092a864886f70d010108300b0609608648016503040201a203020120");
+const RSA_PSS_PARAMETERS_SHA2_256: &[u8] = &hex!("3034a00f300d06096086480165030402010500a11c301a06092a864886f70d010108300d06096086480165030402010500a203020120");
/// Default OAEP parameters using all default values (SHA1, MGF1, Empty)
const RSA_OAEP_PARAMETERS_DEFAULTS: &[u8] = &hex!("3000");
-/// Example OAEP parameters using SHA256 instead of SHA1 and 'abc' as label
-const RSA_OAEP_PARAMETERS_SHA2_256: &[u8] = &hex!("303fa00d300b0609608648016503040201a11a301806092a864886f70d010108300b0609608648016503040201a212301006092a864886f70d0101090403abcdef");
+/// Example OAEP parameters using SHA256 instead of SHA1
+const RSA_OAEP_PARAMETERS_SHA2_256: &[u8] = &hex!("302fa00f300d06096086480165030402010500a11c301a06092a864886f70d010108300d06096086480165030402010500");
+
+struct Sha1Mock {}
+impl AssociatedOid for Sha1Mock {
+ const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26");
+}
+
+struct Sha256Mock {}
+impl AssociatedOid for Sha256Mock {
+ const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.1");
+}
#[test]
fn decode_pss_param() {
@@ -26,20 +37,17 @@ fn decode_pss_param() {
.hash
.assert_algorithm_oid(db::rfc5912::ID_SHA_256)
.is_ok());
- assert_eq!(param.hash.parameters, None);
+ assert_eq!(param.hash.parameters, Some(AnyRef::NULL));
assert!(param
.mask_gen
.assert_algorithm_oid(db::rfc5912::ID_MGF_1)
.is_ok());
- assert_eq!(
- param
- .mask_gen
- .parameters_any()
- .unwrap()
- .sequence(|reader| Ok(ObjectIdentifier::decode(reader)?))
- .unwrap(),
- db::rfc5912::ID_SHA_256
- );
+ assert!(param
+ .mask_gen
+ .parameters
+ .unwrap()
+ .assert_algorithm_oid(db::rfc5912::ID_SHA_256)
+ .is_ok());
assert_eq!(param.salt_len, 32);
assert_eq!(param.trailer_field, TrailerField::BC);
}
@@ -62,19 +70,20 @@ fn decode_pss_param_default() {
.hash
.assert_algorithm_oid(db::rfc5912::ID_SHA_1)
.is_ok());
- assert_eq!(param.hash.parameters, None);
+ assert_eq!(param.hash.parameters, Some(AnyRef::NULL));
assert!(param
.mask_gen
.assert_algorithm_oid(db::rfc5912::ID_MGF_1)
.is_ok());
+ assert!(param
+ .mask_gen
+ .parameters
+ .unwrap()
+ .assert_algorithm_oid(db::rfc5912::ID_SHA_1)
+ .is_ok());
assert_eq!(
- param
- .mask_gen
- .parameters_any()
- .unwrap()
- .sequence(|reader| Ok(ObjectIdentifier::decode(reader)?))
- .unwrap(),
- db::rfc5912::ID_SHA_1
+ param.mask_gen.parameters.unwrap().parameters,
+ Some(AnyRef::NULL)
);
assert_eq!(param.salt_len, 20);
assert_eq!(param.trailer_field, TrailerField::BC);
@@ -91,6 +100,23 @@ fn encode_pss_param_default() {
}
#[test]
+fn new_pss_param() {
+ let mut buf = [0_u8; 256];
+
+ let param = RsaPssParams::new::<Sha1Mock>(20);
+ assert_eq!(
+ param.encode_to_slice(&mut buf).unwrap(),
+ RSA_PSS_PARAMETERS_DEFAULTS
+ );
+
+ let param = RsaPssParams::new::<Sha256Mock>(32);
+ assert_eq!(
+ param.encode_to_slice(&mut buf).unwrap(),
+ RSA_PSS_PARAMETERS_SHA2_256
+ );
+}
+
+#[test]
fn decode_oaep_param() {
let param = RsaOaepParams::try_from(RSA_OAEP_PARAMETERS_SHA2_256).unwrap();
@@ -98,28 +124,28 @@ fn decode_oaep_param() {
.hash
.assert_algorithm_oid(db::rfc5912::ID_SHA_256)
.is_ok());
- assert_eq!(param.hash.parameters, None);
+ assert_eq!(param.hash.parameters, Some(AnyRef::NULL));
assert!(param
.mask_gen
.assert_algorithm_oid(db::rfc5912::ID_MGF_1)
.is_ok());
- assert_eq!(
- param
- .mask_gen
- .parameters_any()
- .unwrap()
- .sequence(|reader| Ok(ObjectIdentifier::decode(reader)?))
- .unwrap(),
- db::rfc5912::ID_SHA_256
- );
+ assert!(param
+ .mask_gen
+ .parameters
+ .unwrap()
+ .assert_algorithm_oid(db::rfc5912::ID_SHA_256)
+ .is_ok());
assert!(param
.p_source
.assert_algorithm_oid(db::rfc5912::ID_P_SPECIFIED)
.is_ok());
- assert_eq!(
- param.p_source.parameters_any().unwrap().octet_string(),
- OctetStringRef::new(&[0xab, 0xcd, 0xef])
- );
+ assert!(param
+ .p_source
+ .parameters_any()
+ .unwrap()
+ .decode_as::<OctetStringRef<'_>>()
+ .unwrap()
+ .is_empty(),);
}
#[test]
@@ -140,19 +166,20 @@ fn decode_oaep_param_default() {
.hash
.assert_algorithm_oid(db::rfc5912::ID_SHA_1)
.is_ok());
- assert_eq!(param.hash.parameters, None);
+ assert_eq!(param.hash.parameters, Some(AnyRef::NULL));
assert!(param
.mask_gen
.assert_algorithm_oid(db::rfc5912::ID_MGF_1)
.is_ok());
+ assert!(param
+ .mask_gen
+ .parameters
+ .unwrap()
+ .assert_algorithm_oid(db::rfc5912::ID_SHA_1)
+ .is_ok());
assert_eq!(
- param
- .mask_gen
- .parameters_any()
- .unwrap()
- .sequence(|reader| Ok(ObjectIdentifier::decode(reader)?))
- .unwrap(),
- db::rfc5912::ID_SHA_1
+ param.mask_gen.parameters.unwrap().parameters,
+ Some(AnyRef::NULL)
);
assert!(param
.p_source
@@ -162,7 +189,7 @@ fn decode_oaep_param_default() {
.p_source
.parameters_any()
.unwrap()
- .octet_string()
+ .decode_as::<OctetStringRef<'_>>()
.unwrap()
.is_empty(),);
assert_eq!(param, Default::default())
@@ -176,3 +203,21 @@ fn encode_oaep_param_default() {
RSA_OAEP_PARAMETERS_DEFAULTS
);
}
+
+#[test]
+fn new_oaep_param() {
+ let mut buf = [0_u8; 256];
+
+ let param = RsaOaepParams::new::<Sha1Mock>();
+ assert_eq!(
+ param.encode_to_slice(&mut buf).unwrap(),
+ RSA_OAEP_PARAMETERS_DEFAULTS
+ );
+
+ let param = RsaOaepParams::new::<Sha256Mock>();
+ println!("{:02x?}", param.encode_to_slice(&mut buf).unwrap());
+ assert_eq!(
+ param.encode_to_slice(&mut buf).unwrap(),
+ RSA_OAEP_PARAMETERS_SHA2_256
+ );
+}