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
14 changes: 8 additions & 6 deletions .github/workflows/yescrypt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ jobs:
with:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
- uses: RustCrypto/actions/cargo-hack-install@master
- run: ${{ matrix.deps }}
- run: cargo test
- run: cargo test --release
- run: cargo check --target ${{ matrix.target }} --all-features
- run: cargo hack test --target ${{ matrix.target }} --feature-powerset
- run: cargo test --target ${{ matrix.target }} --all-features --release

careful:
runs-on: ubuntu-latest
Expand All @@ -61,8 +63,8 @@ jobs:
with:
toolchain: nightly-2025-08-10
- run: cargo install cargo-careful
- run: cargo careful test
- run: cargo careful test --release
- run: cargo careful test --all-features
- run: cargo careful test --all-features --release

cross:
strategy:
Expand All @@ -81,5 +83,5 @@ jobs:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
- uses: RustCrypto/actions/cross-install@master
- run: cross test --target ${{ matrix.target }}
- run: cross test --release --target ${{ matrix.target }}
- run: cross test --target ${{ matrix.target }} --all-features
- run: cross test --target ${{ matrix.target }} --all-features --release
86 changes: 45 additions & 41 deletions yescrypt/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// TODO(tarcieri): use `base64ct` instead?

use crate::{Error, Result};

#[cfg(feature = "simple")]
use core::str;

/// (s)crypt-flavored Base64 alphabet.
Expand All @@ -18,6 +20,7 @@ pub const ATOI64: [u8; 128] = {
tbl
};

#[cfg(feature = "simple")]
pub(crate) fn decode64<'o>(src: &str, dst: &'o mut [u8]) -> Result<&'o [u8]> {
let src = src.as_bytes();
let mut pos = 0usize;
Expand Down Expand Up @@ -108,6 +111,48 @@ pub(crate) fn decode64_uint32(src: &[u8], mut pos: usize, min: u32) -> Result<(u
Ok((dst, pos))
}

#[cfg(feature = "simple")]
pub(crate) fn encode64<'o>(src: &[u8], out: &'o mut [u8]) -> Result<&'o str> {
fn encode64_uint32_fixed(dst: &mut [u8], mut src: u32, srcbits: u32) -> Result<usize> {
let mut bits: u32 = 0;
let mut pos = 0;

while bits < srcbits {
if dst.len() <= pos {
return Err(Error::Encoding);
}

dst[pos] = ITOA64[(src & 0x3f) as usize];
pos += 1;
src >>= 6;
bits += 6;
}

if src != 0 || dst.len() < pos {
return Err(Error::Encoding);
}

Ok(pos)
}

let mut pos = 0;
let mut i = 0;

while i < src.len() {
let mut value = 0u32;
let mut bits = 0u32;
while bits < 24 && i < src.len() {
value |= (src[i] as u32) << bits;
bits += 8;
i += 1;
}
let dnext = encode64_uint32_fixed(&mut out[pos..], value, bits)?;
pos += dnext;
}

str::from_utf8(&out[..pos]).map_err(|_| Error::Encoding)
}

pub(crate) fn encode64_uint32(dst: &mut [u8], mut src: u32, min: u32) -> Result<usize> {
let mut start = 0u32;
let mut end = 47u32;
Expand Down Expand Up @@ -152,44 +197,3 @@ pub(crate) fn encode64_uint32(dst: &mut [u8], mut src: u32, min: u32) -> Result<

Ok(pos)
}

pub(crate) fn encode64<'o>(src: &[u8], out: &'o mut [u8]) -> Result<&'o str> {
let mut pos = 0;
let mut i = 0;

while i < src.len() {
let mut value = 0u32;
let mut bits = 0u32;
while bits < 24 && i < src.len() {
value |= (src[i] as u32) << bits;
bits += 8;
i += 1;
}
let dnext = encode64_uint32_fixed(&mut out[pos..], value, bits)?;
pos += dnext;
}

str::from_utf8(&out[..pos]).map_err(|_| Error::Encoding)
}

fn encode64_uint32_fixed(dst: &mut [u8], mut src: u32, srcbits: u32) -> Result<usize> {
let mut bits: u32 = 0;
let mut pos = 0;

while bits < srcbits {
if dst.len() <= pos {
return Err(Error::Encoding);
}

dst[pos] = ITOA64[(src & 0x3f) as usize];
pos += 1;
src >>= 6;
bits += 6;
}

if src != 0 || dst.len() < pos {
return Err(Error::Encoding);
}

Ok(pos)
}
6 changes: 5 additions & 1 deletion yescrypt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@
//! let password = b"pleaseletmein"; // don't actually use this as a password!
//! let salt = b"WZaPV7LSUEKMo34."; // unique per password, ideally 16-bytes and random
//! let password_hash = yescrypt::yescrypt(password, salt, &Default::default())?;
//! assert_eq!(&password_hash[..3], "$y$");
//! assert!(password_hash.starts_with("$y$"));
//!
//! // verify password is correct for the given hash
//! yescrypt::yescrypt_verify(password, &password_hash)?;
//! # Ok(())
//! # }
//! ```
Expand Down Expand Up @@ -122,6 +125,7 @@ pub fn yescrypt(passwd: &[u8], salt: &[u8], params: &Params) -> Result<String> {
/// Verify a password matches the given yescrypt password hash.
///
/// Password hash should begin with `$y$` in Modular Crypt Format (MCF).
#[cfg(feature = "simple")]
pub fn yescrypt_verify(passwd: &[u8], hash: &str) -> Result<()> {
let hash = mcf::PasswordHashRef::try_from(hash).map_err(|_| Error::Encoding)?;

Expand Down
4 changes: 2 additions & 2 deletions yescrypt/tests/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#![cfg(feature = "simple")]
#![allow(non_snake_case)]

use yescrypt::{Flags, Params, yescrypt, yescrypt_verify};
use yescrypt::{Error, Flags, Params, yescrypt, yescrypt_verify};

const YESCRYPT_P: u32 = 11;

Expand Down Expand Up @@ -74,7 +74,7 @@ fn verify_reference_strings() {
panic!("failed to verify password hash: {hash}");
}

if yescrypt_verify(b"bogus", hash).is_ok() {
if yescrypt_verify(b"bogus", hash) != Err(Error::Password) {
panic!("verification unexpectedly succeeded for password hash: {hash}");
}
}
Expand Down