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
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: CI
on: [push, pull_request]
on: [pull_request]

env:
CARGO_TERM_COLOR: always
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
.DS_Store
.DS_Store
.idea/
18 changes: 2 additions & 16 deletions Cargo.lock

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

30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
[![Docs](https://docs.rs/cryptotools/badge.svg)](https://docs.rs/cryptotools)
[![License](https://img.shields.io/github/license/heroesofcode/cryptotools.svg)](https://github.com/heroesofcode/cryptotools/blob/main/LICENSE)

cryptotools is a cryptography library, with it you can:
cryptotools is a simple, easy-to-use library for cryptographic utilities in Rust. It currently provides the following:

- [x] Encode to base64
- [x] Decode the base64 value
- [x] Encrypt to md5
- [x] Base64 encoding
- [x] Base64 decoding
- [x] MD5 encryption (hashing)

## Installing

In the file `Cargo.toml`
cargo add cryptotools

```toml
[dependencies]
Expand All @@ -22,28 +22,28 @@ cryptotools = "0.3.0"

## Usage

In the first example, if you want to encode and decode base64
### Base64 Encoding & Decoding

```rust
use cryptotools::encode_base64::Base64Encode;
use cryptotools::decode_base64::Base64Decode;

// Encode
let encode = Base64Encode::encode("123456789");
println!("{}", encode);
let input = "hello world";
let encoded = Base64Encode::encode(input);
println!("Base64 Encoded: {}", encoded);

// Decode
let decode = Base64Decode::decode("MTIzNDU2Nzg5");
println!("{}", decode);
let decoded = Base64Decode::decode(&encoded);
println!("Base64 Decoded: {}", decoded);
```

To encrypt a value to md5
### MD5 Hashing

```rust
use cryptotools::encrypt_md5::MD5;

let md5 = MD5::encrypt("9999");
println!("{}", md5);
let input = "password123";
let hash = MD5::encrypt(input);
println!("MD5 Hash: {}", hash);
```

## License
Expand Down
3 changes: 1 addition & 2 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Example

```sh
cd example
cargo run
cargo run -p example
```
2 changes: 1 addition & 1 deletion examples/example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cryptotools = { git = "https://github.com/heroesofcode/cryptotools" }
cryptotools = { path = "../.." }
20 changes: 10 additions & 10 deletions examples/example/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use cryptotools::encode_base64::Base64Encode;
use cryptotools::decode_base64::Base64Decode;
use cryptotools::encode_base64::Base64Encode;
use cryptotools::encrypt_md5::MD5;

fn main() {
// Encode
let encode = Base64Encode::encode("123456789");
println!("{}", encode);
// Encode
let encode = Base64Encode::encode("123456789");
println!("{}", encode);

// Decode
let decode = Base64Decode::decode("MTIzNDU2Nzg5");
println!("{}", decode);
// Decode
let decode = Base64Decode::decode("MTIzNDU2Nzg5");
println!("{}", decode);

// md5
let md5 = MD5::encrypt("9999");
println!("{}", md5);
// md5
let md5 = MD5::encrypt("9999");
println!("{}", md5);
}
126 changes: 77 additions & 49 deletions src/decode_base64.rs
Original file line number Diff line number Diff line change
@@ -1,56 +1,84 @@
/// Provides methods to decode Base64 encoded strings.
///
/// # Example
/// ```
/// use cryptotools::decode_base64::Base64Decode;
/// let decoded = Base64Decode::decode("aGVsbG8=");
/// println!("{decoded}");
/// ```
pub struct Base64Decode;

impl Base64Decode {
/// Convert the value of the "value" parameter to base64 decode
pub fn decode(value: &str) -> String {
let base64_chars: Vec<char> =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".chars().collect();
let mut result = Vec::new();
let mut bytes = Vec::with_capacity(4);
let mut padding_count = 0;

ValidationDecodeBase64::count_number_chars(value, &mut padding_count, base64_chars, &mut bytes);
ValidationDecodeBase64::remove_padding(&mut bytes);
ValidationDecodeBase64::decode_bytes(&mut result, &bytes);
ValidationDecodeBase64::remove_padding_from_result(&mut result, padding_count);

let decode_string = String::from_utf8(result).unwrap();
return decode_string;
}
/// Decodes a Base64 string slice into a regular string.
///
/// # Arguments
///
/// * `value` - The Base64-encoded string slice to decode.
///
/// # Returns
///
/// A decoded string.
pub fn decode(value: &str) -> String {
let base64_chars: Vec<char> =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
.chars()
.collect();
let mut result = Vec::new();
let mut bytes = Vec::with_capacity(4);
let mut padding_count = 0;

ValidationDecodeBase64::count_number_chars(value, &mut padding_count, base64_chars, &mut bytes);
ValidationDecodeBase64::remove_padding(&mut bytes);
ValidationDecodeBase64::decode_bytes(&mut result, &bytes);
ValidationDecodeBase64::remove_padding_from_result(&mut result, padding_count);

let decode_string = String::from_utf8(result).unwrap();
decode_string
}
}

/// Collection of helper methods for validating and processing the Base64 decoding.
struct ValidationDecodeBase64;

impl ValidationDecodeBase64 {
fn count_number_chars(data: &str, padding_count: &mut usize, base64_chars: Vec<char>, bytes: &mut Vec<u8>) {
for ch in data.chars() {
if ch == '=' {
*padding_count += 1;
} else {
let index = base64_chars.iter().position(|&c| c == ch).unwrap();
bytes.push(index as u8);
}
}
}

fn remove_padding(bytes: &mut Vec<u8>) {
while bytes.len() % 4 != 0 {
bytes.pop();
}
}

fn decode_bytes(result: &mut Vec<u8>, bytes: &[u8]) {
for i in (0..bytes.len()).step_by(4) {
let byte1 = (bytes[i] << 2) | (bytes[i + 1] >> 4);
let byte2 = ((bytes[i + 1] & 0x0F) << 4) | (bytes[i + 2] >> 2);
let byte3 = ((bytes[i + 2] & 0x03) << 6) | bytes[i + 3];
result.push(byte1);
result.push(byte2);
result.push(byte3);
}
}

fn remove_padding_from_result(result: &mut Vec<u8>, padding_count: usize) {
result.truncate(result.len() - padding_count);
}
}
impl ValidationDecodeBase64 {
/// Converts Base64 characters to indexes, tracks padding, and fills byte vector.
fn count_number_chars(
data: &str,
padding_count: &mut usize,
base64_chars: Vec<char>,
bytes: &mut Vec<u8>,
) {
for ch in data.chars() {
if ch == '=' {
*padding_count += 1;
} else {
let index = base64_chars.iter().position(|&c| c == ch).unwrap();
bytes.push(index as u8);
}
}
}

/// Removes any extra values so the number of bytes is a multiple of 4.
fn remove_padding(bytes: &mut Vec<u8>) {
while bytes.len() % 4 != 0 {
bytes.pop();
}
}

/// Decodes byte chunks from Base64 index representation into bytes.
fn decode_bytes(result: &mut Vec<u8>, bytes: &[u8]) {
for i in (0..bytes.len()).step_by(4) {
let byte1 = (bytes[i] << 2) | (bytes[i + 1] >> 4);
let byte2 = ((bytes[i + 1] & 0x0F) << 4) | (bytes[i + 2] >> 2);
let byte3 = ((bytes[i + 2] & 0x03) << 6) | bytes[i + 3];
result.push(byte1);
result.push(byte2);
result.push(byte3);
}
}

/// Truncates the last bytes according to the padding count to get the final decoded result.
fn remove_padding_from_result(result: &mut Vec<u8>, padding_count: usize) {
result.truncate(result.len() - padding_count);
}
}
Loading