diff --git a/Cargo.toml b/Cargo.toml index 92f8124..a23c5d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,22 +13,26 @@ keywords = ["ssh", "ssh-keys", "keys", "rsa", "openssh"] license = "MIT OR Apache-2.0" exclude = [".github", ".gitignore", "examples", "fixtures"] +[features] +default = ["std"] +std = ["base64/std", "byteorder/std", "md-5/std", "sha2/std", "thiserror/std"] + [dependencies] # Private dependencies. -base64 = "0.21" -byteorder = "1.1" +base64 = { version = "0.21", default-features = false, features = ["alloc"] } +byteorder = { version = "1.1", default-features = false } # Do not use a range on the crates md-5 or sha2. RustCrypto crate # versions cannot be mixed and matched. Doing so will cause hard # to understand build failures. Read about it at # https://github.com/coreos/openssh-keys/issues/89 -md-5 = "0.10" -sha2 = "0.10" -thiserror = "1.0" +md-5 = { version = "0.10", default-features = false } +sha2 = { version = "0.10", default-features = false } +thiserror = { version = "2.0", default-features = false } # Public dependencies, exposed through library API. # [dev-dependencies] -home = "~0.5" +home = "=0.5.9" [package.metadata.release] publish = false diff --git a/docs/release-notes.md b/docs/release-notes.md index 914d63d..6eb3e05 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -2,6 +2,10 @@ ## Upcoming openssh-keys 0.6.5 (unreleased) +Features: + +- support no_std contexts + Fixes: - Allow parsing comments containing whitespace diff --git a/src/lib.rs b/src/lib.rs index 3084988..0dcc3e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,9 @@ //! println!(" * Pubkey #{} -> {}", i + 1, pubkey.to_fingerprint_string()); //! } //! } +#![cfg_attr(not(any(feature = "std", test)), no_std)] + +extern crate alloc; mod reader; mod writer; @@ -34,10 +37,13 @@ mod writer; pub mod errors { use thiserror::Error; - pub type Result = std::result::Result; + use alloc::string::String; + + pub type Result = core::result::Result; #[derive(Error, Debug)] pub enum OpenSSHKeyError { + #[cfg(any(feature = "std", test, doc))] #[error("I/O error")] IO { #[from] @@ -47,7 +53,7 @@ pub mod errors { #[error("invalid UTF-8")] InvalidUtf8 { #[from] - source: std::str::Utf8Error, + source: core::str::Utf8Error, }, // keep base64::DecodeError out of the public API @@ -74,8 +80,12 @@ use sha2::{Digest, Sha256}; use crate::reader::Reader; use crate::writer::Writer; -use std::fmt; -use std::io::{BufRead, BufReader, Read}; +use core::fmt; + +use alloc::borrow::ToOwned; +use alloc::format; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; const SSH_RSA: &str = "ssh-rsa"; const SSH_DSA: &str = "ssh-dss"; @@ -185,7 +195,7 @@ impl core::cmp::PartialEq for PublicKey { } } -impl std::str::FromStr for PublicKey { +impl core::str::FromStr for PublicKey { type Err = OpenSSHKeyError; fn from_str(s: &str) -> Result { PublicKey::parse(s) @@ -398,13 +408,15 @@ impl PublicKey { /// read_keys takes a reader and parses it as an authorized_keys file. it /// returns an error if it can't read or parse any of the public keys in the /// list. + #[cfg(any(feature = "std", test, doc))] pub fn read_keys(r: R) -> Result> where - R: Read, + R: std::io::Read, { + use std::io::{BufRead, BufReader}; let keybuf = BufReader::new(r); // authorized_keys files are newline-separated lists of public keys - let mut keys = vec![]; + let mut keys = Vec::new(); for key in keybuf.lines() { let key = key?; // skip any empty lines and any comment lines (prefixed with '#') diff --git a/src/reader.rs b/src/reader.rs index 94bc314..f5f79f2 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -23,7 +23,7 @@ impl<'a> Reader<'a> { } pub fn read_string(&mut self) -> Result<&'a str> { - Ok(std::str::from_utf8(self.read_bytes()?)?) + Ok(core::str::from_utf8(self.read_bytes()?)?) } pub fn read_mpint(&mut self) -> Result<&'a [u8]> { diff --git a/src/writer.rs b/src/writer.rs index e17bf8b..66dced5 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -1,6 +1,8 @@ //! This module provides a struct for writing bytes in the OpenSSH public key format. -use byteorder::{BigEndian, WriteBytesExt}; +use byteorder::{BigEndian, ByteOrder}; + +use alloc::vec::Vec; pub struct Writer { data: Vec, @@ -8,7 +10,7 @@ pub struct Writer { impl Writer { pub fn new() -> Writer { - Writer { data: vec![] } + Writer { data: Vec::new() } } pub fn into_vec(self) -> Vec { @@ -16,9 +18,9 @@ impl Writer { } pub fn write_int(&mut self, val: u32) { - if self.data.write_u32::(val).is_err() { - unreachable!() - }; + let mut buf = [0; 4]; + BigEndian::write_u32(&mut buf, val); + self.data.extend_from_slice(&buf); } pub fn write_bytes(&mut self, mut buf: Vec) {