Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 36 additions & 41 deletions ssh-encoding/src/mpint.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Multiple precision integer
//! Multiple precision integer.

use crate::{CheckedSum, Decode, Encode, Error, Reader, Result, Writer};
use alloc::{boxed::Box, vec::Vec};
Expand Down Expand Up @@ -48,34 +48,42 @@ pub struct Mpint {
}

impl Mpint {
/// Create a new multiple precision integer from the given
/// big endian-encoded byte slice.
/// Create a new multiple precision integer from the given big endian-encoded byte slice.
///
/// Note that this method expects a leading zero on positive integers whose
/// MSB is set, but does *NOT* expect a 4-byte length prefix.
/// Note that this method expects a leading zero on positive integers whose MSB is set, but does
/// *NOT* expect a 4-byte length prefix.
///
/// # Errors
/// Returns [`Error::MpintEncoding`] in the event of an unnecessary leading `0`.
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
bytes.try_into()
}

/// Create a new multiple precision integer from the given big endian
/// encoded byte slice representing a positive integer.
/// Create a new multiple precision integer from the given big endian encoded byte slice
/// representing a positive integer.
///
/// The input may begin with leading zeros, which will be stripped when
/// converted to [`Mpint`] encoding.
pub fn from_positive_bytes(mut bytes: &[u8]) -> Result<Self> {
let mut inner = Vec::with_capacity(bytes.len());

/// The input may begin with leading zeros, which will be stripped when converted to [`Mpint`]
/// encoding.
pub fn from_positive_bytes(mut bytes: &[u8]) -> Self {
// Strip leading zeros
while bytes.first().copied() == Some(0) {
bytes = &bytes[1..];
}

match bytes.first().copied() {
Some(n) if n >= 0x80 => inner.push(0),
_ => (),
// Add a leading zero to the output if necessary
let inner = match bytes.first().copied() {
Some(n) if n >= 0x80 => {
let mut inner = Vec::with_capacity(bytes.len().saturating_add(1));
inner.push(0);
inner.extend_from_slice(bytes);
inner
}
_ => Vec::from(bytes),
};

Self {
inner: inner.into_boxed_slice(),
}

inner.extend_from_slice(bytes);
inner.into_boxed_slice().try_into()
}

/// Get the big integer data encoded as big endian bytes.
Expand Down Expand Up @@ -208,21 +216,17 @@ impl fmt::UpperHex for Mpint {
}

#[cfg(feature = "bigint")]
impl TryFrom<Uint> for Mpint {
type Error = Error;

fn try_from(uint: Uint) -> Result<Mpint> {
Mpint::try_from(&uint)
impl From<&Uint> for Mpint {
fn from(uint: &Uint) -> Mpint {
let bytes = Zeroizing::new(uint.to_be_bytes());
Mpint::from_positive_bytes(&bytes)
}
}

#[cfg(feature = "bigint")]
impl TryFrom<&Uint> for Mpint {
type Error = Error;

fn try_from(uint: &Uint) -> Result<Mpint> {
let bytes = Zeroizing::new(uint.to_be_bytes());
Mpint::from_positive_bytes(&bytes)
impl From<Uint> for Mpint {
fn from(uint: Uint) -> Mpint {
Mpint::from(&uint)
}
}

Expand Down Expand Up @@ -278,18 +282,9 @@ mod tests {
}
#[test]
fn from_positive_bytes_strips_leading_zeroes() {
assert_eq!(
Mpint::from_positive_bytes(&hex!("00")).unwrap().as_ref(),
b""
);
assert_eq!(
Mpint::from_positive_bytes(&hex!("00 00")).unwrap().as_ref(),
b""
);
assert_eq!(
Mpint::from_positive_bytes(&hex!("00 01")).unwrap().as_ref(),
b"\x01"
);
assert_eq!(Mpint::from_positive_bytes(&hex!("00")).as_ref(), b"");
assert_eq!(Mpint::from_positive_bytes(&hex!("00 00")).as_ref(), b"");
assert_eq!(Mpint::from_positive_bytes(&hex!("00 01")).as_ref(), b"\x01");
}

// TODO(tarcieri): drop support for negative numbers?
Expand Down
56 changes: 24 additions & 32 deletions ssh-key/src/private/dsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,40 +104,36 @@ impl Drop for DsaPrivateKey {
}

#[cfg(feature = "dsa")]
impl TryFrom<DsaPrivateKey> for Uint {
type Error = Error;

fn try_from(key: DsaPrivateKey) -> Result<Uint> {
Ok(Uint::try_from(&key.inner)?)
impl From<&dsa::SigningKey> for DsaPrivateKey {
fn from(key: &dsa::SigningKey) -> DsaPrivateKey {
DsaPrivateKey {
inner: key.x().as_ref().into(),
}
}
}

#[cfg(feature = "dsa")]
impl TryFrom<&DsaPrivateKey> for Uint {
type Error = Error;

fn try_from(key: &DsaPrivateKey) -> Result<Uint> {
Ok(Uint::try_from(&key.inner)?)
impl From<dsa::SigningKey> for DsaPrivateKey {
fn from(key: dsa::SigningKey) -> DsaPrivateKey {
DsaPrivateKey::from(&key)
}
}

#[cfg(feature = "dsa")]
impl TryFrom<dsa::SigningKey> for DsaPrivateKey {
impl TryFrom<DsaPrivateKey> for Uint {
type Error = Error;

fn try_from(key: dsa::SigningKey) -> Result<DsaPrivateKey> {
DsaPrivateKey::try_from(&key)
fn try_from(key: DsaPrivateKey) -> Result<Uint> {
Ok(Uint::try_from(&key.inner)?)
}
}

#[cfg(feature = "dsa")]
impl TryFrom<&dsa::SigningKey> for DsaPrivateKey {
impl TryFrom<&DsaPrivateKey> for Uint {
type Error = Error;

fn try_from(key: &dsa::SigningKey) -> Result<DsaPrivateKey> {
Ok(DsaPrivateKey {
inner: key.x().as_ref().try_into()?,
})
fn try_from(key: &DsaPrivateKey) -> Result<Uint> {
Ok(Uint::try_from(&key.inner)?)
}
}

Expand All @@ -161,7 +157,7 @@ impl DsaKeypair {
#[cfg(all(feature = "dsa", feature = "rand_core"))]
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Result<Self> {
let components = dsa::Components::generate(rng, Self::KEY_SIZE);
dsa::SigningKey::generate(rng, components).try_into()
Ok(dsa::SigningKey::generate(rng, components).into())
}

/// Create a new [`DsaKeypair`] with the given `public` and `private` components.
Expand Down Expand Up @@ -258,22 +254,18 @@ impl TryFrom<&DsaKeypair> for dsa::SigningKey {
}

#[cfg(feature = "dsa")]
impl TryFrom<dsa::SigningKey> for DsaKeypair {
type Error = Error;

fn try_from(key: dsa::SigningKey) -> Result<DsaKeypair> {
DsaKeypair::try_from(&key)
impl From<dsa::SigningKey> for DsaKeypair {
fn from(key: dsa::SigningKey) -> DsaKeypair {
DsaKeypair::from(&key)
}
}

#[cfg(feature = "dsa")]
impl TryFrom<&dsa::SigningKey> for DsaKeypair {
type Error = Error;

fn try_from(key: &dsa::SigningKey) -> Result<DsaKeypair> {
Ok(DsaKeypair {
private: key.try_into()?,
public: key.verifying_key().try_into()?,
})
impl From<&dsa::SigningKey> for DsaKeypair {
fn from(key: &dsa::SigningKey) -> DsaKeypair {
DsaKeypair {
private: key.into(),
public: key.verifying_key().into(),
}
}
}
8 changes: 4 additions & 4 deletions ssh-key/src/private/rsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,10 @@ impl TryFrom<&rsa::RsaPrivateKey> for RsaKeypair {
let iqmp = key.crt_coefficient().ok_or(Error::Crypto)?;

let private = RsaPrivateKey {
d: key.d().try_into()?,
iqmp: iqmp.try_into()?,
p: p.try_into()?,
q: q.try_into()?,
d: key.d().into(),
iqmp: iqmp.into(),
p: p.into(),
q: q.into(),
};

Ok(RsaKeypair { public, private })
Expand Down
26 changes: 11 additions & 15 deletions ssh-key/src/public/dsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,20 @@ impl TryFrom<&DsaPublicKey> for dsa::VerifyingKey {
}

#[cfg(feature = "dsa")]
impl TryFrom<dsa::VerifyingKey> for DsaPublicKey {
type Error = Error;

fn try_from(key: dsa::VerifyingKey) -> Result<DsaPublicKey> {
DsaPublicKey::try_from(&key)
impl From<dsa::VerifyingKey> for DsaPublicKey {
fn from(key: dsa::VerifyingKey) -> DsaPublicKey {
DsaPublicKey::from(&key)
}
}

#[cfg(feature = "dsa")]
impl TryFrom<&dsa::VerifyingKey> for DsaPublicKey {
type Error = Error;

fn try_from(key: &dsa::VerifyingKey) -> Result<DsaPublicKey> {
Ok(DsaPublicKey {
p: key.components().p().as_ref().try_into()?,
q: key.components().q().as_ref().try_into()?,
g: key.components().g().as_ref().try_into()?,
y: key.y().as_ref().try_into()?,
})
impl From<&dsa::VerifyingKey> for DsaPublicKey {
fn from(key: &dsa::VerifyingKey) -> DsaPublicKey {
DsaPublicKey {
p: key.components().p().as_ref().into(),
q: key.components().q().as_ref().into(),
g: key.components().g().as_ref().into(),
y: key.y().as_ref().into(),
}
}
}
4 changes: 1 addition & 3 deletions ssh-key/src/public/rsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,7 @@ impl TryFrom<&rsa::RsaPublicKey> for RsaPublicKey {
type Error = Error;

fn try_from(key: &rsa::RsaPublicKey) -> Result<RsaPublicKey> {
let e = Mpint::try_from(key.e())?;
let n = Mpint::try_from(key.n().as_ref())?;
RsaPublicKey::new(e, n)
RsaPublicKey::new(key.e().into(), key.n().as_ref().into())
}
}

Expand Down
4 changes: 2 additions & 2 deletions ssh-key/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,8 @@ macro_rules! impl_signature_for_curve {
#[allow(clippy::arithmetic_side_effects)]
let mut data = Vec::with_capacity($size * 2 + 4 * 2 + 2);

Mpint::from_positive_bytes(&r)?.encode(&mut data)?;
Mpint::from_positive_bytes(&s)?.encode(&mut data)?;
Mpint::from_positive_bytes(&r).encode(&mut data)?;
Mpint::from_positive_bytes(&s).encode(&mut data)?;

Ok(Signature {
algorithm: Algorithm::Ecdsa {
Expand Down
Loading