Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Bcrypt hashing #27

Merged
merged 26 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2352887
Add Bcrypt hashing
Jujumba May 19, 2023
bdbb219
feat(common): ByteInput: paint component in red instead of showing no…
TheBestTvarynka May 14, 2023
1f3f057
small refactoring
TheBestTvarynka May 14, 2023
acd108b
fix(common): ByteInput: formatting on input data change
TheBestTvarynka May 14, 2023
67b3044
Add Bcrypt hashing
Jujumba May 19, 2023
52c674c
Bcrypt: Add salt parsing
Jujumba May 20, 2023
d6bb548
fix(crypto-helper): bcrypt: salt input
TheBestTvarynka May 20, 2023
955f536
Bcrypt: implement convertion BcryptAction -> bool
Jujumba May 20, 2023
40bf207
Bcrypt: Add switch and verify callback (bugged)
Jujumba May 21, 2023
f9e014e
Merge branch 'temp' into Bcrypt
Jujumba May 21, 2023
906b512
fix(crypto-helper): bcrypt: salt input
TheBestTvarynka May 20, 2023
dc2c55e
fix(crypto-helper): bcrypt: switcher works now;
TheBestTvarynka May 21, 2023
fdae766
computations.rs: refactor: check salt len once in `hash_bcrypt()`
Jujumba May 21, 2023
cc74730
bcrypt: refactor: refactor boss code😎 and remove unused code
Jujumba May 21, 2023
a749395
bcrypt: impl default for BcryptHashAction
Jujumba May 21, 2023
e88bf66
Apply cargo fmt code-style checks
Jujumba May 21, 2023
df3c973
algorithm.rs: add custom (de)serializers
Jujumba May 21, 2023
a514616
bcrypt: rename BI -> BcryptInputData
Jujumba May 21, 2023
a07fd3f
computations: merge bcrypt processing function into one and apply
Jujumba May 21, 2023
ffd79ba
bcrypt: notify about errors with invalid states and notifications
Jujumba May 21, 2023
fd5d3d5
bcrypt: format html and use ascii byte format by default
Jujumba May 21, 2023
ab3099f
bcrypt: refactor: simplify conversion action -> bool
Jujumba May 21, 2023
ca0b384
computations: remove borrowing
Jujumba May 21, 2023
d1f5d77
bcrypt: remove redundant logic
Jujumba May 22, 2023
4852742
bcrypt: avoid unnecessary data move
Jujumba May 22, 2023
68a7244
bcrypt: input: change class
Jujumba May 22, 2023
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
38 changes: 34 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ hmac-sha256 = "1.1.5"
hmac-sha512 = { version = "1.1.2", features = ["sha384"] }
rsa = "0.7.2"
yew-hooks = "0.2.0"
bcrypt = "0.14.0"
2 changes: 2 additions & 0 deletions src/crypto_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use sha1::{Digest, Sha1};
use yew::{classes, function_component, html, use_effect_with_deps, use_state, Callback, Html};
use yew_hooks::{use_clipboard, use_location};
use yew_notifications::{use_notification, Notification, NotificationType};
use crate::crypto_helper::computations::process_bcrypt;
TheBestTvarynka marked this conversation as resolved.
Show resolved Hide resolved

use self::computations::{process_krb_cipher, process_krb_hmac, process_rsa};
use crate::url_query_params::generate_crypto_helper_link;
Expand All @@ -35,6 +36,7 @@ fn convert(algrithm: &Algorithm) -> Result<Vec<u8>, String> {
Algorithm::HmacSha196Aes128(input) => process_krb_hmac(ChecksumSuite::HmacSha196Aes128.hasher(), input),
Algorithm::HmacSha196Aes256(input) => process_krb_hmac(ChecksumSuite::HmacSha196Aes256.hasher(), input),
Algorithm::Rsa(input) => process_rsa(input),
Algorithm::Bcrypt(input) => process_bcrypt(input),
}
}

Expand Down
68 changes: 66 additions & 2 deletions src/crypto_helper/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};

use super::serde::*;

pub const SUPPORTED_ALGORITHMS: [&str; 10] = [
pub const SUPPORTED_ALGORITHMS: [&str; 11] = [
"MD5", // 0
"SHA1", // 1
"SHA256", // 2
Expand All @@ -17,14 +17,16 @@ pub const SUPPORTED_ALGORITHMS: [&str; 10] = [
"HMAC-SHA1-96-AES256", // 7
"RSA", // 8
"SHA384", // 9
"BCRYPT", // 10
];

pub const HASHING_ALGOS: [&str; 5] = [
pub const HASHING_ALGOS: [&str; 6] = [
SUPPORTED_ALGORITHMS[0],
SUPPORTED_ALGORITHMS[1],
SUPPORTED_ALGORITHMS[2],
SUPPORTED_ALGORITHMS[3],
SUPPORTED_ALGORITHMS[9],
SUPPORTED_ALGORITHMS[10],
];

pub const ENCRYPTION_ALGOS: [&str; 3] = [
Expand Down Expand Up @@ -246,6 +248,64 @@ pub struct RsaInput {
pub payload: Vec<u8>,
TheBestTvarynka marked this conversation as resolved.
Show resolved Hide resolved
}

impl Default for BcryptInput {
fn default() -> Self {
let action = BcryptAction::Hash(BcryptHashAction {
rounds: 8,
salt: Vec::new(),
});
Self {
data: Vec::new(),
action
}
TheBestTvarynka marked this conversation as resolved.
Show resolved Hide resolved
}
}

impl Default for BcryptHashAction {
fn default() -> Self {
Self {
rounds: 8,
salt: Vec::new(),
}
}
}

#[derive(Eq, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct BcryptHashAction {
pub rounds: u32,
pub salt: Vec<u8>,
TheBestTvarynka marked this conversation as resolved.
Show resolved Hide resolved
}

#[derive(Eq, Clone, PartialEq, Serialize, Deserialize, Debug)]
pub enum BcryptAction {
Hash(BcryptHashAction),
Verify(String),
}

impl From<BcryptAction> for bool {
TheBestTvarynka marked this conversation as resolved.
Show resolved Hide resolved
fn from(action: BcryptAction) -> Self {
match action {
BcryptAction::Hash(_) => false,
BcryptAction::Verify(_) => true,
}
}
}

impl From<bool> for BcryptAction {
fn from(action: bool) -> Self {
match action {
true => Self::Verify(Default::default()),
false => Self::Hash(Default::default()),
}
}
}

#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct BcryptInput {
pub action: BcryptAction,
pub data: Vec<u8>,
TheBestTvarynka marked this conversation as resolved.
Show resolved Hide resolved
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum Algorithm {
Expand All @@ -264,6 +324,7 @@ pub enum Algorithm {
HmacSha196Aes128(KrbInputData),
HmacSha196Aes256(KrbInputData),
Rsa(RsaInput),
Bcrypt(BcryptInput),
}

impl TryFrom<&str> for Algorithm {
Expand All @@ -290,6 +351,8 @@ impl TryFrom<&str> for Algorithm {
return Ok(Algorithm::HmacSha196Aes256(Default::default()));
} else if value == SUPPORTED_ALGORITHMS[8] {
return Ok(Algorithm::Rsa(Default::default()));
} else if value == SUPPORTED_ALGORITHMS[10] {
return Ok(Algorithm::Bcrypt(Default::default()));
}

log::error!("invalid algo literal: {}", value);
Expand All @@ -311,6 +374,7 @@ impl From<&Algorithm> for &str {
Algorithm::HmacSha196Aes128(_) => SUPPORTED_ALGORITHMS[6],
Algorithm::HmacSha196Aes256(_) => SUPPORTED_ALGORITHMS[7],
Algorithm::Rsa(_) => SUPPORTED_ALGORITHMS[8],
Algorithm::Bcrypt(_) => SUPPORTED_ALGORITHMS[10],
}
}
}
Expand Down
40 changes: 39 additions & 1 deletion src/crypto_helper/computations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use picky_krb::crypto::{Checksum, Cipher};
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
use rsa::{PaddingScheme, PublicKey as PublicKeyTrait};
use std::convert::TryInto;
use bcrypt::Version;

use super::algorithm::{KrbInput, KrbInputData, KrbMode, RsaAction, RsaInput};
use super::algorithm::{KrbInput, KrbInputData, KrbMode, RsaAction, RsaInput, BcryptInput, BcryptAction, BcryptHashAction};

pub fn process_rsa(input: &RsaInput) -> Result<Vec<u8>, String> {
let payload = &input.payload;
Expand Down Expand Up @@ -44,3 +46,39 @@ pub fn process_krb_hmac(hasher: Box<dyn Checksum>, input: &KrbInputData) -> Resu
.checksum(&input.key, input.key_usage, &input.payload)
.map_err(|err| err.to_string())
}

pub fn process_bcrypt(input: &BcryptInput) -> Result<Vec<u8>, String> {
match &input.action {
BcryptAction::Hash(bcrypt_hash_action) => hash_bcrypt(bcrypt_hash_action, &input.data),
BcryptAction::Verify(hashed) => verify_bcrypt(&input.data, hashed),
}
TheBestTvarynka marked this conversation as resolved.
Show resolved Hide resolved
}
fn hash_bcrypt(hash_action: &BcryptHashAction, password: &[u8]) -> Result<Vec<u8>, String> {
match hash_action.salt.len() {
16 => hash_with_salt_bcrypt(password, hash_action.rounds, hash_action.salt.clone().try_into().unwrap()), // todo: get rid of clone()
0 => hash_without_salt_bcrypt(password, hash_action.rounds),
len => Err(format!("Invalid bcrypt salt len: expected 16 bytes but got {}", len))
}
}
fn hash_with_salt_bcrypt(password: &[u8], rounds: u32, salt: [u8; 16]) -> Result<Vec<u8>, String> {
let res = bcrypt::hash_with_salt(password, rounds, salt);
match &res {
Ok(hash_parts) => Ok(hash_parts.format_for_version(Version::TwoB).into_bytes()),
Err(e) => Err(e.to_string()),
}
}
fn hash_without_salt_bcrypt(password: &[u8], cost: u32) -> Result<Vec<u8>, String> {
match bcrypt::hash(password, cost) {
Ok(hash) => Ok(hash.into_bytes()),
Err(e) => Err(e.to_string())
}
}
TheBestTvarynka marked this conversation as resolved.
Show resolved Hide resolved
fn verify_bcrypt(password: &[u8], hashed: &str) -> Result<Vec<u8>, String>{
match bcrypt::verify(password, hashed) {
Ok(res) => Ok(match res {
true => vec![1],
false => vec![],
}),
Err(e) => Err(e.to_string()),
}
}
3 changes: 3 additions & 0 deletions src/crypto_helper/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ fn get_algorithm_info(algorithm: &Algorithm) -> Html {
Algorithm::Rsa(_) => html! {
<span>{"Use RSA algorithm to sign/verify/encrypt/decrypt your data."}</span>
},
Algorithm::Bcrypt(_) => html! {
<span>{"Use Bcrypt algorithm to encrypt/verify your data."}</span>
},
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/crypto_helper/input.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
mod krb;
mod rsa;
mod bcrypt;

use picky_krb::crypto::CipherSuite;
use yew::{classes, function_component, html, Callback, Html, Properties, UseStateSetter};

use self::krb::build_krb_input;
use self::rsa::build_rsa_input;
use self::bcrypt::build_bcrypt_input;
use super::algorithm::{KrbInput, KrbMode};
use super::Algorithm;
use crate::common::build_byte_input;
Expand Down Expand Up @@ -81,6 +83,10 @@ fn get_input_components(algorithm: &Algorithm, setter: &UseStateSetter<Algorithm
input.clone(),
Callback::from(move |input| setter.set(Algorithm::Rsa(input))),
),
Algorithm::Bcrypt(input) => build_bcrypt_input(
input.clone(),
Callback::from(move |input| setter.set(Algorithm::Bcrypt(input))),
),
}
}

Expand Down
Loading