Minor fixups and doc updates.

This commit is contained in:
2025-12-29 02:03:32 -07:00
parent ddf44d7e33
commit f80204aced
7 changed files with 46 additions and 23 deletions

2
Cargo.lock generated
View File

@@ -4,4 +4,4 @@ version = 4
[[package]] [[package]]
name = "emsha" name = "emsha"
version = "1.0.0" version = "1.0.1"

View File

@@ -5,7 +5,7 @@ repository = "https://git.wntrmute.dev/wntrmute/emsha-rs"
categories = ["cryptography", "no-std", "embedded"] categories = ["cryptography", "no-std", "embedded"]
keywords = ["sha256", "hmac", "hash", "embedded", "no_std"] keywords = ["sha256", "hmac", "hash", "embedded", "no_std"]
license-file = "LICENSE" license-file = "LICENSE"
version = "1.0.0" version = "1.0.1"
edition = "2024" edition = "2024"
publish = ["kellnr"] publish = ["kellnr"]

View File

@@ -1,6 +1,6 @@
//! HMAC-SHA256 implementation. //! HMAC-SHA256 implementation.
use crate::{sha256, Code, Error, Hash, Result}; use crate::{Code, Error, Hash, Result, sha256};
use core::fmt; use core::fmt;
use core::fmt::Formatter; use core::fmt::Formatter;
@@ -11,12 +11,13 @@ enum State {
Finished, Finished,
} }
pub const KEY_LENGTH: usize = 64; const KEY_LENGTH: usize = 64;
const IPAD: u8 = 0x36; const IPAD: u8 = 0x36;
const OPAD: u8 = 0x5c; const OPAD: u8 = 0x5c;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
/// HMAC_SHA256 is a keyed message authentication function.
pub struct HMAC_SHA256 { pub struct HMAC_SHA256 {
state: State, state: State,
ctx: sha256::SHA256, ctx: sha256::SHA256,
@@ -36,6 +37,7 @@ impl fmt::Display for HMAC_SHA256 {
} }
impl HMAC_SHA256 { impl HMAC_SHA256 {
/// Construct a new HMAC-SHA256 instance with the provided key.
pub fn new(k: &[u8]) -> Result<Self> { pub fn new(k: &[u8]) -> Result<Self> {
let mut ik: [u8; KEY_LENGTH] = [0; KEY_LENGTH]; let mut ik: [u8; KEY_LENGTH] = [0; KEY_LENGTH];
let mut ctx = sha256::SHA256::default(); let mut ctx = sha256::SHA256::default();
@@ -157,8 +159,4 @@ impl Hash for HMAC_SHA256 {
self.copy_digest(digest) self.copy_digest(digest)
} }
fn size() -> usize {
sha256::SIZE
}
} }

View File

@@ -1,12 +1,28 @@
//! emsha is the embedded hashing library. It aims to work even in //! emsha is the embedded hashing library. It aims to work even in
//! nostdenv environments. //! nostdenv environments.
//!
//! ## Example SHA256 hashing
//! ```
//! use emsha::{Hash, sha256};
//! # use emsha::Result;
//! # fn main() -> Result<()> {
//! let mut h = sha256::SHA256::new();
//! let mut d: [u8; sha256::SIZE] = [0; sha256::SIZE];
//! h.update(b"hello, world!")?;
//! h.finalize(&mut d)?;
//! println!("{:?}", d);
//! # Ok(())
//! # }
//! ```
#![no_std] #![no_std]
#![warn(missing_docs)]
use core::error; use core::error;
use core::fmt; use core::fmt;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// Error is a standardized error type for the emsha package.
pub struct Error { pub struct Error {
reason: Code, reason: Code,
} }
@@ -16,7 +32,6 @@ impl fmt::Display for Error {
match self.reason { match self.reason {
Code::Unknown => write!(f, "unknown error"), Code::Unknown => write!(f, "unknown error"),
Code::OK => write!(f, "OK"), Code::OK => write!(f, "OK"),
Code::TestFailure => write!(f, "test failure"),
Code::InvalidState => write!(f, "invalid state"), Code::InvalidState => write!(f, "invalid state"),
Code::InputTooLong => write!(f, "input is too long"), Code::InputTooLong => write!(f, "input is too long"),
Code::BufferTooSmall => { Code::BufferTooSmall => {
@@ -30,6 +45,7 @@ impl fmt::Display for Error {
} }
impl Error { impl Error {
/// Construct an error with a `emsha::Code`.
pub fn with(reason: Code) -> Self { pub fn with(reason: Code) -> Self {
Self { reason } Self { reason }
} }
@@ -38,18 +54,33 @@ impl Error {
impl error::Error for Error {} impl error::Error for Error {}
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
/// Common error codes for emsha.
pub enum Code { pub enum Code {
Unknown, /// This is used internally to denote a Hash is in a good state.
OK, OK,
TestFailure,
/// The Hash is in an invalid state and cannot be used except
/// maybe via a reset. This is a serious issue.
InvalidState, InvalidState,
/// The input passed to the hash is too long.
InputTooLong, InputTooLong,
/// A buffer passed to a hash function was not large enough.
BufferTooSmall, BufferTooSmall,
/// An attempt was made to get the result of a hash before it was
/// finalized.
HashNotFinalized, HashNotFinalized,
/// An unknown error has occurred.
Unknown,
} }
/// Result is a convenience type for results returned from this package.
pub type Result<T> = core::result::Result<T, Error>; pub type Result<T> = core::result::Result<T, Error>;
/// Hash implements a secure hashing algorithm.
pub trait Hash { pub trait Hash {
/// Bring the Hash back to its initial state. /// Bring the Hash back to its initial state.
/// ///
@@ -82,12 +113,6 @@ pub trait Hash {
/// The Hash must keep enough state for repeated calls to result /// The Hash must keep enough state for repeated calls to result
/// to work. /// to work.
fn result(&self, digest: &mut [u8]) -> Result<()>; fn result(&self, digest: &mut [u8]) -> Result<()>;
/// Return the output size of the Hash.
///
/// This is how large the buffers written to by result should
/// be.
fn size() -> usize;
} }
mod common; mod common;

View File

@@ -1,3 +1,5 @@
//! SHA-256 implementation of the `Hash` type.
use crate::common::*; use crate::common::*;
use crate::{Code, Error, Hash, Result}; use crate::{Code, Error, Hash, Result};
use core::fmt; use core::fmt;
@@ -26,6 +28,7 @@ const H0: [u32; 8] = [
const MB_SIZE: usize = 64; const MB_SIZE: usize = 64;
/// SIZE is the output size for a SHA-256 digest.
pub const SIZE: usize = 32; pub const SIZE: usize = 32;
fn u32_to_chunk_in_place(x: u32, chunk: &mut [u8]) { fn u32_to_chunk_in_place(x: u32, chunk: &mut [u8]) {
@@ -37,6 +40,7 @@ fn u32_to_chunk_in_place(x: u32, chunk: &mut [u8]) {
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
/// SHA-256 is described in RFC 6234.
pub struct SHA256 { pub struct SHA256 {
mlen: u64, mlen: u64,
i_hash: [u32; 8], i_hash: [u32; 8],
@@ -66,6 +70,7 @@ impl Default for SHA256 {
} }
impl SHA256 { impl SHA256 {
/// Construct a new SHA256 context.
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
mlen: 0, mlen: 0,
@@ -329,10 +334,6 @@ impl Hash for SHA256 {
self.copy_out_digest(digest); self.copy_out_digest(digest);
Ok(()) Ok(())
} }
fn size() -> usize {
SIZE
}
} }
fn run_test(input: &[u8], expected: &[u8]) -> Result<()> { fn run_test(input: &[u8], expected: &[u8]) -> Result<()> {

View File

@@ -1,6 +1,6 @@
mod common; mod common;
use common::hexstr; use common::hexstr;
use emsha::{hmac, sha256, Hash, Result}; use emsha::{Hash, Result, hmac, sha256};
#[test] #[test]
fn test_hmac_00() -> Result<()> { fn test_hmac_00() -> Result<()> {

View File

@@ -63,7 +63,6 @@ fn test_golden_tests() -> Result<()> {
let mut s: [u8; 64] = [0; 64]; let mut s: [u8; 64] = [0; 64];
while i < golden_tests.len() { while i < golden_tests.len() {
eprintln!("golden test: {:}", i);
h.update(golden_tests[i].input)?; h.update(golden_tests[i].input)?;
h.finalize(&mut d)?; h.finalize(&mut d)?;
hexstr(&d, &mut s); hexstr(&d, &mut s);