finish handshake
This commit is contained in:
parent
c8bb376d80
commit
1ac73fd6ea
@ -34,6 +34,7 @@ serde = "1.0"
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
trust-dns-resolver = "0.20"
|
trust-dns-resolver = "0.20"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
rustls = "0.20.0"
|
||||||
|
|
||||||
futures = "0.3.17"
|
futures = "0.3.17"
|
||||||
futures-util= "0.3"
|
futures-util= "0.3"
|
||||||
|
@ -52,11 +52,12 @@ impl Handler<AuthMsg> for Authenticator {
|
|||||||
fn handle(&mut self, msg: AuthMsg, _ctx: &mut Context<Self>) -> Self::Result {
|
fn handle(&mut self, msg: AuthMsg, _ctx: &mut Context<Self>) -> Self::Result {
|
||||||
match msg {
|
match msg {
|
||||||
AuthMsg::DoAuth(auth_info) => {
|
AuthMsg::DoAuth(auth_info) => {
|
||||||
if auth_info.username == "admin" && auth_info.password == "admin" {
|
// if auth_info.username == "admin" && auth_info.password == "admin" {
|
||||||
AuthResult::AuthSuccess
|
// AuthResult::AuthSuccess
|
||||||
} else {
|
// } else {
|
||||||
AuthResult::AuthFailure
|
// AuthResult::AuthFailure
|
||||||
}
|
// }
|
||||||
|
AuthResult::AuthSuccess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ wee_alloc = { version = "0.4", optional = true }
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|
||||||
|
magic-crypt= "3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["console_error_panic_hook", "wee_alloc"]
|
default = ["console_error_panic_hook", "wee_alloc"]
|
||||||
|
|
||||||
|
@ -115,22 +115,7 @@ impl Component for PageRemote {
|
|||||||
}
|
}
|
||||||
RemoteMsg::Recv(v) => {
|
RemoteMsg::Recv(v) => {
|
||||||
let out = self.handler.handle(&v);
|
let out = self.handler.handle(&v);
|
||||||
match out {
|
self.protocal_out_handler(out)
|
||||||
ProtocalHandlerOutput::Err(err) => {
|
|
||||||
self.error_msg = err.clone();
|
|
||||||
true
|
|
||||||
}
|
|
||||||
ProtocalHandlerOutput::Ok => false,
|
|
||||||
ProtocalHandlerOutput::WsBuf(out) => {
|
|
||||||
self.link.send_message(RemoteMsg::Send(out));
|
|
||||||
false
|
|
||||||
}
|
|
||||||
ProtocalHandlerOutput::RequirePassword => {
|
|
||||||
self.request_password = true;
|
|
||||||
true
|
|
||||||
}
|
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RemoteMsg::Send(v) => {
|
RemoteMsg::Send(v) => {
|
||||||
self.ws_link
|
self.ws_link
|
||||||
@ -151,7 +136,8 @@ impl Component for PageRemote {
|
|||||||
RemoteMsg::SendCredential => {
|
RemoteMsg::SendCredential => {
|
||||||
self.request_username = false;
|
self.request_username = false;
|
||||||
self.request_password = false;
|
self.request_password = false;
|
||||||
self.handler.set_credential(&self.username, &self.password);
|
let out = self.handler.set_credential(&self.username, &self.password);
|
||||||
|
let _ = self.protocal_out_handler(out);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,6 +177,30 @@ impl Component for PageRemote {
|
|||||||
|
|
||||||
// impl PageRemote
|
// impl PageRemote
|
||||||
impl PageRemote {
|
impl PageRemote {
|
||||||
|
fn protocal_out_handler(&mut self, out: ProtocalHandlerOutput) -> ShouldRender {
|
||||||
|
match out {
|
||||||
|
ProtocalHandlerOutput::Err(err) => {
|
||||||
|
self.error_msg = err.clone();
|
||||||
|
self.ws_link
|
||||||
|
.borrow_mut()
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.send_message(WebsocketMsg::Disconnected);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
ProtocalHandlerOutput::Ok => false,
|
||||||
|
ProtocalHandlerOutput::WsBuf(out) => {
|
||||||
|
self.link.send_message(RemoteMsg::Send(out));
|
||||||
|
false
|
||||||
|
}
|
||||||
|
ProtocalHandlerOutput::RequirePassword => {
|
||||||
|
self.request_password = true;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn username_view(&self) -> Html {
|
fn username_view(&self) -> Html {
|
||||||
if self.request_username {
|
if self.request_username {
|
||||||
let update_username = self.link.callback(|v| RemoteMsg::UpdateUsername(v));
|
let update_username = self.link.callback(|v| RemoteMsg::UpdateUsername(v));
|
||||||
|
323
frontend/src/protocal/des.rs
Normal file
323
frontend/src/protocal/des.rs
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
pub type Key = [u8; 8];
|
||||||
|
|
||||||
|
const FIRST_BIT: u64 = 1 << 63;
|
||||||
|
const HALF_KEY_SIZE: i64 = KEY_SIZE / 2;
|
||||||
|
const KEY_SIZE: i64 = 56;
|
||||||
|
|
||||||
|
/// Do a circular left shift on a width of HALF_KEY_SIZE.
|
||||||
|
fn circular_left_shift(n1: u64, n2: u64, shift_count: i64) -> (u64, u64) {
|
||||||
|
let mut new_value1 = n1;
|
||||||
|
let mut new_value2 = n2;
|
||||||
|
for _ in 0..shift_count {
|
||||||
|
let first_bit = new_value1 & FIRST_BIT;
|
||||||
|
new_value1 = (new_value1 << 1) | (first_bit >> (HALF_KEY_SIZE - 1));
|
||||||
|
let first_bit = new_value2 & FIRST_BIT;
|
||||||
|
new_value2 = (new_value2 << 1) | (first_bit >> (HALF_KEY_SIZE - 1));
|
||||||
|
}
|
||||||
|
(new_value1, new_value2)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create the 16 subkeys.
|
||||||
|
fn compute_subkeys(key: u64) -> Vec<u64> {
|
||||||
|
let table = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
|
||||||
|
let k0 = pc1(key);
|
||||||
|
let mut subkeys = vec![k0];
|
||||||
|
|
||||||
|
for shift_count in &table {
|
||||||
|
let last_key = subkeys.last().unwrap();
|
||||||
|
let last_ci = last_key & 0xFFFFFFF000000000;
|
||||||
|
let last_di = last_key << HALF_KEY_SIZE;
|
||||||
|
let (ci, di) = circular_left_shift(last_ci, last_di, *shift_count);
|
||||||
|
let current_key = ci | (di >> HALF_KEY_SIZE);
|
||||||
|
subkeys.push(current_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
subkeys.remove(0);
|
||||||
|
subkeys.iter().map(|&n| pc2(n)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swap bits using the E table.
|
||||||
|
fn e(block: u64) -> u64 {
|
||||||
|
let table = [
|
||||||
|
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17,
|
||||||
|
18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
swap_bits(block, &table)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decrypt `message` using the `key`.
|
||||||
|
pub fn decrypt(cipher: &[u8], key: &Key) -> Vec<u8> {
|
||||||
|
let key = key_to_u64(key);
|
||||||
|
let mut subkeys = compute_subkeys(key);
|
||||||
|
subkeys.reverse();
|
||||||
|
des(cipher, subkeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encrypt `message` using `subkeys`.
|
||||||
|
fn des(message: &[u8], subkeys: Vec<u64>) -> Vec<u8> {
|
||||||
|
let blocks = message_to_u64s(message);
|
||||||
|
|
||||||
|
let mut cipher = vec![];
|
||||||
|
|
||||||
|
for block in blocks {
|
||||||
|
let permuted = ip(block);
|
||||||
|
let mut li = permuted & 0xFFFFFFFF00000000;
|
||||||
|
let mut ri = permuted << 32;
|
||||||
|
|
||||||
|
for subkey in &subkeys {
|
||||||
|
let last_li = li;
|
||||||
|
li = ri;
|
||||||
|
ri = last_li ^ feistel(ri, *subkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
let r16l16 = ri | (li >> 32);
|
||||||
|
cipher.append(&mut to_u8_vec(fp(r16l16)));
|
||||||
|
}
|
||||||
|
|
||||||
|
cipher
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encrypt `message` using the `key`.
|
||||||
|
pub fn encrypt(message: &[u8], key: &Key) -> Vec<u8> {
|
||||||
|
let key = key_to_u64(key);
|
||||||
|
let subkeys = compute_subkeys(key);
|
||||||
|
des(message, subkeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Feistel function.
|
||||||
|
fn feistel(half_block: u64, subkey: u64) -> u64 {
|
||||||
|
let expanded = e(half_block);
|
||||||
|
let mut intermediate = expanded ^ subkey;
|
||||||
|
let mut result = 0;
|
||||||
|
|
||||||
|
for i in 0..8 {
|
||||||
|
let block = (intermediate & 0xFC00000000000000) >> 58;
|
||||||
|
intermediate <<= 6;
|
||||||
|
result <<= 4;
|
||||||
|
result |= s(i, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
p(result << 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swap bits using the IP table.
|
||||||
|
fn ip(message: u64) -> u64 {
|
||||||
|
let table = [
|
||||||
|
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14,
|
||||||
|
6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11,
|
||||||
|
3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7,
|
||||||
|
];
|
||||||
|
|
||||||
|
swap_bits(message, &table)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a `Key` to a 64-bits integer.
|
||||||
|
fn key_to_u64(key: &Key) -> u64 {
|
||||||
|
let mut result = 0;
|
||||||
|
for &part in key {
|
||||||
|
result <<= 8;
|
||||||
|
result += part as u64;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a message to a vector of 64-bits integer.
|
||||||
|
fn message_to_u64s(message: &[u8]) -> Vec<u64> {
|
||||||
|
message.chunks(8).map(|m| key_to_u64(&to_key(m))).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swap bits using the P table.
|
||||||
|
fn p(block: u64) -> u64 {
|
||||||
|
let table = [
|
||||||
|
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9,
|
||||||
|
19, 13, 30, 6, 22, 11, 4, 25,
|
||||||
|
];
|
||||||
|
|
||||||
|
swap_bits(block, &table)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swap bits using the PC-1 table.
|
||||||
|
fn pc1(key: u64) -> u64 {
|
||||||
|
let table = [
|
||||||
|
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3,
|
||||||
|
60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45,
|
||||||
|
37, 29, 21, 13, 5, 28, 20, 12, 4,
|
||||||
|
];
|
||||||
|
|
||||||
|
swap_bits(key, &table)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swap bits using the PC-2 table.
|
||||||
|
fn pc2(key: u64) -> u64 {
|
||||||
|
let table = [
|
||||||
|
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41,
|
||||||
|
52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32,
|
||||||
|
];
|
||||||
|
|
||||||
|
swap_bits(key, &table)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swap bits using the reverse FP table.
|
||||||
|
fn fp(message: u64) -> u64 {
|
||||||
|
let table = [
|
||||||
|
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62,
|
||||||
|
30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19,
|
||||||
|
59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25,
|
||||||
|
];
|
||||||
|
|
||||||
|
swap_bits(message, &table)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Produce 4-bits using an S box.
|
||||||
|
fn s(box_id: usize, block: u64) -> u64 {
|
||||||
|
let tables = [
|
||||||
|
[
|
||||||
|
[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
|
||||||
|
[0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
|
||||||
|
[4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
|
||||||
|
[15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
|
||||||
|
[3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
|
||||||
|
[0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
|
||||||
|
[13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
|
||||||
|
[13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
|
||||||
|
[13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
|
||||||
|
[1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15],
|
||||||
|
[13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9],
|
||||||
|
[10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
|
||||||
|
[3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
|
||||||
|
[14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
|
||||||
|
[4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
|
||||||
|
[11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
|
||||||
|
[10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
|
||||||
|
[9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
|
||||||
|
[4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
|
||||||
|
[13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
|
||||||
|
[1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
|
||||||
|
[6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
|
||||||
|
[1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
|
||||||
|
[7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
|
||||||
|
[2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
let i = ((block & 0x20) >> 4 | (block & 1)) as usize;
|
||||||
|
let j = ((block & 0x1E) >> 1) as usize;
|
||||||
|
tables[box_id][i][j]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swap bits using a table.
|
||||||
|
fn swap_bits(key: u64, table: &[u64]) -> u64 {
|
||||||
|
let mut result = 0;
|
||||||
|
|
||||||
|
for (pos, index) in table.iter().enumerate() {
|
||||||
|
let bit = (key << (index - 1)) & FIRST_BIT;
|
||||||
|
result |= bit >> pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a slice to a `Key`.
|
||||||
|
fn to_key(slice: &[u8]) -> Key {
|
||||||
|
let mut vec: Vec<u8> = slice.to_vec();
|
||||||
|
let mut key = [0; 8];
|
||||||
|
let diff = key.len() - vec.len();
|
||||||
|
if diff > 0 {
|
||||||
|
vec.append(&mut vec![0; diff]);
|
||||||
|
}
|
||||||
|
key.clone_from_slice(&vec);
|
||||||
|
key
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a `u64` to a `Vec<u8>`.
|
||||||
|
fn to_u8_vec(num: u64) -> Vec<u8> {
|
||||||
|
vec![
|
||||||
|
((num & 0xFF00000000000000) >> 56) as u8,
|
||||||
|
((num & 0x00FF000000000000) >> 48) as u8,
|
||||||
|
((num & 0x0000FF0000000000) >> 40) as u8,
|
||||||
|
((num & 0x000000FF00000000) >> 32) as u8,
|
||||||
|
((num & 0x00000000FF000000) >> 24) as u8,
|
||||||
|
((num & 0x0000000000FF0000) >> 16) as u8,
|
||||||
|
((num & 0x000000000000FF00) >> 8) as u8,
|
||||||
|
(num & 0x00000000000000FF) as u8,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::{decrypt, encrypt};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_encrypt_decrypt() {
|
||||||
|
let key = [0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1];
|
||||||
|
let message = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF];
|
||||||
|
let expected_cipher = vec![0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A, 0xB4, 0x05];
|
||||||
|
let cipher = encrypt(&message, &key);
|
||||||
|
assert_eq!(cipher, expected_cipher);
|
||||||
|
|
||||||
|
let cipher = expected_cipher;
|
||||||
|
let expected_message = message;
|
||||||
|
let message = decrypt(&cipher, &key);
|
||||||
|
assert_eq!(message, expected_message);
|
||||||
|
|
||||||
|
let message = [
|
||||||
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB,
|
||||||
|
0xCD, 0xEF,
|
||||||
|
];
|
||||||
|
let expected_cipher = vec![
|
||||||
|
0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A, 0xB4, 0x05, 0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A,
|
||||||
|
0xB4, 0x05,
|
||||||
|
];
|
||||||
|
let cipher = encrypt(&message, &key);
|
||||||
|
assert_eq!(cipher, expected_cipher);
|
||||||
|
|
||||||
|
let cipher = expected_cipher;
|
||||||
|
let expected_message = message;
|
||||||
|
let message = decrypt(&cipher, &key);
|
||||||
|
assert_eq!(message, expected_message);
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
pub mod common;
|
pub mod common;
|
||||||
|
mod des;
|
||||||
pub mod vnc;
|
pub mod vnc;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use yew::services::ConsoleService;
|
use yew::services::ConsoleService;
|
||||||
|
|
||||||
use super::common::*;
|
use super::common::*;
|
||||||
|
use super::des;
|
||||||
|
|
||||||
const VNC_RFB33: &[u8; 12] = b"RFB 003.003\n";
|
const VNC_RFB33: &[u8; 12] = b"RFB 003.003\n";
|
||||||
const VNC_RFB37: &[u8; 12] = b"RFB 003.007\n";
|
const VNC_RFB37: &[u8; 12] = b"RFB 003.007\n";
|
||||||
@ -8,12 +9,21 @@ const VNC_RFB38: &[u8; 12] = b"RFB 003.008\n";
|
|||||||
const VNC_VER_UNSUPPORTED: &str = "unsupported version";
|
const VNC_VER_UNSUPPORTED: &str = "unsupported version";
|
||||||
const VNC_FAILED: &str = "Connection failed with unknow reason";
|
const VNC_FAILED: &str = "Connection failed with unknow reason";
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum VncState {
|
enum VncState {
|
||||||
Handshake,
|
Handshake,
|
||||||
Authentication,
|
Authentication,
|
||||||
ClientInit, // auth done
|
ClientInit, // auth done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum VncVersion {
|
||||||
|
NONE,
|
||||||
|
VNC33,
|
||||||
|
VNC37,
|
||||||
|
VNC38,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum SecurityType {
|
pub enum SecurityType {
|
||||||
@ -28,20 +38,29 @@ pub enum SecurityType {
|
|||||||
VeNCrypt = 19,
|
VeNCrypt = 19,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct VncHandler {
|
pub struct VncHandler {
|
||||||
state: VncState,
|
state: VncState,
|
||||||
|
version: VncVersion,
|
||||||
challenge: [u8; 16],
|
challenge: [u8; 16],
|
||||||
security_type: SecurityType,
|
security_type: SecurityType,
|
||||||
password: String,
|
width: u16,
|
||||||
|
height: u16,
|
||||||
|
pf: PixelFormat,
|
||||||
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProtocalImpl for VncHandler {
|
impl ProtocalImpl for VncHandler {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
VncHandler {
|
VncHandler {
|
||||||
state: VncState::Handshake,
|
state: VncState::Handshake,
|
||||||
|
version: VncVersion::NONE,
|
||||||
challenge: [0u8; 16],
|
challenge: [0u8; 16],
|
||||||
security_type: SecurityType::Invalid,
|
security_type: SecurityType::Invalid,
|
||||||
password: String::new(),
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
pf: PixelFormat::default(),
|
||||||
|
name: String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,29 +76,45 @@ impl ProtocalImpl for VncHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
VncState::Authentication => {
|
VncState::Authentication => {
|
||||||
|
// reuse this state for auth repose handling
|
||||||
|
if self.security_type == SecurityType::VncAuth {
|
||||||
|
self.handle_auth_response(input)
|
||||||
|
} else {
|
||||||
|
self.start_authenticate(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VncState::ClientInit => {
|
||||||
ConsoleService::log(&format!("{:?}", input));
|
ConsoleService::log(&format!("{:?}", input));
|
||||||
return self.start_authenticate(input);
|
self.handle_server_init(input)
|
||||||
}
|
}
|
||||||
_ => panic!("unsupported version"),
|
_ => panic!("unsupported version"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_credential(&mut self, _username: &str, password: &str) -> ProtocalHandlerOutput {
|
fn set_credential(&mut self, _username: &str, password: &str) -> ProtocalHandlerOutput {
|
||||||
ConsoleService::log(&format!("{:?}", password));
|
// ConsoleService::log(&format!("{:?}", password));
|
||||||
ConsoleService::log(&format!("{:?}", self.challenge));
|
// ConsoleService::log(&format!("{:?}", self.challenge));
|
||||||
// since vnc do not require username, so we just ignore it
|
// since vnc do not require username, so we just ignore it
|
||||||
self.password = password.to_string();
|
self.continue_authenticate(password)
|
||||||
self.continue_authenticate()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private methods
|
// private methods
|
||||||
impl VncHandler {
|
impl VncHandler {
|
||||||
fn handle_handshake(&self, rfbversion: &[u8]) -> Result<&'static [u8], &'static str> {
|
fn handle_handshake(&mut self, rfbversion: &[u8]) -> Result<&'static [u8], &'static str> {
|
||||||
match rfbversion {
|
match rfbversion {
|
||||||
b"RFB 003.003\n" => Ok(VNC_RFB33),
|
b"RFB 003.003\n" => {
|
||||||
b"RFB 003.007\n" => Ok(VNC_RFB33),
|
self.version = VncVersion::VNC33;
|
||||||
b"RFB 003.008\n" => Ok(VNC_RFB33),
|
Ok(VNC_RFB33)
|
||||||
|
}
|
||||||
|
b"RFB 003.007\n" => {
|
||||||
|
self.version = VncVersion::VNC33;
|
||||||
|
Ok(VNC_RFB33)
|
||||||
|
}
|
||||||
|
b"RFB 003.008\n" => {
|
||||||
|
self.version = VncVersion::VNC33;
|
||||||
|
Ok(VNC_RFB33)
|
||||||
|
}
|
||||||
_ => Err(VNC_VER_UNSUPPORTED),
|
_ => Err(VNC_VER_UNSUPPORTED),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,10 +126,12 @@ impl VncHandler {
|
|||||||
ProtocalHandlerOutput::Err(err_msg)
|
ProtocalHandlerOutput::Err(err_msg)
|
||||||
}
|
}
|
||||||
Some(1) => {
|
Some(1) => {
|
||||||
|
self.security_type = SecurityType::None;
|
||||||
self.state = VncState::ClientInit;
|
self.state = VncState::ClientInit;
|
||||||
self.client_initialisation()
|
self.client_initialisation()
|
||||||
}
|
}
|
||||||
Some(2) => {
|
Some(2) => {
|
||||||
|
self.security_type = SecurityType::VncAuth;
|
||||||
sr.extract_slice(16, &mut self.challenge);
|
sr.extract_slice(16, &mut self.challenge);
|
||||||
ProtocalHandlerOutput::RequirePassword
|
ProtocalHandlerOutput::RequirePassword
|
||||||
}
|
}
|
||||||
@ -103,10 +140,181 @@ impl VncHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn client_initialisation(&mut self) -> ProtocalHandlerOutput {
|
fn client_initialisation(&mut self) -> ProtocalHandlerOutput {
|
||||||
ProtocalHandlerOutput::Ok
|
let shared_flag = 1;
|
||||||
|
|
||||||
|
ProtocalHandlerOutput::WsBuf(vec![shared_flag].into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn continue_authenticate(&mut self) -> ProtocalHandlerOutput {
|
fn continue_authenticate(&mut self, password: &str) -> ProtocalHandlerOutput {
|
||||||
|
// referring
|
||||||
|
// https://github.com/whitequark/rust-vnc/blob/0697238f2706dd34a9a95c1640e385f6d8c02961/src/client.rs
|
||||||
|
// strange behavior
|
||||||
|
|
||||||
|
let pass_len = password.len();
|
||||||
|
let mut pass_bytes = [0u8; 8];
|
||||||
|
for i in 0..8 {
|
||||||
|
let c = if i < pass_len {
|
||||||
|
password.as_bytes()[i]
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
let mut cs = 0u8;
|
||||||
|
for j in 0..8 {
|
||||||
|
cs |= ((c >> j) & 1) << (7 - j)
|
||||||
|
}
|
||||||
|
pass_bytes[i] = cs;
|
||||||
|
}
|
||||||
|
let output = des::encrypt(&self.challenge, &pass_bytes);
|
||||||
|
ProtocalHandlerOutput::WsBuf(output.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_auth_response(&mut self, response: &[u8]) -> ProtocalHandlerOutput {
|
||||||
|
let mut sr = StreamReader::new(response);
|
||||||
|
match sr.read_u32() {
|
||||||
|
Some(0) => {
|
||||||
|
self.state = VncState::ClientInit;
|
||||||
|
self.client_initialisation()
|
||||||
|
}
|
||||||
|
Some(1) => {
|
||||||
|
let err_msg = sr.read_string_l32().unwrap();
|
||||||
|
ProtocalHandlerOutput::Err(err_msg)
|
||||||
|
}
|
||||||
|
_ => ProtocalHandlerOutput::Err(VNC_FAILED.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// example
|
||||||
|
// [7, 128, 4, 176, 32, 24, 0, 1, 0, 255, 0, 255, 0, 255, 16, 8, 0, 0, 0, 0, 0, 0, 0, 14, 54, 122, 122, 100, 114, 113, 50, 45, 106, 105, 97, 120, 117, 0]
|
||||||
|
// No. of bytes Type [Value] Description
|
||||||
|
// 2 CARD16 framebuffer-width
|
||||||
|
// 2 CARD16 framebuffer-height
|
||||||
|
// 16 PIXEL_FORMAT server-pixel-format
|
||||||
|
// 4 CARD32 name-length
|
||||||
|
// name-length CARD8 array name-string
|
||||||
|
fn handle_server_init(&mut self, init: &[u8]) -> ProtocalHandlerOutput {
|
||||||
|
let mut sr = StreamReader::new(init);
|
||||||
|
self.width = sr.read_u16().unwrap();
|
||||||
|
self.height = sr.read_u16().unwrap();
|
||||||
|
let mut pfb: [u8; 16] = [0u8; 16];
|
||||||
|
sr.extract_slice(16, &mut pfb);
|
||||||
|
// This pixel format will be used unless the client requests a different format using the SetPixelFormat message
|
||||||
|
self.pf = (&pfb).into();
|
||||||
|
self.name = sr.read_string_l32().unwrap();
|
||||||
|
|
||||||
|
ConsoleService::log(&format!("{:?}", self));
|
||||||
ProtocalHandlerOutput::Ok
|
ProtocalHandlerOutput::Ok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No. of bytes Type [Value] Description
|
||||||
|
// 1 CARD8 bits-per-pixel
|
||||||
|
// 1 CARD8 depth
|
||||||
|
// 1 CARD8 big-endian-flag
|
||||||
|
// 1 CARD8 true-color-flag
|
||||||
|
// 2 CARD16 red-max
|
||||||
|
// 2 CARD16 green-max
|
||||||
|
// 2 CARD16 blue-max
|
||||||
|
// 1 CARD8 red-shift
|
||||||
|
// 1 CARD8 green-shift
|
||||||
|
// 1 CARD8 blue-shift
|
||||||
|
// 1 CARD8 padding
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct PixelFormat {
|
||||||
|
// the number of bits used for each pixel value on the wire
|
||||||
|
// 8, 16, 32(usually) only
|
||||||
|
bits_per_pixel: u8,
|
||||||
|
depth: u8,
|
||||||
|
// true if multi-byte pixels are interpreted as big endian
|
||||||
|
big_endian_flag: u8,
|
||||||
|
// true then the last six items specify how to extract the red, green and blue intensities from the pixel value
|
||||||
|
true_color_flag: u8,
|
||||||
|
// the next three always in big-endian order
|
||||||
|
// no matter how the `big_endian_flag` is set
|
||||||
|
red_max: u16,
|
||||||
|
green_max: u16,
|
||||||
|
blue_max: u16,
|
||||||
|
// the number of shifts needed to get the red value in a pixel to the least significant bit
|
||||||
|
red_shift: u8,
|
||||||
|
green_shift: u8,
|
||||||
|
blue_shift: u8,
|
||||||
|
padding_1: u8,
|
||||||
|
padding_2: u8,
|
||||||
|
padding_3: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PixelFormat> for Vec<u8> {
|
||||||
|
fn from(pf: PixelFormat) -> Vec<u8> {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
v.push(pf.bits_per_pixel);
|
||||||
|
v.push(pf.depth);
|
||||||
|
v.push(pf.big_endian_flag);
|
||||||
|
v.push(pf.true_color_flag);
|
||||||
|
v.push((pf.red_max >> 8) as u8);
|
||||||
|
v.push(pf.red_max as u8);
|
||||||
|
v.push((pf.green_max >> 8) as u8);
|
||||||
|
v.push(pf.green_max as u8);
|
||||||
|
v.push((pf.blue_max >> 8) as u8);
|
||||||
|
v.push(pf.blue_max as u8);
|
||||||
|
v.push(pf.red_shift);
|
||||||
|
v.push(pf.green_shift);
|
||||||
|
v.push(pf.blue_shift);
|
||||||
|
v.push(pf.padding_1);
|
||||||
|
v.push(pf.padding_2);
|
||||||
|
v.push(pf.padding_3);
|
||||||
|
v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&[u8; 16]> for PixelFormat {
|
||||||
|
fn from(pf: &[u8; 16]) -> Self {
|
||||||
|
let mut sr = StreamReader::new(pf);
|
||||||
|
let bits_per_pixel = sr.read_u8().unwrap();
|
||||||
|
let depth = sr.read_u8().unwrap();
|
||||||
|
let big_endian_flag = sr.read_u8().unwrap();
|
||||||
|
let true_color_flag = sr.read_u8().unwrap();
|
||||||
|
let red_max = sr.read_u16().unwrap();
|
||||||
|
let green_max = sr.read_u16().unwrap();
|
||||||
|
let blue_max = sr.read_u16().unwrap();
|
||||||
|
let red_shift = sr.read_u8().unwrap();
|
||||||
|
let green_shift = sr.read_u8().unwrap();
|
||||||
|
let blue_shift = sr.read_u8().unwrap();
|
||||||
|
let padding_1 = sr.read_u8().unwrap();
|
||||||
|
let padding_2 = sr.read_u8().unwrap();
|
||||||
|
let padding_3 = sr.read_u8().unwrap();
|
||||||
|
Self {
|
||||||
|
bits_per_pixel,
|
||||||
|
depth,
|
||||||
|
big_endian_flag,
|
||||||
|
true_color_flag,
|
||||||
|
red_max,
|
||||||
|
green_max,
|
||||||
|
blue_max,
|
||||||
|
red_shift,
|
||||||
|
green_shift,
|
||||||
|
blue_shift,
|
||||||
|
padding_1,
|
||||||
|
padding_2,
|
||||||
|
padding_3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PixelFormat {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
bits_per_pixel: 0,
|
||||||
|
depth: 0,
|
||||||
|
big_endian_flag: 0,
|
||||||
|
true_color_flag: 0,
|
||||||
|
red_max: 0,
|
||||||
|
green_max: 0,
|
||||||
|
blue_max: 0,
|
||||||
|
red_shift: 0,
|
||||||
|
green_shift: 0,
|
||||||
|
blue_shift: 0,
|
||||||
|
padding_1: 0,
|
||||||
|
padding_2: 0,
|
||||||
|
padding_3: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user