Skip to content

Commit

Permalink
Merge pull request #3 from Cryptographic-API-Services/#2-blake2-hash
Browse files Browse the repository at this point in the history
X25519
  • Loading branch information
WingZer0o authored Feb 8, 2024
2 parents f798fb9 + 41ff021 commit 0ed9c4b
Show file tree
Hide file tree
Showing 18 changed files with 381 additions and 4 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ path = "src/lib.rs"
crate-type = ["cdylib"]

[dependencies]
aes-gcm = "0.10.3"
argon2 = "0.5.2"
bcrypt = "0.15.0"
blake2 = "0.10.6"
napi = "2"
napi-derive = "2"
rand = "0.8.5"
rand_chacha = "0.3.1"
scrypt = "0.11.0"
sha3 = "0.10.8"
x25519-dalek = {version = "2.0.0", features = ["static_secrets"] }

[build-dependencies]
napi-build = "1"
15 changes: 15 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,18 @@ export function sha512(dataToHash: Array<number>): Array<number>
export function sha512Verify(dataToHash: Array<number>, dataToVerify: Array<number>): boolean
export function sha256(dataToHash: Array<number>): Array<number>
export function sha256Verify(dataToHash: Array<number>, dataToVerify: Array<number>): boolean
export function x25519GenerateSecretAndPublicKey(): X25519SecretPublicKeyResult
export function x25519DiffieHellman(mySecretKey: Array<number>, usersPublicKey: Array<number>): Array<number>
export function aesNonce(): Array<number>
export function aes128Key(): Array<number>
export function aes256Key(): Array<number>
export function aes128Encrypt(aesKey: Array<number>, nonce: Array<number>, plaintext: Array<number>): Array<number>
export function aes128Decrypt(aesKey: Array<number>, nonce: Array<number>, ciphertext: Array<number>): Array<number>
export function aes256Encrypt(aesKey: Array<number>, nonce: Array<number>, plaintext: Array<number>): Array<number>
export function aes256Decrypt(aesKey: Array<number>, nonce: Array<number>, ciphertext: Array<number>): Array<number>
export type x25519SecretPublicKeyResult = X25519SecretPublicKeyResult
export class X25519SecretPublicKeyResult {
publicKey: Array<number>
secretKey: Array<number>
constructor(publicKey: Array<number>, secretKey: Array<number>)
}
Binary file modified index.node
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cas-typescript-sdk",
"version": "1.0.9",
"version": "1.0.10",
"description": "",
"main": "lib/index.js",
"types": "lib/index.d.ts",
Expand Down
10 changes: 7 additions & 3 deletions src-ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ import {
ScryptWrapper,
} from "./password-hashers/index";
import { HasherFactory, HasherType, SHAWrapper } from "./hashers/index";
import { X25519Wrapper } from "./key_exchange/index";
import { AESWrapper } from "./symmetric/index";

export {
Argon2Wrapper,
BCryptWrapper,
ScryptWrapper,
PasswordHasherFactory,
PasswordHasherType,
HasherFactory,
HasherType,
PasswordHasherFactory,
PasswordHasherType,
ScryptWrapper,
SHAWrapper,
X25519Wrapper,
AESWrapper
};
3 changes: 3 additions & 0 deletions src-ts/key_exchange/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { X25519Wrapper } from "./x25519";

export { X25519Wrapper };
11 changes: 11 additions & 0 deletions src-ts/key_exchange/x25519.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { x25519DiffieHellman, x25519GenerateSecretAndPublicKey, X25519SecretPublicKeyResult } from "../../index"

export class X25519Wrapper {
public generateSecretAndPublicKey(): X25519SecretPublicKeyResult {
return x25519GenerateSecretAndPublicKey();
}

public diffieHellman(secretKey: Array<number>, publicKey: Array<number>) {
return x25519DiffieHellman(secretKey, publicKey);
}
}
39 changes: 39 additions & 0 deletions src-ts/symmetric/aes-wrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
aes128Decrypt,
aes128Encrypt,
aes128Key,
aes256Decrypt,
aes256Encrypt,
aes256Key,
aesNonce,
} from "../../index";

export class AESWrapper {
public aes128Key(): Array<number> {
return aes128Key();
}

public aes256Key(): Array<number> {
return aes256Key();
}

public aesNonce(): Array<number> {
return aesNonce();
}

public aes128Encrypt(aesKey: Array<number>, nonce: Array<number>, plaintext: Array<number>): Array<number> {
return aes128Encrypt(aesKey, nonce, plaintext);
}

public aes128Decrypt(aesKey: Array<number>, nonce: Array<number>, ciphertext: Array<number>): Array<number> {
return aes128Decrypt(aesKey, nonce, ciphertext);
}

public aes256Encrypt(aesKey: Array<number>, nonce: Array<number>, plaintext: Array<number>): Array<number> {
return aes256Encrypt(aesKey, nonce, plaintext);
}

public aes256Decrypt(aesKey: Array<number>, nonce: Array<number>, ciphertext: Array<number>): Array<number> {
return aes256Decrypt(aesKey, nonce, ciphertext);
}
}
3 changes: 3 additions & 0 deletions src-ts/symmetric/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { AESWrapper } from "./aes-wrapper";

export { AESWrapper };
39 changes: 39 additions & 0 deletions src/hashers/blake2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use blake2::{Blake2b512, Blake2s256, Digest};
use super::cas_hasher::CASHasher;

pub struct CASBlake2;

impl CASHasher for CASBlake2 {
fn hash_512(data_to_hash: Vec<u8>) -> Vec<u8> {
let mut hasher = Blake2b512::new();
hasher.update(data_to_hash);
let result = hasher.finalize();
return result.to_vec();
}

fn verify_512(hash_to_verify: Vec<u8>, data_to_verify: Vec<u8>) -> bool {
let mut hasher = Blake2b512::new();
hasher.update(data_to_verify);
let result = hasher.finalize();
return hash_to_verify.eq(&result.to_vec());
}

fn hash_256(data_to_hash: Vec<u8>) -> Vec<u8> {
let mut hasher = Blake2s256::new();
hasher.update(data_to_hash);
let result = hasher.finalize();
return result.to_vec();
}

fn verify_256(hash_to_verify: Vec<u8>, data_to_verify: Vec<u8>) -> bool {
let mut hasher = Blake2s256::new();
hasher.update(data_to_verify);
let result = hasher.finalize();
return hash_to_verify.eq(&result.to_vec());
}
}

#[test]
fn hash_512_test() {

}
6 changes: 6 additions & 0 deletions src/key_exchange/cas_key_exchange.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use super::x25519::x25519SecretPublicKeyResult;

pub trait CASKeyExchange {
fn generate_secret_and_public_key() -> x25519SecretPublicKeyResult;
fn diffie_hellman(my_secret_key: Vec<u8>, users_public_key: Vec<u8>) -> Vec<u8>;
}
57 changes: 57 additions & 0 deletions src/key_exchange/x25519.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use napi::bindgen_prelude::ClassInstance;
use napi_derive::napi;
use rand::rngs::OsRng;
use x25519_dalek::{PublicKey, StaticSecret};

use super::cas_key_exchange::CASKeyExchange;

#[napi(constructor)]
pub struct x25519SecretPublicKeyResult {
pub public_key: Vec<u8>,
pub secret_key: Vec<u8>
}

pub struct X25519;

impl CASKeyExchange for X25519 {
fn generate_secret_and_public_key() -> x25519SecretPublicKeyResult {
let secret_key = StaticSecret::random_from_rng(OsRng);
let public_key = PublicKey::from(&secret_key);
let result = x25519SecretPublicKeyResult {
secret_key: secret_key.as_bytes().to_vec(),
public_key: public_key.as_bytes().to_vec()
};
result
}

fn diffie_hellman(my_secret_key: Vec<u8>, users_public_key: Vec<u8>) -> Vec<u8> {
let mut secret_key_array: [u8; 32] = Default::default();
secret_key_array.copy_from_slice(&my_secret_key);
let mut users_public_key_array: [u8; 32] = Default::default();
users_public_key_array.copy_from_slice(&users_public_key);

let secret_key = StaticSecret::from(secret_key_array);
let public_key = PublicKey::from(users_public_key_array);
return secret_key.diffie_hellman(&public_key).as_bytes().to_vec();
}
}

#[napi]
pub fn x25519_generate_secret_and_public_key() -> x25519SecretPublicKeyResult {
return <X25519 as CASKeyExchange>::generate_secret_and_public_key();
}

#[napi]
pub fn x25519_diffie_hellman(my_secret_key: Vec<u8>, users_public_key: Vec<u8>) -> Vec<u8> {
return <X25519 as CASKeyExchange>::diffie_hellman(my_secret_key, users_public_key);
}

#[test]
pub fn x25519_diffie_hellman_test() {
let alice = x25519_generate_secret_and_public_key();
let bob = x25519_generate_secret_and_public_key();

let alice_shared_secret = x25519_diffie_hellman(alice.secret_key, bob.public_key);
let bob_shared_secret = x25519_diffie_hellman(bob.secret_key, alice.public_key);
assert_eq!(true, alice_shared_secret.eq(&bob_shared_secret));
}
11 changes: 11 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,15 @@ mod password_hashers {
mod hashers {
pub mod sha;
pub mod cas_hasher;
pub mod blake2;
}

mod key_exchange {
pub mod x25519;
pub mod cas_key_exchange;
}

mod symmetric {
pub mod aes;
pub mod cas_symmetric_encryption;
}
116 changes: 116 additions & 0 deletions src/symmetric/aes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use napi_derive::napi;
use rand::rngs::OsRng;
use rand::{RngCore, SeedableRng};
use rand_chacha::ChaCha20Rng;

use aes_gcm::{
aead::{generic_array::GenericArray, Aead},
Aes256Gcm, Aes128Gcm, KeyInit, Nonce
};

use super::cas_symmetric_encryption::CASAESEncryption;
pub struct CASAES128;
pub struct CASAES256;

impl CASAESEncryption for CASAES256 {
fn generate_key() -> Vec<u8> {
return Aes256Gcm::generate_key(&mut OsRng).to_vec();
}

fn encrypt_plaintext(aes_key: Vec<u8>, nonce: Vec<u8>, plaintext: Vec<u8>) -> Vec<u8> {
let key = GenericArray::from_slice(&aes_key);
let mut cipher = Aes256Gcm::new(&key);
let nonce = Nonce::from_slice(&nonce);
let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).unwrap();
ciphertext
}

fn decrypt_ciphertext(aes_key: Vec<u8>, nonce: Vec<u8>, ciphertext: Vec<u8>) -> Vec<u8> {
let key = GenericArray::from_slice(&aes_key);
let mut cipher = Aes256Gcm::new(&key);
let nonce = Nonce::from_slice(&nonce);
let plaintext = cipher.decrypt(nonce, ciphertext.as_ref()).unwrap();
plaintext
}
}

impl CASAESEncryption for CASAES128 {
fn generate_key() -> Vec<u8> {
return Aes128Gcm::generate_key(&mut OsRng).to_vec();
}

fn encrypt_plaintext(aes_key: Vec<u8>, nonce: Vec<u8>, plaintext: Vec<u8>) -> Vec<u8> {
let key = GenericArray::from_slice(&aes_key);
let mut cipher = Aes128Gcm::new(&key);
let nonce = Nonce::from_slice(&nonce);
let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).unwrap();
ciphertext
}

fn decrypt_ciphertext(aes_key: Vec<u8>, nonce: Vec<u8>, ciphertext: Vec<u8>) -> Vec<u8> {
let key = GenericArray::from_slice(&aes_key);
let mut cipher = Aes128Gcm::new(&key);
let nonce = Nonce::from_slice(&nonce);
let plaintext = cipher.decrypt(nonce, ciphertext.as_ref()).unwrap();
plaintext
}
}

#[napi]
pub fn aes_nonce() -> Vec<u8> {
let mut rng = ChaCha20Rng::from_entropy();
let mut random_bytes = Vec::with_capacity(12);
random_bytes.resize(12, 0);
rng.fill_bytes(&mut random_bytes);
random_bytes
}

#[napi]
pub fn aes128_key() -> Vec<u8> {
return CASAES128::generate_key();
}

#[napi]
pub fn aes256_key() -> Vec<u8> {
return CASAES256::generate_key();
}

#[napi]
pub fn aes128_encrypt(aes_key: Vec<u8>, nonce: Vec<u8>, plaintext: Vec<u8>) -> Vec<u8> {
return CASAES128::encrypt_plaintext(aes_key, nonce, plaintext);
}

#[napi]
pub fn aes128_decrypt(aes_key: Vec<u8>, nonce: Vec<u8>, ciphertext: Vec<u8>) -> Vec<u8> {
return CASAES128::decrypt_ciphertext(aes_key, nonce, ciphertext);
}

#[napi]
pub fn aes256_encrypt(aes_key: Vec<u8>, nonce: Vec<u8>, plaintext: Vec<u8>) -> Vec<u8> {
return CASAES256::encrypt_plaintext(aes_key, nonce, plaintext);
}

#[napi]
pub fn aes256_decrypt(aes_key: Vec<u8>, nonce: Vec<u8>, ciphertext: Vec<u8>) -> Vec<u8> {
return CASAES256::decrypt_ciphertext(aes_key, nonce, ciphertext);
}

#[test]
fn aes128_encrypt_decrypt_test() {
let aes_key = aes128_key();
let nonce = aes_nonce();
let plaintext = b"WelcomeHome".to_vec();
let ciphertext = aes128_encrypt(aes_key.clone(), nonce.clone(), plaintext.clone());
let decrypted_plaintext = aes128_decrypt(aes_key, nonce, ciphertext);
assert_eq!(decrypted_plaintext, plaintext)
}

#[test]
fn aes256_encrypt_decrypt_test() {
let aes_key = aes256_key();
let nonce = aes_nonce();
let plaintext = b"WelcomeHome".to_vec();
let ciphertext = aes256_encrypt(aes_key.clone(), nonce.clone(), plaintext.clone());
let decrypted_plaintext = aes256_decrypt(aes_key, nonce, ciphertext);
assert_eq!(decrypted_plaintext, plaintext)
}
5 changes: 5 additions & 0 deletions src/symmetric/cas_symmetric_encryption.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub trait CASAESEncryption {
fn generate_key() -> Vec<u8>;
fn encrypt_plaintext(aes_key: Vec<u8>, nonce: Vec<u8>, plaintext: Vec<u8>) -> Vec<u8>;
fn decrypt_ciphertext(aes_key: Vec<u8>, nonce: Vec<u8>, ciphertext: Vec<u8>) -> Vec<u8>;
}
10 changes: 10 additions & 0 deletions test-ts/helpers/array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const areEqual = (a: any, b: any) => {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length !== b.length) return false;

for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
};
Loading

0 comments on commit 0ed9c4b

Please sign in to comment.