Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
marcin committed May 8, 2021
1 parent f997d90 commit 70762c0
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 259 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
[package]
name = "opaque-wasm"
version = "0.4.1"
version = "0.5.0"
authors = ["Marcin Lazar <[email protected]>"]
edition = "2018"
repository = "https://github.com/marucjmar/opaque-wasm"

[lib]
crate-type = ["cdylib", "rlib"]
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## opaque-wasm

An implementation of the OPAQUE key exchange protocol in WASM(WebAssembly) hosted by the browser. The library was founded on the basis of [opaque-ke](https://github.com/novifinancial/opaque-ke).
An implementation of the OPAQUE key exchange protocol in WASM(WebAssembly). The library was founded on the basis of [opaque-ke](https://github.com/novifinancial/opaque-ke).

### Installation

Expand All @@ -11,6 +11,7 @@ yarn add opaque-wasm


### JS simple example of usage
Check full implementation in this [file](https://github.com/marucjmar/opaque-wasm/blob/master/js-test/test.mjs)

```js
import { Registration, Login } from "opaque-wasm";
Expand Down
1 change: 1 addition & 0 deletions js-test/node_modules/opaque-wasm

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

53 changes: 26 additions & 27 deletions js-test/test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,47 @@ const email = '[email protected]'
const server_privatekey = 'c95843d9c67f7ba7f1231af10e1a88dc' // XXX: must be 32 chars long

async function run() {
console.log('--- STARTING ---')
console.log('--- STARTING ---')

// User registration
const registration = new Registration()
const registration_tx = registration.start(password)
// User registration
const registration = new Registration()
const registration_tx = registration.start(password)

console.log('--- begin ---',registration_tx)
console.log('--- begin ---', registration_tx)

const serverRegistration = new HandleRegistration()
const registration_response = serverRegistration.start(registration_tx, server_privatekey)
console.log('-- server response --', registration_response)
const serverRegistration = new HandleRegistration()
const registration_response = serverRegistration.start(registration_tx, server_privatekey)
console.log('-- server response --', registration_response)


const registration_final = registration.finish(registration_response)
console.log('-- client finish --',registration_final)
const registration_final = registration.finish(registration_response)
console.log('-- client finish --', registration_final)

const password_file = serverRegistration.finish(registration_final)
console.log('-- password_file --', password_file)
const password_file = serverRegistration.finish(registration_final)
console.log('-- password_file --', password_file)


// User Login
// User Login

const login = new Login()
const login_tx = login.start(password)
console.log('login_tx', login_tx)
const login = new Login()
const login_tx = login.start(password)
console.log('login_tx', login_tx)

console.log(login)
console.log(login)

const serverLogin = new HandleLogin()
const login_response = serverLogin.start(password_file, login_tx, server_privatekey)
console.log('login_response',login_response)
const serverLogin = new HandleLogin()
const login_response = serverLogin.start(password_file, login_tx, server_privatekey)
console.log('login_response', login_response)

const login_final = login.finish(login_response)
console.log('client login final', login_final)
const login_final = login.finish(login_response)
console.log('client login final', login_final)

console.log(login)
console.log(login)

console.log('client session key',login.getSessionKey())

const server_finish = serverLogin.finish(login_final)
console.log('server session key', server_finish)
console.log('client session key', login.getSessionKey())

const server_finish = serverLogin.finish(login_final)
console.log('server session key', server_finish)
}

run()
64 changes: 64 additions & 0 deletions src/client_login.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::hash_methods::Default;
use opaque_ke::{
ClientLogin, ClientLoginFinishParameters, ClientLoginStartParameters, CredentialResponse,
};
use rand::rngs::OsRng;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct Login {
state: Option<ClientLogin<Default>>,
rng: OsRng,
session_key: Option<Vec<u8>>,
}

#[wasm_bindgen]
impl Login {
#[wasm_bindgen(constructor)]
pub fn new() -> Login {
Login {
rng: OsRng,
state: None,
session_key: None,
}
}

pub fn start(&mut self, password: &str) -> Result<Vec<u8>, JsValue> {
let client_login_start_result = match ClientLogin::<Default>::start(
&mut self.rng,
&password.as_bytes(),
ClientLoginStartParameters::default(),
) {
Ok(client_login_start_result) => client_login_start_result,
Err(_e) => return Err("Failed start".into()),
};

self.state = Some(client_login_start_result.state);

return Ok(client_login_start_result.message.serialize());
}

pub fn finish(&mut self, message: Vec<u8>) -> Result<Vec<u8>, JsValue> {
let message = CredentialResponse::deserialize(&message[..]);

if message.is_err() {
return Err("Message deserialize failed".into());
}

let state = self.state.take();

let result = state
.unwrap()
.finish(message.unwrap(), ClientLoginFinishParameters::default())
.unwrap();

self.session_key = Some(result.session_key);

return Ok(result.message.serialize());
}

#[wasm_bindgen(js_name = getSessionKey)]
pub fn get_session_key(self) -> Result<Vec<u8>, JsValue> {
return Ok(self.session_key.unwrap());
}
}
50 changes: 50 additions & 0 deletions src/client_registration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use crate::hash_methods::Default;
use opaque_ke::{ClientRegistration, ClientRegistrationFinishParameters, RegistrationResponse};
use rand::rngs::OsRng;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct Registration {
state: Option<ClientRegistration<Default>>,
rng: OsRng,
}

#[wasm_bindgen]
impl Registration {
#[wasm_bindgen(constructor)]
pub fn new() -> Registration {
Registration {
rng: OsRng,
state: None,
}
}

pub fn start(&mut self, password: &str) -> Result<Vec<u8>, JsValue> {
let client_registration_start_result =
match ClientRegistration::<Default>::start(&mut self.rng, &password.as_bytes()) {
Ok(reply) => reply,
Err(_e) => return Err("Start failed".into()),
};
self.state = Some(client_registration_start_result.state);

return Ok(client_registration_start_result.message.serialize());
}

pub fn finish(self, message: Vec<u8>) -> Result<Vec<u8>, JsValue> {
let message = match RegistrationResponse::deserialize(&message[..]) {
Ok(message) => message,
Err(_e) => return Err("Message deserialize failed".into()),
};
let mut rng = self.rng;

let client_finish_registration_result = match self.state.unwrap().finish(
&mut rng,
message,
ClientRegistrationFinishParameters::default(),
) {
Ok(reply) => reply,
Err(_e) => return Err("Mismatch messagess".into()),
};
return Ok(client_finish_registration_result.message.serialize());
}
}
61 changes: 61 additions & 0 deletions src/handle_login.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use crate::hash_methods::Default;
use opaque_ke::{
keypair::KeyPair, CredentialFinalization, CredentialRequest, ServerLogin,
ServerLoginStartParameters, ServerRegistration,
};
use rand::rngs::OsRng;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct HandleLogin {
state: Option<ServerLogin<Default>>,
rng: OsRng,
}

#[wasm_bindgen]
impl HandleLogin {
#[wasm_bindgen(constructor)]
pub fn new() -> HandleLogin {
HandleLogin {
state: None,
rng: OsRng,
}
}

pub fn start(
&mut self,
password_file: Vec<u8>,
credential_request: Vec<u8>,
server_privatekey: Vec<u8>,
) -> Result<Vec<u8>, JsValue> {
let server_kp = KeyPair::<curve25519_dalek::ristretto::RistrettoPoint>::from_private_key_slice(
&server_privatekey,
)
.unwrap();

let request = CredentialRequest::deserialize(&credential_request[..]).unwrap();
let password = ServerRegistration::<Default>::deserialize(&password_file[..]).unwrap();

let server_login_start_result = match ServerLogin::start(
&mut self.rng,
password,
&server_kp.private(),
request,
ServerLoginStartParameters::default(),
) {
Ok(message) => message,
Err(_e) => return Err("Message deserialize failed".into()),
};

self.state = Some(server_login_start_result.state);

return Ok(server_login_start_result.message.serialize());
}

pub fn finish(self, credential_finish: Vec<u8>) -> Result<Vec<u8>, JsValue> {
let finish = CredentialFinalization::deserialize(&credential_finish[..]).unwrap();

let result = self.state.unwrap().finish(finish).unwrap();
return Ok(result.session_key);
}
}
52 changes: 52 additions & 0 deletions src/handle_registration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use crate::hash_methods::Default;
use opaque_ke::{keypair::KeyPair, RegistrationRequest, RegistrationUpload, ServerRegistration};
use rand::rngs::OsRng;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct HandleRegistration {
rng: OsRng,
state: Option<ServerRegistration<Default>>,
}

#[wasm_bindgen]
impl HandleRegistration {
#[wasm_bindgen(constructor)]
pub fn new() -> HandleRegistration {
HandleRegistration {
rng: OsRng,
state: None,
}
}

pub fn start(
&mut self,
registration_request: Vec<u8>,
server_privatekey: Vec<u8>,
) -> Result<Vec<u8>, JsValue> {
let server_kp = KeyPair::<curve25519_dalek::ristretto::RistrettoPoint>::from_private_key_slice(
&server_privatekey,
)
.unwrap();
let request = match RegistrationRequest::deserialize(&registration_request[..]) {
Ok(message) => message,
Err(_e) => return Err("Message deserialize failed".into()),
};

let server_registration_start_result =
match ServerRegistration::<Default>::start(&mut self.rng, request, &server_kp.public()) {
Ok(message) => message,
Err(_e) => return Err("Message deserialize failed".into()),
};

self.state = Some(server_registration_start_result.state);
return Ok(server_registration_start_result.message.serialize());
}

pub fn finish(self, registration_finish: Vec<u8>) -> Result<Vec<u8>, JsValue> {
let message = RegistrationUpload::deserialize(&registration_finish[..]).unwrap();
let password_file = self.state.unwrap().finish(message).unwrap();

return Ok(password_file.serialize());
}
}
25 changes: 7 additions & 18 deletions src/hash_methods.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
use digest::Digest;
use generic_array::typenum::Unsigned;
use generic_array::GenericArray;
use opaque_ke::errors::InternalPakeError;
use opaque_ke::hash::Hash;
use opaque_ke::slow_hash::SlowHash;
use opaque_ke::ciphersuite::CipherSuite;

pub struct Scrypt;

impl<D: Hash> SlowHash<D> for Scrypt {
fn hash(
input: GenericArray<u8, <D as Digest>::OutputSize>,
) -> Result<Vec<u8>, InternalPakeError> {
let params = scrypt::ScryptParams::new(15, 8, 1).unwrap();
let mut output = vec![0u8; <D as Digest>::OutputSize::to_usize()];
scrypt::scrypt(&input, &[], &params, &mut output)
.map_err(|_| InternalPakeError::SlowHashError)?;
Ok(output)
}
pub struct Default;
impl CipherSuite for Default {
type Group = curve25519_dalek::ristretto::RistrettoPoint;
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
type Hash = sha2::Sha512;
type SlowHash = scrypt::ScryptParams;
}
Loading

0 comments on commit 70762c0

Please sign in to comment.