Report some details of why asymmetric keys were rejected.
This commit is contained in:
parent
ddc36a9ca3
commit
9968baa55d
@ -69,7 +69,7 @@ impl<'a> KeyPair {
|
||||
///
|
||||
/// If you need to parse PKCS#8 v1 files (without the public key) then use
|
||||
/// `Ed25519KeyPair::from_pkcs8_maybe_unchecked()` instead.
|
||||
pub fn from_pkcs8(input: untrusted::Input) -> Result<Self, error::Unspecified> {
|
||||
pub fn from_pkcs8(input: untrusted::Input) -> Result<Self, error::KeyRejected> {
|
||||
let (seed, public_key) = unwrap_pkcs8(pkcs8::Version::V2Only, input)?;
|
||||
Self::from_seed_and_public_key(seed, public_key.unwrap())
|
||||
}
|
||||
@ -86,7 +86,7 @@ impl<'a> KeyPair {
|
||||
/// between the public key and the private key.
|
||||
///
|
||||
/// PKCS#8 v2 files are parsed exactly like `Ed25519KeyPair::from_pkcs8()`.
|
||||
pub fn from_pkcs8_maybe_unchecked(input: untrusted::Input) -> Result<Self, error::Unspecified> {
|
||||
pub fn from_pkcs8_maybe_unchecked(input: untrusted::Input) -> Result<Self, error::KeyRejected> {
|
||||
let (seed, public_key) = unwrap_pkcs8(pkcs8::Version::V1OrV2, input)?;
|
||||
if let Some(public_key) = public_key {
|
||||
Self::from_seed_and_public_key(seed, public_key)
|
||||
@ -107,14 +107,19 @@ impl<'a> KeyPair {
|
||||
/// key.
|
||||
pub fn from_seed_and_public_key(
|
||||
seed: untrusted::Input, public_key: untrusted::Input,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
let pair = Self::from_seed_unchecked(seed)?;
|
||||
|
||||
// This implicitly verifies that `public_key` is the right length.
|
||||
// XXX: This rejects ~18 keys when they are partially reduced, though
|
||||
// those keys are virtually impossible to find.
|
||||
if public_key != pair.public_key_bytes() {
|
||||
return Err(error::Unspecified);
|
||||
let err = if public_key.len() != pair.public_key_bytes().len() {
|
||||
error::KeyRejected::invalid_encoding()
|
||||
} else {
|
||||
error::KeyRejected::inconsistent_components()
|
||||
};
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
Ok(pair)
|
||||
@ -129,8 +134,9 @@ impl<'a> KeyPair {
|
||||
/// Since the public key is not given, the public key will be computed from
|
||||
/// the private key. It is not possible to detect misuse or corruption of
|
||||
/// the private key since the public key isn't given as input.
|
||||
pub fn from_seed_unchecked(seed: untrusted::Input) -> Result<Self, error::Unspecified> {
|
||||
let seed = slice_as_array_ref!(seed.as_slice_less_safe(), SEED_LEN)?;
|
||||
pub fn from_seed_unchecked(seed: untrusted::Input) -> Result<Self, error::KeyRejected> {
|
||||
let seed = slice_as_array_ref!(seed.as_slice_less_safe(), SEED_LEN)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
Ok(Self::from_seed_(seed))
|
||||
}
|
||||
|
||||
@ -194,11 +200,13 @@ impl<'a> KeyPair {
|
||||
|
||||
fn unwrap_pkcs8(
|
||||
version: pkcs8::Version, input: untrusted::Input,
|
||||
) -> Result<(untrusted::Input, Option<untrusted::Input>), error::Unspecified> {
|
||||
) -> Result<(untrusted::Input, Option<untrusted::Input>), error::KeyRejected> {
|
||||
let (private_key, public_key) = pkcs8::unwrap_key(&PKCS8_TEMPLATE, version, input)?;
|
||||
let private_key = private_key.read_all(error::Unspecified, |input| {
|
||||
let private_key = private_key
|
||||
.read_all(error::Unspecified, |input| {
|
||||
der::expect_tag_and_get_value(input, der::Tag::OctetString)
|
||||
})?;
|
||||
})
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
Ok((private_key, public_key))
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ impl private::Sealed for Algorithm {}
|
||||
impl signature::SigningAlgorithm for Algorithm {
|
||||
fn from_pkcs8(
|
||||
&'static self, input: untrusted::Input,
|
||||
) -> Result<signature::KeyPair, error::Unspecified> {
|
||||
) -> Result<signature::KeyPair, error::KeyRejected> {
|
||||
Key::from_pkcs8(self, input).map(signature::KeyPair::new)
|
||||
}
|
||||
}
|
||||
@ -106,7 +106,7 @@ impl Key {
|
||||
/// algorithm identifier in the PKCS#8 header.
|
||||
pub fn from_pkcs8(
|
||||
alg: &'static Algorithm, input: untrusted::Input,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
let key_pair = ec::suite_b::key_pair_from_pkcs8(alg.curve, alg.pkcs8_template, input)?;
|
||||
Ok(Self::new(alg, key_pair))
|
||||
}
|
||||
@ -119,7 +119,7 @@ impl Key {
|
||||
/// key) instead.
|
||||
pub fn from_private_key_and_public_key(
|
||||
alg: &'static Algorithm, private_key: untrusted::Input, public_key: untrusted::Input,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
let key_pair = ec::suite_b::key_pair_from_bytes(alg.curve, private_key, public_key)?;
|
||||
Ok(Self::new(alg, key_pair))
|
||||
}
|
||||
|
@ -152,33 +152,40 @@ fn verify_affine_point_is_on_the_curve_scaled(
|
||||
|
||||
pub(crate) fn key_pair_from_pkcs8(
|
||||
curve: &ec::Curve, template: &pkcs8::Template, input: untrusted::Input,
|
||||
) -> Result<ec::KeyPair, error::Unspecified> {
|
||||
) -> Result<ec::KeyPair, error::KeyRejected> {
|
||||
let (ec_private_key, _) = pkcs8::unwrap_key(template, pkcs8::Version::V1Only, input)?;
|
||||
let (private_key, public_key) = ec_private_key.read_all(error::Unspecified, |input| {
|
||||
let (private_key, public_key) =
|
||||
ec_private_key.read_all(error::KeyRejected::invalid_encoding(), |input| {
|
||||
// https://tools.ietf.org/html/rfc5915#section-3
|
||||
der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
|
||||
key_pair_from_pkcs8_(template, input)
|
||||
})
|
||||
der::nested(
|
||||
input,
|
||||
der::Tag::Sequence,
|
||||
error::KeyRejected::invalid_encoding(),
|
||||
|input| key_pair_from_pkcs8_(template, input),
|
||||
)
|
||||
})?;
|
||||
key_pair_from_bytes(curve, private_key, public_key)
|
||||
}
|
||||
|
||||
fn key_pair_from_pkcs8_<'a>(
|
||||
template: &pkcs8::Template, input: &mut untrusted::Reader<'a>,
|
||||
) -> Result<(untrusted::Input<'a>, untrusted::Input<'a>), error::Unspecified> {
|
||||
let version = der::small_nonnegative_integer(input)?;
|
||||
) -> Result<(untrusted::Input<'a>, untrusted::Input<'a>), error::KeyRejected> {
|
||||
let version = der::small_nonnegative_integer(input)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
if version != 1 {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::version_not_supported());
|
||||
}
|
||||
|
||||
let private_key = der::expect_tag_and_get_value(input, der::Tag::OctetString)?;
|
||||
let private_key = der::expect_tag_and_get_value(input, der::Tag::OctetString)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
|
||||
// [0] parameters (optional).
|
||||
if input.peek(der::Tag::ContextSpecificConstructed0 as u8) {
|
||||
let actual_alg_id =
|
||||
der::expect_tag_and_get_value(input, der::Tag::ContextSpecificConstructed0)?;
|
||||
der::expect_tag_and_get_value(input, der::Tag::ContextSpecificConstructed0)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
if actual_alg_id != template.curve_oid() {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::wrong_algorithm());
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,23 +196,26 @@ fn key_pair_from_pkcs8_<'a>(
|
||||
der::Tag::ContextSpecificConstructed1,
|
||||
error::Unspecified,
|
||||
der::bit_string_with_no_unused_bits,
|
||||
)?;
|
||||
)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
|
||||
Ok((private_key, public_key))
|
||||
}
|
||||
|
||||
pub fn key_pair_from_bytes(
|
||||
curve: &ec::Curve, private_key_bytes: untrusted::Input, public_key_bytes: untrusted::Input,
|
||||
) -> Result<ec::KeyPair, error::Unspecified> {
|
||||
let private_key = ec::PrivateKey::from_bytes(curve, private_key_bytes)?;
|
||||
) -> Result<ec::KeyPair, error::KeyRejected> {
|
||||
let private_key = ec::PrivateKey::from_bytes(curve, private_key_bytes)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_component())?;
|
||||
|
||||
let mut public_key_check = [0; ec::PUBLIC_KEY_MAX_LEN];
|
||||
{
|
||||
// Borrow `public_key_check`.
|
||||
let public_key_check = &mut public_key_check[..curve.public_key_len];
|
||||
(curve.public_from_private)(public_key_check, &private_key)?;
|
||||
(curve.public_from_private)(public_key_check, &private_key)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::unexpected_error())?;
|
||||
if public_key_bytes != &*public_key_check {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::inconsistent_components());
|
||||
}
|
||||
}
|
||||
|
||||
|
82
src/error.rs
82
src/error.rs
@ -82,10 +82,14 @@ use std;
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Unspecified;
|
||||
|
||||
impl Unspecified {
|
||||
fn description_() -> &'static str { "ring::error::Unspecified" }
|
||||
}
|
||||
|
||||
// This is required for the implementation of `std::error::Error`.
|
||||
impl core::fmt::Display for Unspecified {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
f.write_str("ring::error::Unspecified")
|
||||
f.write_str(Self::description_())
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,10 +98,82 @@ impl std::error::Error for Unspecified {
|
||||
#[inline]
|
||||
fn cause(&self) -> Option<&std::error::Error> { None }
|
||||
|
||||
#[inline]
|
||||
fn description(&self) -> &str { "ring::error::Unspecified" }
|
||||
fn description(&self) -> &str { Self::description_() }
|
||||
}
|
||||
|
||||
impl From<untrusted::EndOfInput> for Unspecified {
|
||||
fn from(_: untrusted::EndOfInput) -> Self { Unspecified }
|
||||
}
|
||||
|
||||
/// An error parsing or validating a key.
|
||||
///
|
||||
/// The `Display` implementation and `<KeyRejected as Error>::description()`
|
||||
/// will return a string that will help you better understand why a key was
|
||||
/// rejected change which errors are reported in which situations while
|
||||
/// minimizing the likelihood that any applications will be broken.
|
||||
///
|
||||
/// Here is an incomplete list of reasons a key may be unsupported:
|
||||
///
|
||||
/// * Invalid or Inconsistent Components: A component of the key has an
|
||||
/// invalid value, or the mathematical relationship between two (or more)
|
||||
/// components required for a valid key does not hold.
|
||||
///
|
||||
/// * The encoding of the key is invalid. Perhaps the key isn't in the correct
|
||||
/// format; e.g. it may be Base64 ("PEM") encoded, in which case the Base64
|
||||
/// encoding needs to be undone first.
|
||||
///
|
||||
/// * The encoding includes a versioning mechanism and that mechanism indicates
|
||||
/// that the key is encoded in a version of the encoding that isn't supported.
|
||||
/// This might happen for multi-prime RSA keys (keys with more than two
|
||||
/// private prime factors), which aren't supported, for example.
|
||||
///
|
||||
/// * Too small or too Large: One of the primary components of the key is too
|
||||
/// small or two large. Too-small keys are rejected for security reasons.
|
||||
/// Some unnecessarily large keys are rejected for performance reasons.
|
||||
///
|
||||
/// * Wrong algorithm: The key is not valid for the algorithm in which it
|
||||
/// was being used.
|
||||
///
|
||||
/// * Unexpected errors: Report this as a bug.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct KeyRejected(&'static str);
|
||||
|
||||
impl KeyRejected {
|
||||
fn description_(&self) -> &'static str { self.0 }
|
||||
|
||||
pub(crate) fn inconsistent_components() -> Self { KeyRejected("InconsistentComponents") }
|
||||
|
||||
pub(crate) fn invalid_component() -> Self { KeyRejected("InvalidComponent") }
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn invalid_encoding() -> Self { KeyRejected("InvalidEncoding") }
|
||||
|
||||
pub(crate) fn public_key_is_missing() -> Self { KeyRejected("PublicKeyIsMissing") }
|
||||
|
||||
pub(crate) fn too_small() -> Self { KeyRejected("TooSmall") }
|
||||
|
||||
pub(crate) fn too_large() -> Self { KeyRejected("TooLarge") }
|
||||
|
||||
pub(crate) fn version_not_supported() -> Self { KeyRejected("VersionNotSupported") }
|
||||
|
||||
pub(crate) fn wrong_algorithm() -> Self { KeyRejected("WrongAlgorithm") }
|
||||
|
||||
pub(crate) fn unexpected_error() -> Self { KeyRejected("UnexpectedError") }
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_heap")]
|
||||
impl std::error::Error for KeyRejected {
|
||||
fn cause(&self) -> Option<&std::error::Error> { None }
|
||||
|
||||
fn description(&self) -> &str { self.description_() }
|
||||
}
|
||||
|
||||
impl std::fmt::Display for KeyRejected {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
f.write_str(self.description_())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KeyRejected> for Unspecified {
|
||||
fn from(_: KeyRejected) -> Self { Unspecified }
|
||||
}
|
||||
|
61
src/pkcs8.rs
61
src/pkcs8.rs
@ -63,7 +63,7 @@ impl Template {
|
||||
/// [RFC 5958]: https://tools.ietf.org/html/rfc5958.
|
||||
pub(crate) fn unwrap_key<'a>(
|
||||
template: &Template, version: Version, input: untrusted::Input<'a>,
|
||||
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::Unspecified> {
|
||||
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::KeyRejected> {
|
||||
unwrap_key_(template.alg_id_value(), version, input)
|
||||
}
|
||||
|
||||
@ -79,47 +79,68 @@ pub(crate) fn unwrap_key<'a>(
|
||||
/// [RFC 5958]: https://tools.ietf.org/html/rfc5958.
|
||||
pub(crate) fn unwrap_key_<'a>(
|
||||
alg_id: &[u8], version: Version, input: untrusted::Input<'a>,
|
||||
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::Unspecified> {
|
||||
input.read_all(error::Unspecified, |input| {
|
||||
der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
|
||||
unwrap_key__(alg_id, version, input)
|
||||
})
|
||||
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::KeyRejected> {
|
||||
input.read_all(error::KeyRejected::invalid_encoding(), |input| {
|
||||
der::nested(
|
||||
input,
|
||||
der::Tag::Sequence,
|
||||
error::KeyRejected::invalid_encoding(),
|
||||
|input| unwrap_key__(alg_id, version, input),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn unwrap_key__<'a>(
|
||||
alg_id: &[u8], version: Version, input: &mut untrusted::Reader<'a>,
|
||||
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::Unspecified> {
|
||||
// Currently we only support algorithms that should only be encoded
|
||||
// in v1 form, so reject v2 and any later form.
|
||||
let require_public_key = match (der::small_nonnegative_integer(input)?, version) {
|
||||
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::KeyRejected> {
|
||||
let actual_version = der::small_nonnegative_integer(input)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
|
||||
// Do things in a specific order to return more useful errors:
|
||||
// 1. Check for completely unsupported version.
|
||||
// 2. Check for algorithm mismatch.
|
||||
// 3. Check for algorithm-specific version mismatch.
|
||||
|
||||
if actual_version > 1 {
|
||||
return Err(error::KeyRejected::version_not_supported());
|
||||
};
|
||||
|
||||
let actual_alg_id = der::expect_tag_and_get_value(input, der::Tag::Sequence)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
if actual_alg_id != alg_id {
|
||||
return Err(error::KeyRejected::wrong_algorithm());
|
||||
}
|
||||
|
||||
let require_public_key = match (actual_version, version) {
|
||||
(0, Version::V1Only) => false,
|
||||
(0, Version::V1OrV2) => false,
|
||||
(1, Version::V1OrV2) | (1, Version::V2Only) => true,
|
||||
_ => {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::version_not_supported());
|
||||
},
|
||||
};
|
||||
|
||||
let actual_alg_id = der::expect_tag_and_get_value(input, der::Tag::Sequence)?;
|
||||
if actual_alg_id != alg_id {
|
||||
return Err(error::Unspecified);
|
||||
}
|
||||
|
||||
let private_key = der::expect_tag_and_get_value(input, der::Tag::OctetString)?;
|
||||
let private_key = der::expect_tag_and_get_value(input, der::Tag::OctetString)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
|
||||
// Ignore any attributes that are present.
|
||||
if input.peek(der::Tag::ContextSpecificConstructed0 as u8) {
|
||||
let _ = der::expect_tag_and_get_value(input, der::Tag::ContextSpecificConstructed0)?;
|
||||
let _ = der::expect_tag_and_get_value(input, der::Tag::ContextSpecificConstructed0)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
}
|
||||
|
||||
let public_key = if require_public_key {
|
||||
Some(der::nested(
|
||||
if input.at_end() {
|
||||
return Err(error::KeyRejected::public_key_is_missing());
|
||||
}
|
||||
let public_key = der::nested(
|
||||
input,
|
||||
der::Tag::ContextSpecificConstructed1,
|
||||
error::Unspecified,
|
||||
der::bit_string_with_no_unused_bits,
|
||||
)?)
|
||||
)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
|
||||
Some(public_key)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -98,18 +98,19 @@ impl<M> Clone for BoxedLimbs<M> {
|
||||
impl<M> BoxedLimbs<M> {
|
||||
fn positive_minimal_width_from_be_bytes(
|
||||
input: untrusted::Input,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
// Reject leading zeros. Also reject the value zero ([0]) because zero
|
||||
// isn't positive.
|
||||
if untrusted::Reader::new(input).peek(0) {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::invalid_encoding());
|
||||
}
|
||||
let num_limbs = (input.len() + LIMB_BYTES - 1) / LIMB_BYTES;
|
||||
let mut r = Self::zero(Width {
|
||||
num_limbs,
|
||||
m: PhantomData,
|
||||
});
|
||||
limb::parse_big_endian_and_pad_consttime(input, &mut r)?;
|
||||
limb::parse_big_endian_and_pad_consttime(input, &mut r)
|
||||
.map_err(|error::Unspecified| error::KeyRejected::unexpected_error())?;
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
@ -227,14 +228,14 @@ impl core::fmt::Debug for Modulus<super::N> {
|
||||
impl<M> Modulus<M> {
|
||||
pub fn from_be_bytes_with_bit_length(
|
||||
input: untrusted::Input,
|
||||
) -> Result<(Self, bits::BitLength), error::Unspecified> {
|
||||
) -> Result<(Self, bits::BitLength), error::KeyRejected> {
|
||||
let limbs = BoxedLimbs::positive_minimal_width_from_be_bytes(input)?;
|
||||
let bits = limb::limbs_minimal_bits(&limbs);
|
||||
Ok((Self::from_boxed_limbs(limbs)?, bits))
|
||||
}
|
||||
|
||||
#[cfg(feature = "rsa_signing")]
|
||||
pub fn from(n: Nonnegative) -> Result<Self, error::Unspecified> {
|
||||
pub fn from(n: Nonnegative) -> Result<Self, error::KeyRejected> {
|
||||
let limbs = BoxedLimbs {
|
||||
limbs: n.limbs.into_boxed_slice(),
|
||||
m: PhantomData,
|
||||
@ -242,16 +243,17 @@ impl<M> Modulus<M> {
|
||||
Self::from_boxed_limbs(limbs)
|
||||
}
|
||||
|
||||
fn from_boxed_limbs(n: BoxedLimbs<M>) -> Result<Self, error::Unspecified> {
|
||||
fn from_boxed_limbs(n: BoxedLimbs<M>) -> Result<Self, error::KeyRejected> {
|
||||
if n.len() > MODULUS_MAX_LIMBS {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::too_large());
|
||||
}
|
||||
Result::from(unsafe { GFp_bn_mul_mont_check_num_limbs(n.len()) })?;
|
||||
Result::from(unsafe { GFp_bn_mul_mont_check_num_limbs(n.len()) })
|
||||
.map_err(|error::Unspecified| error::KeyRejected::too_small())?;
|
||||
if limb::limbs_are_even_constant_time(&n) != LimbMask::False {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::invalid_component());
|
||||
}
|
||||
if limb::limbs_less_than_limb_constant_time(&n, 3) != LimbMask::False {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::unexpected_error());
|
||||
}
|
||||
|
||||
// n_mod_r = n % r. As explained in the documentation for `n0`, this is
|
||||
@ -427,7 +429,7 @@ impl<M> Elem<M, Unencoded> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "rsa_signing")]
|
||||
pub fn into_modulus<MM>(self) -> Result<Modulus<MM>, error::Unspecified> {
|
||||
pub fn into_modulus<MM>(self) -> Result<Modulus<MM>, error::KeyRejected> {
|
||||
Modulus::from_boxed_limbs(BoxedLimbs::minimal_width_from_unpadded(&self.limbs))
|
||||
}
|
||||
|
||||
@ -647,19 +649,21 @@ pub struct PublicExponent(u64);
|
||||
impl PublicExponent {
|
||||
pub fn from_be_bytes(
|
||||
input: untrusted::Input, min_value: u64,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
if input.len() > 5 {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::too_large());
|
||||
}
|
||||
let value = input.read_all_mut(error::Unspecified, |input| {
|
||||
let value = input.read_all_mut(error::KeyRejected::invalid_encoding(), |input| {
|
||||
// The exponent can't be zero and it can't be prefixed with
|
||||
// zero-valued bytes.
|
||||
if input.peek(0) {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::invalid_encoding());
|
||||
}
|
||||
let mut value = 0u64;
|
||||
loop {
|
||||
let byte = input.read_byte()?;
|
||||
let byte = input
|
||||
.read_byte()
|
||||
.map_err(|untrusted::EndOfInput| error::KeyRejected::invalid_encoding())?;
|
||||
value = (value << 8) | u64::from(byte);
|
||||
if input.at_end() {
|
||||
return Ok(value);
|
||||
@ -672,18 +676,18 @@ impl PublicExponent {
|
||||
// verification, for compatibility. Only small public exponents are
|
||||
// supported.
|
||||
if value & 1 != 1 {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::invalid_component());
|
||||
}
|
||||
debug_assert!(min_value & 1 == 1);
|
||||
debug_assert!(min_value <= PUBLIC_EXPONENT_MAX_VALUE);
|
||||
if min_value < 3 {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::invalid_component());
|
||||
}
|
||||
if value < min_value {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::too_small());
|
||||
}
|
||||
if value > PUBLIC_EXPONENT_MAX_VALUE {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::too_large());
|
||||
}
|
||||
|
||||
Ok(PublicExponent(value))
|
||||
|
@ -18,7 +18,11 @@ use super::{
|
||||
};
|
||||
use arithmetic::montgomery::R;
|
||||
/// RSA PKCS#1 1.5 signatures.
|
||||
use crate::{bits, der, digest, error, pkcs8, rand};
|
||||
use crate::{
|
||||
bits, der, digest,
|
||||
error::{self, KeyRejected},
|
||||
pkcs8, rand,
|
||||
};
|
||||
use std;
|
||||
use untrusted;
|
||||
|
||||
@ -136,7 +140,7 @@ impl KeyPair {
|
||||
///
|
||||
/// [RFC 5958]:
|
||||
/// https://tools.ietf.org/html/rfc5958
|
||||
pub fn from_pkcs8(input: untrusted::Input) -> Result<Self, error::Unspecified> {
|
||||
pub fn from_pkcs8(input: untrusted::Input) -> Result<Self, KeyRejected> {
|
||||
const RSA_ENCRYPTION: &[u8] = include_bytes!("../data/alg-rsa-encryption.der");
|
||||
let (der, _) = pkcs8::unwrap_key_(&RSA_ENCRYPTION, pkcs8::Version::V1Only, input)?;
|
||||
Self::from_der(der)
|
||||
@ -157,33 +161,44 @@ impl KeyPair {
|
||||
///
|
||||
/// [NIST SP-800-56B rev. 1]:
|
||||
/// http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br1.pdf
|
||||
pub fn from_der(input: untrusted::Input) -> Result<Self, error::Unspecified> {
|
||||
input.read_all(error::Unspecified, |input| {
|
||||
pub fn from_der(input: untrusted::Input) -> Result<Self, KeyRejected> {
|
||||
input.read_all(KeyRejected::invalid_encoding(), |input| {
|
||||
der::nested(
|
||||
input,
|
||||
der::Tag::Sequence,
|
||||
error::Unspecified,
|
||||
error::KeyRejected::invalid_encoding(),
|
||||
Self::from_der_reader,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn from_der_reader(input: &mut untrusted::Reader) -> Result<Self, error::Unspecified> {
|
||||
let version = der::small_nonnegative_integer(input)?;
|
||||
fn from_der_reader(input: &mut untrusted::Reader) -> Result<Self, KeyRejected> {
|
||||
let version = der::small_nonnegative_integer(input)
|
||||
.map_err(|error::Unspecified| KeyRejected::invalid_encoding())?;
|
||||
if version != 0 {
|
||||
return Err(error::Unspecified);
|
||||
return Err(KeyRejected::version_not_supported());
|
||||
}
|
||||
let n = der::positive_integer(input)?;
|
||||
let e = der::positive_integer(input)?;
|
||||
let d = der::positive_integer(input)?;
|
||||
let p = der::positive_integer(input)?;
|
||||
let q = der::positive_integer(input)?;
|
||||
let dP = der::positive_integer(input)?;
|
||||
let dQ = der::positive_integer(input)?;
|
||||
let qInv = der::positive_integer(input)?;
|
||||
|
||||
let (p, p_bits) = bigint::Nonnegative::from_be_bytes_with_bit_length(p)?;
|
||||
let (q, q_bits) = bigint::Nonnegative::from_be_bytes_with_bit_length(q)?;
|
||||
fn positive_integer<'a>(
|
||||
input: &mut untrusted::Reader<'a>,
|
||||
) -> Result<untrusted::Input<'a>, KeyRejected> {
|
||||
der::positive_integer(input)
|
||||
.map_err(|error::Unspecified| KeyRejected::invalid_encoding())
|
||||
}
|
||||
|
||||
let n = positive_integer(input)?;
|
||||
let e = positive_integer(input)?;
|
||||
let d = positive_integer(input)?;
|
||||
let p = positive_integer(input)?;
|
||||
let q = positive_integer(input)?;
|
||||
let dP = positive_integer(input)?;
|
||||
let dQ = positive_integer(input)?;
|
||||
let qInv = positive_integer(input)?;
|
||||
|
||||
let (p, p_bits) = bigint::Nonnegative::from_be_bytes_with_bit_length(p)
|
||||
.map_err(|error::Unspecified| KeyRejected::invalid_encoding())?;
|
||||
let (q, q_bits) = bigint::Nonnegative::from_be_bytes_with_bit_length(q)
|
||||
.map_err(|error::Unspecified| KeyRejected::invalid_encoding())?;
|
||||
|
||||
// Our implementation of CRT-based modular exponentiation used requires
|
||||
// that `p > q` so swap them if `p < q`. If swapped, `qInv` is
|
||||
@ -191,7 +206,7 @@ impl KeyPair {
|
||||
// `q_mod_p` is constructed.
|
||||
let ((p, p_bits, dP), (q, q_bits, dQ, qInv)) = match q.verify_less_than(&p) {
|
||||
Ok(_) => ((p, p_bits, dP), (q, q_bits, dQ, Some(qInv))),
|
||||
Err(_) => {
|
||||
Err(error::Unspecified) => {
|
||||
// TODO: verify `q` and `qInv` are inverses (mod p).
|
||||
((q, q_bits, dQ), (p, p_bits, dP, None))
|
||||
},
|
||||
@ -244,7 +259,7 @@ impl KeyPair {
|
||||
// Second, stop if `p > 2**(nBits/2) - 1`.
|
||||
let half_n_bits = public_key.n_bits.half_rounded_up();
|
||||
if p_bits != half_n_bits {
|
||||
return Err(error::Unspecified);
|
||||
return Err(KeyRejected::inconsistent_components());
|
||||
}
|
||||
|
||||
// TODO: Step 5.d: Verify GCD(p - 1, e) == 1.
|
||||
@ -257,12 +272,14 @@ impl KeyPair {
|
||||
//
|
||||
// Second, stop if `q > 2**(nBits/2) - 1`.
|
||||
if p_bits != q_bits {
|
||||
return Err(error::Unspecified);
|
||||
return Err(KeyRejected::inconsistent_components());
|
||||
}
|
||||
|
||||
// TODO: Step 5.h: Verify GCD(p - 1, e) == 1.
|
||||
|
||||
let q_mod_n_decoded = q.to_elem(&public_key.n)?;
|
||||
let q_mod_n_decoded = q
|
||||
.to_elem(&public_key.n)
|
||||
.map_err(|error::Unspecified| KeyRejected::inconsistent_components())?;
|
||||
|
||||
// TODO: Step 5.i
|
||||
//
|
||||
@ -280,10 +297,12 @@ impl KeyPair {
|
||||
q_mod_n_decoded.clone(),
|
||||
&public_key.n,
|
||||
);
|
||||
let p_mod_n = p.to_elem(&public_key.n)?;
|
||||
let p_mod_n = p
|
||||
.to_elem(&public_key.n)
|
||||
.map_err(|error::Unspecified| KeyRejected::inconsistent_components())?;
|
||||
let pq_mod_n = bigint::elem_mul(&q_mod_n, p_mod_n, &public_key.n);
|
||||
if !pq_mod_n.is_zero() {
|
||||
return Err(error::Unspecified);
|
||||
return Err(KeyRejected::inconsistent_components());
|
||||
}
|
||||
|
||||
// 6.4.1.4.3/6.4.1.2.1 - Step 6.
|
||||
@ -293,15 +312,17 @@ impl KeyPair {
|
||||
// First, validate `2**half_n_bits < d`. Since 2**half_n_bits has a bit
|
||||
// length of half_n_bits + 1, this check gives us 2**half_n_bits <= d,
|
||||
// and knowing d is odd makes the inequality strict.
|
||||
let (d, d_bits) = bigint::Nonnegative::from_be_bytes_with_bit_length(d)?;
|
||||
let (d, d_bits) = bigint::Nonnegative::from_be_bytes_with_bit_length(d)
|
||||
.map_err(|_| error::KeyRejected::invalid_encoding())?;
|
||||
if !(half_n_bits < d_bits) {
|
||||
return Err(error::Unspecified);
|
||||
return Err(KeyRejected::inconsistent_components());
|
||||
}
|
||||
// XXX: This check should be `d < LCM(p - 1, q - 1)`, but we don't have
|
||||
// a good way of calculating LCM, so it is omitted, as explained above.
|
||||
d.verify_less_than_modulus(&public_key.n)?;
|
||||
d.verify_less_than_modulus(&public_key.n)
|
||||
.map_err(|error::Unspecified| KeyRejected::inconsistent_components())?;
|
||||
if !d.is_odd() {
|
||||
return Err(error::Unspecified);
|
||||
return Err(KeyRejected::invalid_component());
|
||||
}
|
||||
|
||||
// Step 6.b is omitted as explained above.
|
||||
@ -318,12 +339,14 @@ impl KeyPair {
|
||||
|
||||
// Step 7.c.
|
||||
let qInv = if let Some(qInv) = qInv {
|
||||
bigint::Elem::from_be_bytes_padded(qInv, &p.modulus)?
|
||||
bigint::Elem::from_be_bytes_padded(qInv, &p.modulus)
|
||||
.map_err(|error::Unspecified| KeyRejected::invalid_component())?
|
||||
} else {
|
||||
// We swapped `p` and `q` above, so we need to calculate `qInv`.
|
||||
// Step 7.f below will verify `qInv` is correct.
|
||||
let q_mod_p = bigint::elem_mul(p.modulus.oneRR().as_ref(), q_mod_p.clone(), &p.modulus);
|
||||
bigint::elem_inverse_consttime(q_mod_p, &p.modulus)?
|
||||
bigint::elem_inverse_consttime(q_mod_p, &p.modulus)
|
||||
.map_err(|error::Unspecified| KeyRejected::unexpected_error())?
|
||||
};
|
||||
|
||||
// Steps 7.d and 7.e are omitted per the documentation above, and
|
||||
@ -332,7 +355,8 @@ impl KeyPair {
|
||||
|
||||
// Step 7.f.
|
||||
let qInv = bigint::elem_mul(p.modulus.oneRR().as_ref(), qInv, &p.modulus);
|
||||
bigint::verify_inverses_consttime(&qInv, q_mod_p, &p.modulus)?;
|
||||
bigint::verify_inverses_consttime(&qInv, q_mod_p, &p.modulus)
|
||||
.map_err(|error::Unspecified| KeyRejected::inconsistent_components())?;
|
||||
|
||||
let qq = bigint::elem_mul(&q_mod_n, q_mod_n_decoded, &public_key.n).into_modulus::<QQ>()?;
|
||||
|
||||
@ -360,11 +384,12 @@ struct PrivatePrime<M: Prime> {
|
||||
impl<M: Prime + Clone> PrivatePrime<M> {
|
||||
/// Constructs a `PrivatePrime` from the private prime `p` and `dP` where
|
||||
/// dP == d % (p - 1).
|
||||
fn new(p: bigint::Nonnegative, dP: untrusted::Input) -> Result<Self, error::Unspecified> {
|
||||
fn new(p: bigint::Nonnegative, dP: untrusted::Input) -> Result<Self, KeyRejected> {
|
||||
let p = bigint::Modulus::from(p)?;
|
||||
|
||||
// [NIST SP-800-56B rev. 1] 6.4.1.4.3 - Steps 7.a & 7.b.
|
||||
let dP = bigint::PrivateExponent::from_be_bytes_padded(dP, &p)?;
|
||||
let dP = bigint::PrivateExponent::from_be_bytes_padded(dP, &p)
|
||||
.map_err(|error::Unspecified| KeyRejected::invalid_component())?;
|
||||
|
||||
// XXX: Steps 7.d and 7.e are omitted. We don't check that
|
||||
// `dP == d % (p - 1)` because we don't (in the long term) have a good
|
||||
|
@ -29,7 +29,7 @@ impl Key {
|
||||
pub fn from_modulus_and_exponent(
|
||||
n: untrusted::Input, e: untrusted::Input, n_min_bits: bits::BitLength,
|
||||
n_max_bits: bits::BitLength, e_min_value: u64,
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
) -> Result<Self, error::KeyRejected> {
|
||||
// This is an incomplete implementation of NIST SP800-56Br1 Section
|
||||
// 6.4.2.2, "Partial Public-Key Validation for RSA." That spec defers
|
||||
// to NIST SP800-89 Section 5.3.3, "(Explicit) Partial Public Key
|
||||
@ -52,12 +52,13 @@ impl Key {
|
||||
// flexible to be compatible with other commonly-used crypto libraries.
|
||||
assert!(n_min_bits >= N_MIN_BITS);
|
||||
let n_bits_rounded_up =
|
||||
bits::BitLength::from_usize_bytes(n_bits.as_usize_bytes_rounded_up())?;
|
||||
bits::BitLength::from_usize_bytes(n_bits.as_usize_bytes_rounded_up())
|
||||
.map_err(|error::Unspecified| error::KeyRejected::unexpected_error())?;
|
||||
if n_bits_rounded_up < n_min_bits {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::too_small());
|
||||
}
|
||||
if n_bits > n_max_bits {
|
||||
return Err(error::Unspecified);
|
||||
return Err(error::KeyRejected::too_large());
|
||||
}
|
||||
|
||||
// Step 2 / Step b.
|
||||
|
@ -213,12 +213,12 @@
|
||||
//! let private_key_der = read_file(private_key_path)?;
|
||||
//! let private_key_der = untrusted::Input::from(&private_key_der);
|
||||
//! let key_pair = signature::RSAKeyPair::from_der(private_key_der)
|
||||
//! .map_err(|ring::error::Unspecified| MyError::BadPrivateKey)?;
|
||||
//! .map_err(|_| MyError::BadPrivateKey)?;
|
||||
//!
|
||||
//! // Create a signing state.
|
||||
//! let key_pair = std::sync::Arc::new(key_pair);
|
||||
//! let mut signing_state = signature::RSASigningState::new(key_pair)
|
||||
//! .map_err(|ring::error::Unspecified| MyError::OOM)?;
|
||||
//! .map_err(|_| MyError::OOM)?;
|
||||
//!
|
||||
//! // Sign the message "hello, world", using PKCS#1 v1.5 padding and the
|
||||
//! // SHA256 digest algorithm.
|
||||
@ -227,7 +227,7 @@
|
||||
//! let mut signature = vec![0; signing_state.key_pair().public_modulus_len()];
|
||||
//! signing_state.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE,
|
||||
//! &mut signature)
|
||||
//! .map_err(|ring::error::Unspecified| MyError::OOM)?;
|
||||
//! .map_err(|_| MyError::OOM)?;
|
||||
//!
|
||||
//! // Verify the signature.
|
||||
//! let public_key_der = read_file(public_key_path)?;
|
||||
@ -236,7 +236,7 @@
|
||||
//! let signature = untrusted::Input::from(&signature);
|
||||
//! signature::verify(&signature::RSA_PKCS1_2048_8192_SHA256,
|
||||
//! public_key_der, message, signature)
|
||||
//! .map_err(|ring::error::Unspecified| MyError::BadSignature)?;
|
||||
//! .map_err(|_| MyError::BadSignature)?;
|
||||
//!
|
||||
//! Ok(())
|
||||
//! }
|
||||
@ -373,7 +373,7 @@ pub(crate) trait KeyPairImpl: core::fmt::Debug + Send + 'static {
|
||||
pub trait SigningAlgorithm: core::fmt::Debug + Sync + 'static + private::Sealed {
|
||||
/// Parses the key out of the given PKCS#8 document, verifying that it is
|
||||
/// valid for the algorithm.
|
||||
fn from_pkcs8(&'static self, input: untrusted::Input) -> Result<KeyPair, error::Unspecified>;
|
||||
fn from_pkcs8(&'static self, input: untrusted::Input) -> Result<KeyPair, error::KeyRejected>;
|
||||
}
|
||||
|
||||
/// Returns a key for signing that is parsed from a PKCS#8 document.
|
||||
@ -383,7 +383,7 @@ pub trait SigningAlgorithm: core::fmt::Debug + Sync + 'static + private::Sealed
|
||||
#[inline]
|
||||
pub fn key_pair_from_pkcs8(
|
||||
alg: &'static SigningAlgorithm, input: untrusted::Input,
|
||||
) -> Result<KeyPair, error::Unspecified> {
|
||||
) -> Result<KeyPair, error::KeyRejected> {
|
||||
alg.from_pkcs8(input)
|
||||
}
|
||||
|
||||
|
@ -15,29 +15,29 @@ Input = 3081bf020100301006072a8648ce3d020106052b810400220481a73081a40201010430fc
|
||||
# A P-256 key where the ECPrivateKey contains a parameters field identifying P-384.
|
||||
Curve = P-256
|
||||
Input = 308190020100301306072a8648ce3d020106082a8648ce3d030107047630740201010420090460075f15d2a256248000fb02d83ad77593dde4ae59fc5e96142dffb2bd07a00706052b81040022a14403420004cf0d13a3a7577231ea1b66cf4021cd54f21f4ac4f5f2fdd28e05bc7d2bd099d1374cd08d2ef654d6f04498db462f73e0282058dd661a4c9b0437af3f7af6e724
|
||||
Error = DECODE_ERROR
|
||||
Error = WrongAlgorithm
|
||||
|
||||
# A P-256 key where the ECPrivateKey contains a parameters field containing an entire AlgorithmIdentifier.
|
||||
Curve = P-256
|
||||
Input = 3081a0020100301306072a8648ce3d020106082a8648ce3d0301070481853081820201010420090460075f15d2a256248000fb02d83ad77593dde4ae59fc5e96142dffb2bd07a015301306072a8648ce3d020106082a8648ce3d030107a14403420004cf0d13a3a7577231ea1b66cf4021cd54f21f4ac4f5f2fdd28e05bc7d2bd099d1374cd08d2ef654d6f04498db462f73e0282058dd661a4c9b0437af3f7af6e724
|
||||
Error = DECODE_ERROR
|
||||
Error = WrongAlgorithm
|
||||
|
||||
# The curve P-256 is encoded explicitly, instead of as a reference to a named curve.
|
||||
Curve = P-256
|
||||
Input = 308201220201010420c6c1aada15b07661f8142c6caf0fdb241aff2efe46c0938b74f2bcc53052b077a081fa3081f7020101302c06072a8648ce3d0101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff305b0420ffffffff00000001000000000000000000000000fffffffffffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b031500c49d360886e704936a6678e1139d26b7819f7e900441046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020101
|
||||
Error = DECODE_ERROR
|
||||
Error = InvalidEncoding
|
||||
|
||||
# A valid PKCS#8 P-256 private key, but without the public key in the ECPrivateKey.
|
||||
Curve = P-256
|
||||
Input = 308141020100301306072a8648ce3d020106082a8648ce3d030107042730250201010420090460075f15d2a256248000fb02d83ad77593dde4ae59fc5e96142dffb2bd07
|
||||
Error = DECODE_ERROR
|
||||
Error = InvalidEncoding
|
||||
|
||||
# The AlgorithmIdentifier is ecPublicKey w/ P-256, but it's an RSAPrivateKey.
|
||||
Curve = P-256
|
||||
Input = 308189020100301306072A8648CE3D020106082A8648CE3D0301070500046d306b0201010420090460075f15d2a256248000fb02d83ad77593dde4ae59fc5e96142dffb2bd07a14403420004cf0d13a3a7577231ea1b66cf4021cd54f21f4ac4f5f2fdd28e05bc7d2bd099d1374cd08d2ef654d6f04498db462f73e0282058dd661a4c9b0437af3f7af6e724
|
||||
Error = DECODE_ERROR
|
||||
Error = InvalidEncoding
|
||||
|
||||
# A P-256 ECPrivateKey, but the AlgorithmIdentifier is The AlgorithmIdentifier is rsaEncryption.
|
||||
# A P-256 ECPrivateKey, but the AlgorithmIdentifier is rsaEncryption.
|
||||
Curve = P-256
|
||||
Input = 308181020100300d06092a864886f70d0101010500046d306b0201010420090460075f15d2a256248000fb02d83ad77593dde4ae59fc5e96142dffb2bd07a14403420004cf0d13a3a7577231ea1b66cf4021cd54f21f4ac4f5f2fdd28e05bc7d2bd099d1374cd08d2ef654d6f04498db462f73e0282058dd661a4c9b0437af3f7af6e724
|
||||
Error = DECODE_ERROR
|
||||
Error = WrongAlgorithm
|
||||
|
@ -41,6 +41,8 @@ use ring::{rand, signature, test};
|
||||
#[test]
|
||||
fn ecdsa_from_pkcs8_test() {
|
||||
test::from_file("tests/ecdsa_from_pkcs8_tests.txt", |section, test_case| {
|
||||
use std::error::Error;
|
||||
|
||||
assert_eq!(section, "");
|
||||
|
||||
let curve_name = test_case.consume_string("Curve");
|
||||
@ -73,14 +75,26 @@ fn ecdsa_from_pkcs8_test() {
|
||||
|
||||
let error = test_case.consume_optional_string("Error");
|
||||
|
||||
assert_eq!(
|
||||
signature::key_pair_from_pkcs8(this_fixed, input).is_ok(),
|
||||
error.is_none()
|
||||
);
|
||||
assert_eq!(
|
||||
signature::key_pair_from_pkcs8(this_asn1, input).is_ok(),
|
||||
error.is_none()
|
||||
);
|
||||
match (
|
||||
signature::key_pair_from_pkcs8(this_fixed, input),
|
||||
error.clone(),
|
||||
) {
|
||||
(Ok(_), None) => (),
|
||||
(Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
|
||||
(Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
|
||||
(Err(actual), Some(expected)) => assert_eq!(actual.description(), expected),
|
||||
};
|
||||
|
||||
match (
|
||||
signature::key_pair_from_pkcs8(this_asn1, input),
|
||||
error.clone(),
|
||||
) {
|
||||
(Ok(_), None) => (),
|
||||
(Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
|
||||
(Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
|
||||
(Err(actual), Some(expected)) => assert_eq!(actual.description(), expected),
|
||||
};
|
||||
|
||||
assert!(signature::key_pair_from_pkcs8(other_fixed, input).is_err());
|
||||
assert!(signature::key_pair_from_pkcs8(other_asn1, input).is_err());
|
||||
|
||||
|
@ -3,43 +3,43 @@ Input = 3053020101300506032b657004220420a22efdb713f0e1600d2a5ce948e321ca3a18137c
|
||||
|
||||
# v2. The private key's last byte, zero, is omitted.
|
||||
Input = 3052020101300506032b65700421041fa22efdb713f0e1600d2a5ce948e321ca3a18137c47f15091a12c7126c1749aa1230321001aeb8e3ee5ba5afd91113466d19f4ea77fa0feffbd8c5adcb499927f12535f77
|
||||
Error = DECODE_ERROR
|
||||
Error = InvalidEncoding
|
||||
|
||||
# v2. The private key starts with a zero byte.
|
||||
Input = 3053020101300506032b65700422042000b1a7c20b2b4ed9c78f3686db82f854734cdc95be51def304d98e0cd30bf490a12303210063457cd4dfdd0e98a53796265831d46ac6a5a685f2a54c9697a38b2c800d60ba
|
||||
|
||||
# v2. The private key's first byte, zero, is omitted.
|
||||
Input = 3052020101300506032b65700421041fb1a7c20b2b4ed9c78f3686db82f854734cdc95be51def304d98e0cd30bf490a12303210063457cd4dfdd0e98a53796265831d46ac6a5a685f2a54c9697a38b2c800d60ba
|
||||
Error = DECODE_ERROR
|
||||
Error = InvalidEncoding
|
||||
|
||||
# v2. The public key's first byte is zero.
|
||||
Input = 3053020101300506032b6570042204202dc67de5186d9193021c0b104d9c6ef24bee2bd395ccb5ed5a2db5f37a2fc1f0a12303210000c17e4d8bbff27c1fb618c23fce988703c7efa3cd590aacac12d3f1e3c90c8c
|
||||
|
||||
# v2. The public key's first byte, zero, is omitted.
|
||||
Input = 3052020101300506032b6570042204202dc67de5186d9193021c0b104d9c6ef24bee2bd395ccb5ed5a2db5f37a2fc1f0a122032000c17e4d8bbff27c1fb618c23fce988703c7efa3cd590aacac12d3f1e3c90c8c
|
||||
Error = DECODE_ERROR
|
||||
Error = InvalidEncoding
|
||||
|
||||
# v2. The public key's last byte is zero.
|
||||
Input = 3053020101300506032b657004220420b2579f555a2eabdabac8d46997b1c08fe8ce63858df124efc29c60dfbb86c349a1230321009d421270ce2fcc08672c41e427214876245c9b0f14ab671b8bb9d266a492e400
|
||||
|
||||
# v2. The public key's last byte, zero, is omitted (valid ASN.1 DER).
|
||||
Input = 3052020101300506032b657004220420b2579f555a2eabdabac8d46997b1c08fe8ce63858df124efc29c60dfbb86c349a1220320009d421270ce2fcc08672c41e427214876245c9b0f14ab671b8bb9d266a492e4
|
||||
Error = DECODE_ERROR
|
||||
Error = InvalidEncoding
|
||||
|
||||
# v2. The public key's last byte, zero, has been truncated (invalid ASN.1 DER).
|
||||
Input = 3053020101300506032b657004220420b2579f555a2eabdabac8d46997b1c08fe8ce63858df124efc29c60dfbb86c349a1230321009d421270ce2fcc08672c41e427214876245c9b0f14ab671b8bb9d266a492e4
|
||||
Error = DECODE_ERROR
|
||||
Error = InvalidEncoding
|
||||
|
||||
# v2. The public key's high bit has been flipped. Ed25519 public keys don't
|
||||
# have their high bit masked, so this is wrong.
|
||||
Input = 3053020101300506032b6570042204202dc67de5186d9193021c0b104d9c6ef24bee2bd395ccb5ed5a2db5f37a2fc1f0a12303210000c17e4d8bbff27c1fb618c23fce988703c7efa3cd590aacac12d3f1e3c90c0c
|
||||
Error = DECODE_ERROR
|
||||
Error = InconsistentComponents
|
||||
|
||||
# v2. Valid except the public key field is missing.
|
||||
Input = 302e020101300506032b657004220420a22efdb713f0e1600d2a5ce948e321ca3a18137c47f15091a12c7126c1749a00
|
||||
Error = DECODE_ERROR
|
||||
Error = PublicKeyIsMissing
|
||||
|
||||
# v2. Valid except the public key is encoded as [0] instead of [1]; i.e. the
|
||||
# attributes are invalid and the public key is missing.
|
||||
Input = 3053020101300506032b657004220420a22efdb713f0e1600d2a5ce948e321ca3a18137c47f15091a12c7126c1749a00a0230321001aeb8e3ee5ba5afd91113466d19f4ea77fa0feffbd8c5adcb499927f12535f77
|
||||
Error = DECODE_ERROR
|
||||
Error = PublicKeyIsMissing
|
||||
|
@ -3,11 +3,11 @@ Input = 302e020100300506032b6570042204209d61b19deffd5a60ba844af492ec2cc44449c569
|
||||
|
||||
# The same as the above, but with an invalid NULL parameter. (This is from BoringSSL's tests.)
|
||||
Input = 3030020100300706032b65700500042204209d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60
|
||||
Error = DECODE_ERROR
|
||||
Error = WrongAlgorithm
|
||||
|
||||
# Sample private key from draft-ietf-curdle-pkix-04.
|
||||
Input = 302e020100300506032b657004220420d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842
|
||||
|
||||
# v1. valid except it includes publicKey.
|
||||
Input = 3053020100300506032b657004220420a22efdb713f0e1600d2a5ce948e321ca3a18137c47f15091a12c7126c1749a00a1230321001aeb8e3ee5ba5afd91113466d19f4ea77fa0feffbd8c5adcb499927f12535f77
|
||||
Error = DECODE_ERROR
|
||||
Error = InvalidEncoding
|
||||
|
@ -123,13 +123,22 @@ fn test_ed25519_from_pkcs8_unchecked() {
|
||||
test::from_file(
|
||||
"tests/ed25519_from_pkcs8_unchecked_tests.txt",
|
||||
|section, test_case| {
|
||||
use std::error::Error;
|
||||
|
||||
assert_eq!(section, "");
|
||||
let input = test_case.consume_bytes("Input");
|
||||
let error = test_case.consume_optional_string("Error");
|
||||
assert_eq!(
|
||||
Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&input)).is_ok(),
|
||||
error.is_none()
|
||||
);
|
||||
|
||||
match (
|
||||
Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&input)),
|
||||
error.clone(),
|
||||
) {
|
||||
(Ok(_), None) => (),
|
||||
(Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
|
||||
(Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
|
||||
(Err(actual), Some(expected)) => assert_eq!(actual.description(), expected),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
@ -141,13 +150,22 @@ fn test_ed25519_from_pkcs8() {
|
||||
test::from_file(
|
||||
"tests/ed25519_from_pkcs8_tests.txt",
|
||||
|section, test_case| {
|
||||
use std::error::Error;
|
||||
|
||||
assert_eq!(section, "");
|
||||
let input = test_case.consume_bytes("Input");
|
||||
let error = test_case.consume_optional_string("Error");
|
||||
assert_eq!(
|
||||
Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&input)).is_ok(),
|
||||
error.is_none()
|
||||
);
|
||||
|
||||
match (
|
||||
Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&input)),
|
||||
error.clone(),
|
||||
) {
|
||||
(Ok(_), None) => (),
|
||||
(Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
|
||||
(Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
|
||||
(Err(actual), Some(expected)) => assert_eq!(actual.description(), expected),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
|
@ -3,7 +3,7 @@ Input = 308204bd020100300d06092a864886f70d0101010500048204a7308204a3020100028201
|
||||
|
||||
# The same key as above, with the last byte removed.
|
||||
Input = 308204bd020100300d06092a864886f70d0101010500048204a7308204a30201000282010100b9d7af84fa4184a5f22037ec8aff2db5f78bd8c21e714e579ae57c6398c4950f3a694b17bfccf488766159aec5bb7c2c43d59c798cbd45a09c9c86933f126879ee7eadcd404f61ecfc425197cab03946ba381a49ef3b4d0f60b17f8a747cde56a834a7f6008f35ffb2f60a54ceda1974ff2a9963aba7f80d4e2916a93d8c74bb1ba5f3b189a4e8f0377bd3e94b5cc3f9c53cb8c8c7c0af394818755e968b7a76d9cada8da7af5fbe25da2a09737d5e4e4d7092aa16a0718d7322ce8aca767015128d6d35775ea9cb8bb1ac6512e1b787d34015221be780a37b1d69bc3708bfd8832591be6095a768f0fd3b3457927e6ae3641d55799a29a0a269cb4a693bc14b0203010001028201001c5fb7e69fa6dd2fd0f5e653f12ce0b7c5a1ce6864e97bc2985dad4e2f86e4133d21d25b3fe774f658cca83aace9e11d8905d62c20b6cd28a680a77357cfe1afac201f3d1532898afb40cce0560bedd2c49fc833bd98da3d1cd03cded0c637d4173e62de865b572d410f9ba83324cd7a3573359428232f1628f6d104e9e6c5f380898b5570201cf11eb5f7e0c4933139c7e7fba67582287ffb81b84fa81e9a2d9739815a25790c06ead7abcf286bd43c6e3d009d01f15fca3d720bbea48b0c8ccf8764f3c822e61159d8efcbff38c794f8afe040b45df14c976a91b1b6d886a55b8e68969bcb30c7197920d97d7721d78d954d89ffecbcc93c6ee82a86fe754102818100eba1cbe453f5cb2fb7eabc12d697267d25785a8f7b43cc2cb14555d3618c63929b19839dcd4212397ecda8ad872f97ede6ac95ebda7322bbc9409bac2b24ae56ad62202800c670365ae28671195fe934978a5987bee2fcea06561b782630b066b0a35c3f559a281f0f729fc282ef8ebdbb065d60000223da6edb732fa32d82bb02818100c9e81e353315fd88eff53763ed7b3859f419a0a158f5155851ce0fe6e43188e44fb43dd25bcdb7f3839fe84a5db88c6525e5bcbae513bae5ff54398106bd8ae4d241c082f8a64a9089531f7b57b09af52042efa097140702dda55a2141c174dd7a324761267728a6cc4ce386c034393d855ebe985c4e5f2aec2bd3f2e2123ab1028180566889dd9c50798771397a68aa1ad9b970e136cc811676ac3901c51c741c48737dbf187de8c47eec68acc05b8a4490c164230c0366a36c2c52fc075a56a3e7eecf3c39b091c0336c2b5e00913f0de5f62c5046ceb9d88188cc740d34bd44839bd4d0c346527cea93a15596727d139e53c35eed25043bc4ac18950f237c02777b0281800f9dd98049e44088efee6a8b5b19f5c0d765880c12c25a154bb6817a5d5a0b798544aea76f9c58c707fe3d4c4b3573fe7ad0eb291580d22ae9f5ccc0d311a40590d1af1f3236427c2d72f57367d3ec185b9771cb5d041a8ab93409e59a9d68f99c72f91c658a3fe5aed59f9f938c368530a4a45f4a7c7155f3906c4354030ef102818100c89e0ba805c970abd84a70770d8fc57bfaa34748a58b77fcddaf0ca285db91953ef5728c1be7470da5540df6af56bb04c0f5ec500f83b08057664cb1551e1e29c58d8b1e9d70e23ed57fdf9936c591a83c1dc954f6654d4a245b6d8676d045c2089ffce537d234fc88e98d92afa92926c75b286e8fee70e273d762bbe63cd6
|
||||
Error = DECODE_ERROR
|
||||
Error = InvalidEncoding
|
||||
|
||||
# RSA 3072-bit key with e == 65537.
|
||||
Input = 308206fd020100300d06092a864886f70d0101010500048206e7308206e30201000282018100ac2d26e81b524ff75bb23d79c5eef2258546a1cbc9ce00cdb453449ad3af0d38d748bab51533ff39aabe9d21a0b1113f57764a6c27d10c97212296e3033814b8b1ec1d4b8cb00a4d8174dce02a7a73149d195ef83c3ee0334a8bf94d86dc0e8ba2a5ac80343e8124ead35dda110f106436813fae364113f8136a79f7791b035549dc7f7a1492ff0cbbbae937eb7e05ed997a3023bc3622def643a13aa4b20f15b4c293ccfd64a26db61623ae4fc69bac32162953cb37c93216c009ca217bc9b4cfa463e22b9d083d1c42f321cb8c248c29090194c0e5e94957ca2a34d62bcab2a12acfbb4565bf2576583a57fd78b810a7f7c70aec118e7e9bb7fba9c80c10acb8154af0e0e21ee4e488393c9dfd977aa7c245925fb5f880bf1074d916710630362c246f0270d70cbb546bd5ef07e423c37f1f446707c4d6c3874f9c7abfe80f873884911a6a98514b34ef147b1e7ff93c9497b57c73653f391d74bce6db9699cfb3fdca698427db519f08e33b16a7105b27f1387aa9958a674d777c1403e03302030100010282018043901045627b415fea7e9dfb0bfdc0cd9267ee139ee41492a3e14cf9887997b1a76125caeb40153616d767a78b7c102d8fef9e32a4c936ac935714688e99d21fcbc9c09125eaea90116dbf42c3c87b222aa78b09d3f2445e3c318329b5f2e24e4f0bbe0e2cf21e1153888fba83992ab07866ed8b3a44fd460ab06c9dfccae9daecf9f697fc3cd692b3941bf25299884ffd3ae26b136f16edf12b06b8916a41db1dac80fd1eadffc31781c68c9f476b4cfdf68e4f105e9ab7ea0f7f87eeedb96f723e2a17e5103af96c3a508d38262577ffe3b2fb7bb4f7150cdc9dfb8d4f3d5cdf349192d1d302182df169403a066ddb28647831041d587884282392f83716b74f201d33fa5a967d5f506a93e4e9506ecf6802869ead17beff0b8903114f154fa3973067d56003409cdefa962578096d664c79d2c5df6e8dbbf67a9bf6e2c7c938608c17ae1ef6e56fce9058fb4823c5cee63e2a1c9f495dca8021fcb50cd92a35a9de5df29755b8f0d6d677d8fb8144dd106f07782e63032e6f40f3c29c0de90281c100def986933a3b7fdcb21c7096a4ef361c6631a23aacc8831f34270efd4850eac191d9284070cc910cf12864efd6d8c676491ba8f810b005dc4143e7e774d2d4fa255007ec75a98f5fc105100ed49327e90d31f01771bfe92b1f47cb36eb8c2d30067d1523980b9329e73ff7ae84a8ae11276a085a201bef0b398f934e4bdd7eba261e676a4a933a4254934f6ad8c17277a977a7782da24000eec12cf8def48d86a73ac84e9dcf5b5e8dad32ceb4d565085c2063f88df9a4b1f200375d2a58c86f0281c100c5ad84dcac6f51bfefa20c2b52611bcec8822739ff907491912b7c0d80ddcdfe1836c264969048133e76d3c4987a563a2d7d3c3b213cf47e1cd9329df1878bc4834e9742e5d0a31c663d4fa8edd8e0abad1c5fe2e6fef1f01c35b93eff619c7ae80873842daa277096dd1f3da4b4182525d06c1041a9c8627be145c3435a79dba4dfe52f63fa51486762d1b55d449fb55f07d304fcc726b9cc1e42484bc6d72704e0192f4bb7e6c6438dbd9aecf8d10626bc2ce1904f96d7594b9fc0e8231e7d0281c050a322f519a92ceb8e8a5479567aa032130f3e21441d5bb62c3137ed877aa3fb8f185ec33747f3e91f49c17f2f4ec42f40ef3ce3417db710d9958a479d6b25d4b52bc541d1a7998f4289e72dc5d8d625253d7b1baf6a7d13b843498dba0fbec3d084e9e12e7a79253d5957e4885b4c602dc5ddf1620d581cd21b4765987029057f059dd6c5d38acd3432f614a90104b99bd30700a2583c175a41085794a21290b0e7c44b122d4c58dc99d77703d4ecade24b607c22343748974156c45dad30070281c100a8d548d2c91bd2b0a1d4bf9c08a214040ad0cefc0440b6aed55454819bfcd5411e2136ea7e8600691f4292202932e38e90e79397d50da0ac4dab5c45f5d21517e4262d9edf75d0ba22c05ed7233dc6b61a06500715cfcd878c307e6545ed729eaeaaf92e7d6a04816ef8b1040f361a213028d10319720f49be106b6b188d9fe26ef12367d476291233eafcbd70497a368851c073540a2c132838f7d79390e295dade23e477413c833d9343cb9c75eee0d8188424ab02af0c82a1ca7212525c690281c012315e04ad315f39c8c0657c93ed32ec2501c9cf2b3c3f6c07fc78ad95d9c5827201ef95d7f549ddba41a75ed1b2a5261037490d235c4f097a123dd454da7f2954a1ea4e612662e5086d6e532adef15506b2adf1aeb5237257df7193d85e2a4d61bbef24122deee62b41b73cf277486da9dee39311904e49fcf7e5cf7c1ba5da0b8e25853da1389b79753a894643ff8299d1c599130c9d0f25db07eafde4a1ee1e66f839c3b775000a5d8576f3b158d2cfe8cbec94376cb81d54c6066a4fc97f
|
||||
@ -16,16 +16,18 @@ Input = 308206ff020100300d06092a864886f70d0101010500048206e9308206e5020100028201
|
||||
|
||||
# RSA 2048-bit key with invalid e == 3.
|
||||
Input = 308204bc020100300d06092a864886f70d0101010500048204a6308204a20201000282010100bbb126534d64a3a60711730846af3c2f4cf4fee28f48e7c9ca2b0b5a6c8ad51e2509d38b87ea6b039ad3a33ac57e78c444d86438b1938eed73219cba33b06454e429330ce0fcd356624630c58f32a7ab3bef8c7cb3f9843b09c3e61dc92329df330f002451b5910cac3e7b513d3ca1cd58e39a5cc277e64da395058805f69f19bb62571f28525c5a7f781055ea82bddcc8d10c7163060e2040aeb390e6cd8cbba216726875d3b2975fae77d9d092a9e65f545f8a1e282c7096b3e8293d47d15e656717b0ea2d9a170d489c2f3b596cb745fd3f587e10cf3ff043a1f42ed9d030d900c02676761e70e2b5a8fd9387dc658cc95b1ac3ca83ce3b352d6e71514025020103028201007d20c43788edc26eaf60f75ad9ca281f88a354970a309a8686c75ce6f30738bec35be25d0546f2026737c2272e545082d89042d076625f48f76bbdd177caed8ded70ccb340a88ce441842083b4cc6fc77d4a5da877fbad7cb12d4413db6cc694ccb4aac2e123b60872d4523628d31688e5ed11932c4feede6d0e03b003f9bf6556ac08bfb5829df7f6baf74772fd3e22ca571851c5a0efe8330ffb45863a804f870f4535da65761c81c22decb3bd8fe55fb250b09fce0f12f1c1a073ab5349a8b9d8e3fb826a04f441479cf3b4ecb7d61aca60f44a3f1ffbe2bd615cb65c29b11beeff13074c06356ece01581b45fcfc2cab27a8777a631b3361763d59b7f26b02818100f6434d514907d7c9f522c84633148b5e2fccf3bc0fc4e6a5c5f7b88b15a062433dae12c53d5e54e2a47427da06b6ff4e2c4635b90aa8887b365b96e6485584f64138c39ef0d9108dc8f569f5cdac877c5d4bfad3a89dbda8f5e88d05277462b2636618c6f21f845ebbca664f1c7d5534c15ff90f5faffd712ecd2f130b8f808d02818100c31cfcae4f06979c983cd5248af2554a6981743aaacfbf9e2e1f021d87d56a0119d177d270dd2c89f8970b1cbc3f52c02382b0c823ca8d58f5b5e09573f55deb0d68fe18b5b5821ae267c6cbde49d179c081b3166614619d263f02e3f5db2ef4cbb428c2f96490c200b640aa4e218bb68868a68eb0e2f1b43f55ccff5f2dd3f902818100a42cde3630afe5314e17302eccb85ce975334d280a83446e83fa7b0763c04182291eb72e28e98dec6da2c53c0479ff8972d97926071b05a779926499858e58a42b7b2d14a090b5b3db4e46a3de7304fd9387fc8d1b13d3c5f945b358c4f841cc42441084a16a583f27dc4434bda8e37880eaa60a3fcaa8f61f3374b75d0a55b3028181008213531edf59ba68657de36db1f6e386f100f8271c8a7fbec96a01690538f15611364fe1a0937306a5ba07687d7f8c8017ac75dac28708e5f923eb0e4d4e3e9cb39b54107923ac11ec452f32943136512b01220eeeb841136ed4ac97f93cc9f887cd7081fb98608155ced5c6dec107cf059b19b475eca122d4e3ddff94c937fb0281805d84a6c335b77a5d2468b81cab4ab69198906454bb499b00c8094456b855987dd20a95a5be48f21067554b86df117cc9abab45dca04265fb589606b2cbc074808f39862cbf39e3efd1df44e04fcd9f778574528fcb52f5b7e16066267cf08d29ce7a29deb3d9c3671634af765916a865646accbdec557d970de3b242e3450167
|
||||
Error = DECODE_ERROR
|
||||
Error = TooSmall
|
||||
|
||||
# A valid ECC P-256 key.
|
||||
Input = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420090460075f15d2a256248000fb02d83ad77593dde4ae59fc5e96142dffb2bd07a14403420004cf0d13a3a7577231ea1b66cf4021cd54f21f4ac4f5f2fdd28e05bc7d2bd099d1374cd08d2ef654d6f04498db462f73e0282058dd661a4c9b0437af3f7af6e724
|
||||
Error = DECODE_ERROR
|
||||
Error = WrongAlgorithm
|
||||
|
||||
# An RSAPrivateKey, but with an AlgorithmIdentifier of ecPublicKey w/ P-256.
|
||||
Input = 308189020100301306072A8648CE3D020106082A8648CE3D0301070500046d306b0201010420090460075f15d2a256248000fb02d83ad77593dde4ae59fc5e96142dffb2bd07a14403420004cf0d13a3a7577231ea1b66cf4021cd54f21f4ac4f5f2fdd28e05bc7d2bd099d1374cd08d2ef654d6f04498db462f73e0282058dd661a4c9b0437af3f7af6e724
|
||||
Error = DECODE_ERROR
|
||||
Error = WrongAlgorithm
|
||||
|
||||
# The AlgorithmIdentifier is rsaEncryption, but it contains a P-256 ECPrivateKey.
|
||||
# TODO: This should be "InvalidEncoding"; that would require delaying the version
|
||||
# validation until more parsing is done.
|
||||
Input = 308181020100300d06092a864886f70d0101010500046d306b0201010420090460075f15d2a256248000fb02d83ad77593dde4ae59fc5e96142dffb2bd07a14403420004cf0d13a3a7577231ea1b66cf4021cd54f21f4ac4f5f2fdd28e05bc7d2bd099d1374cd08d2ef654d6f04498db462f73e0282058dd661a4c9b0437af3f7af6e724
|
||||
Error = DECODE_ERROR
|
||||
Error = VersionNotSupported
|
||||
|
@ -43,6 +43,8 @@ use ring::rand;
|
||||
#[test]
|
||||
fn rsa_from_pkcs8_test() {
|
||||
test::from_file("tests/rsa_from_pkcs8_tests.txt", |section, test_case| {
|
||||
use std::error::Error;
|
||||
|
||||
assert_eq!(section, "");
|
||||
|
||||
let input = test_case.consume_bytes("Input");
|
||||
@ -50,10 +52,12 @@ fn rsa_from_pkcs8_test() {
|
||||
|
||||
let error = test_case.consume_optional_string("Error");
|
||||
|
||||
assert_eq!(
|
||||
signature::RSAKeyPair::from_pkcs8(input).is_ok(),
|
||||
error.is_none()
|
||||
);
|
||||
match (signature::RSAKeyPair::from_pkcs8(input), error) {
|
||||
(Ok(_), None) => (),
|
||||
(Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
|
||||
(Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
|
||||
(Err(actual), Some(expected)) => assert_eq!(actual.description(), expected),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user