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
20 changes: 19 additions & 1 deletion Cargo.lock

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

6 changes: 5 additions & 1 deletion kinode/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "6f8ebb4" }
alloy-rpc-client = { git = "https://github.com/alloy-rs/alloy", rev = "6f8ebb4", features = ["ws"]}
alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "6f8ebb4" }
alloy-providers = { git = "https://github.com/alloy-rs/alloy", rev = "6f8ebb4" }
alloy-primitives = "0.6.2"
alloy-sol-macro = "0.6.2"
alloy-sol-types = "0.6.2"
alloy-signer = { git = "https://github.com/alloy-rs/alloy", rev = "6f8ebb4" }
anyhow = "1.0.71"
async-trait = "0.1.71"
base64 = "0.13"
Expand Down Expand Up @@ -84,4 +88,4 @@ uuid = { version = "1.1.2", features = ["serde", "v4"] }
warp = "0.3.5"
wasmtime = "17.0.1"
wasmtime-wasi = "17.0.1"
zip = "0.6"
zip = "0.6"
2 changes: 1 addition & 1 deletion kinode/src/http/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ async fn login_handler(
password: "secret".to_string(),
};

match keygen::decode_keyfile(&encoded_keyfile, &info.password) {
match keygen::decode_keyfile(&encoded_keyfile, &info.password_hash) {
Ok(keyfile) => {
let token = match register::generate_jwt(&keyfile.jwt_secret_bytes, our.as_ref()) {
Some(token) => token,
Expand Down
59 changes: 36 additions & 23 deletions kinode/src/keygen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ use aes_gcm::{
aead::{Aead, AeadCore, KeyInit, OsRng},
Aes256Gcm, Key,
};
use digest::generic_array;
use lazy_static::__Deref;
use alloy_primitives::keccak256;
use digest::generic_array::GenericArray;
use lib::types::core::Keyfile;
use ring::pbkdf2;
use ring::pkcs8::Document;
use ring::rand::SystemRandom;
use ring::signature::{self, KeyPair};
use ring::{digest as ring_digest, rand::SecureRandom};
use std::num::NonZeroU32;

use lib::types::core::Keyfile;

type DiskKey = [u8; CREDENTIAL_LEN];

pub const CREDENTIAL_LEN: usize = ring_digest::SHA256_OUTPUT_LEN;
Expand All @@ -24,13 +23,12 @@ pub fn encode_keyfile(
username: String,
routers: Vec<String>,
networking_key: &[u8],
jwt: Vec<u8>,
file_key: Vec<u8>,
jwt: &[u8],
file_key: &[u8],
) -> Vec<u8> {
let mut disk_key: DiskKey = [0u8; CREDENTIAL_LEN];

let rng = SystemRandom::new();

let mut salt = [0u8; 32]; // generate a unique salt
rng.fill(&mut salt).unwrap();

Expand All @@ -50,16 +48,16 @@ pub fn encode_keyfile(
let file_nonce = Aes256Gcm::generate_nonce(&mut OsRng);

let keyciphertext: Vec<u8> = cipher.encrypt(&network_nonce, networking_key).unwrap();
let jwtciphertext: Vec<u8> = cipher.encrypt(&jwt_nonce, jwt.as_ref()).unwrap();
let jwtciphertext: Vec<u8> = cipher.encrypt(&jwt_nonce, jwt).unwrap();
let fileciphertext: Vec<u8> = cipher.encrypt(&file_nonce, file_key.as_ref()).unwrap();

bincode::serialize(&(
username.clone(),
routers.clone(),
salt.to_vec(),
[network_nonce.deref().to_vec(), keyciphertext].concat(),
[jwt_nonce.deref().to_vec(), jwtciphertext].concat(),
[file_nonce.deref().to_vec(), fileciphertext].concat(),
[network_nonce.to_vec(), keyciphertext].concat(),
[jwt_nonce.to_vec(), jwtciphertext].concat(),
[file_nonce.to_vec(), fileciphertext].concat(),
))
.unwrap()
}
Expand All @@ -82,9 +80,9 @@ pub fn decode_keyfile(keyfile: &[u8], password: &str) -> Result<Keyfile, &'stati
let cipher_key = Key::<Aes256Gcm>::from_slice(&disk_key);
let cipher = Aes256Gcm::new(cipher_key);

let net_nonce = generic_array::GenericArray::from_slice(&key_enc[..12]);
let jwt_nonce = generic_array::GenericArray::from_slice(&jwt_enc[..12]);
let file_nonce = generic_array::GenericArray::from_slice(&file_enc[..12]);
let net_nonce = GenericArray::from_slice(&key_enc[..12]);
let jwt_nonce = GenericArray::from_slice(&jwt_enc[..12]);
let file_nonce = GenericArray::from_slice(&file_enc[..12]);

let serialized_networking_keypair: Vec<u8> = cipher
.decrypt(net_nonce, &key_enc[12..])
Expand All @@ -111,13 +109,35 @@ pub fn decode_keyfile(keyfile: &[u8], password: &str) -> Result<Keyfile, &'stati
}

pub fn get_username_and_routers(keyfile: &[u8]) -> Result<(String, Vec<String>), &'static str> {
let (username, routers, _salt, _key_enc, _jwt_enc, _file_enc) =
bincode::deserialize::<(String, Vec<String>, Vec<u8>, Vec<u8>, Vec<u8>, Vec<u8>)>(keyfile)
let (username, routers, _salt, _key_enc, _jwt_enc) =
bincode::deserialize::<(String, Vec<String>, Vec<u8>, Vec<u8>, Vec<u8>)>(keyfile)
.map_err(|_| "failed to deserialize keyfile")?;

Ok((username, routers))
}

pub fn namehash(name: &str) -> Vec<u8> {
let mut node = vec![0u8; 32];
if name.is_empty() {
return node;
}
let mut labels: Vec<&str> = name.split(".").collect();
labels.reverse();
for label in labels.iter() {
node.append(&mut keccak256(label.as_bytes()).to_vec());
node = keccak256(node.as_slice()).to_vec();
}
node
}

/// randomly generated key to encrypt file chunks,
pub fn generate_file_key() -> Vec<u8> {
let mut key = [0u8; 32];
let rng = SystemRandom::new();
rng.fill(&mut key).unwrap();
key.to_vec()
}

/// # Returns
/// a pair of (public key (encoded as a hex string), serialized key as a pkcs8 Document)
pub fn generate_networking_key() -> (String, Document) {
Expand All @@ -126,10 +146,3 @@ pub fn generate_networking_key() -> (String, Document) {
let keys = signature::Ed25519KeyPair::from_pkcs8(doc.as_ref()).unwrap();
(hex::encode(keys.public_key().as_ref()), doc)
}
/// randomly generated key to encrypt file chunks, encrypted on-disk with disk_key
pub fn generate_file_key() -> Vec<u8> {
let mut key = [0u8; 32];
let rng = SystemRandom::new();
rng.fill(&mut key).unwrap();
key.to_vec()
}
8 changes: 4 additions & 4 deletions kinode/src/register-ui/build/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"files": {
"main.css": "/static/css/main.dce05a4d.css",
"main.js": "/static/js/main.726c0750.js",
"main.css": "/static/css/main.054f6f32.css",
"main.js": "/static/js/main.00b7179d.js",
"static/media/unknown.png": "/static/media/unknown.880d04d4611a45ab1001.png",
"static/media/background.jpg": "/static/media/background.01d2427cfc21fb685016.jpg",
"static/media/kinode.svg": "/static/media/kinode.86d0c1a6a4a3ca3be41616b5989d6925.svg",
"index.html": "/index.html",
"static/media/logo.svg": "/static/media/logo.45dcb752ac5b825f5e3b9299d2210f0a.svg"
},
"entrypoints": [
"static/css/main.dce05a4d.css",
"static/js/main.726c0750.js"
"static/css/main.054f6f32.css",
"static/js/main.00b7179d.js"
]
}
2 changes: 1 addition & 1 deletion kinode/src/register-ui/build/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><title>Welcome - Kinode</title><meta charset="utf-8"/><meta http-equiv="pragma" content="no-cache"/><meta http-equiv="cache-control" content="no-cache"/><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet"><link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzc5IiBoZWlnaHQ9IjUxNCIgdmlld0JveD0iMCAwIDc3OSA1MTQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICA8c3R5bGU+CiAgICAgICAgQG1lZGlhIChwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyaykgewogICAgICAgICAgICBzdmcgeyBmaWxsOiB3aGl0ZTsgfQogICAgICAgIH0KICAgICAgICBAbWVkaWEgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBsaWdodCkgewogICAgICAgICAgICBzdmcgeyBmaWxsOiBibGFjazsgfQogICAgICAgIH0KICAgIDwvc3R5bGU+CiAgICA8cGF0aCBkPSJNNzUzLjA5MiA1LjkxOTMyQzc1Ni41NTcgNS4wOTk3NiA3NTUuOTYyIC0wLjAwMDEyMjA3IDc1Mi40MDEgLTAuMDAwMTIyMDdINDI2LjAwMUM0MjQuNzU1IC0wLjAwMDEyMjA3IDQyMy42MzkgMC43NzAyNyA0MjMuMTk3IDEuOTM1MzVMMjM2Ljk2OCA0OTIuNkMyMzUuNzI5IDQ5NS44NjUgMjQwLjEyMyA0OTguMjU1IDI0Mi4xOTEgNDk1LjQ0MUw1NjkuMzU3IDUwLjExMzJDNTY5Ljc3OCA0OS41MzkyIDU3MC4zOTEgNDkuMTMzOSA1NzEuMDg0IDQ4Ljk3TDc1My4wOTIgNS45MTkzMloiLz4KICAgIDxwYXRoIGQ9Ik0xMS45NjY1IDQwLjIyODhDOS4xMDk0OSAzOC43NzcgMTAuMjEzNSAzNC40NTgzIDEzLjQxNjcgMzQuNTU1N0w0MDQuMjczIDQ2LjQzNjdDNDA2LjMzNCA0Ni40OTkzIDQwNy43MTkgNDguNTc0OSA0MDYuOTg2IDUwLjUwMjNMMzQ3LjQzOCAyMDYuOTgxQzM0Ni44MDQgMjA4LjY0NyAzNDQuODY1IDIwOS4zOTYgMzQzLjI3NSAyMDguNTg4TDExLjk2NjUgNDAuMjI4OFoiLz4KPC9zdmc+Cg=="><meta httpequiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1.00001,viewport-fit=cover"/><script defer="defer" src="/static/js/main.726c0750.js"></script><link href="/static/css/main.dce05a4d.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><title>Welcome - Kinode</title><meta charset="utf-8"/><meta http-equiv="pragma" content="no-cache"/><meta http-equiv="cache-control" content="no-cache"/><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet"><link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzc5IiBoZWlnaHQ9IjUxNCIgdmlld0JveD0iMCAwIDc3OSA1MTQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICA8c3R5bGU+CiAgICAgICAgQG1lZGlhIChwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyaykgewogICAgICAgICAgICBzdmcgeyBmaWxsOiB3aGl0ZTsgfQogICAgICAgIH0KICAgICAgICBAbWVkaWEgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBsaWdodCkgewogICAgICAgICAgICBzdmcgeyBmaWxsOiBibGFjazsgfQogICAgICAgIH0KICAgIDwvc3R5bGU+CiAgICA8cGF0aCBkPSJNNzUzLjA5MiA1LjkxOTMyQzc1Ni41NTcgNS4wOTk3NiA3NTUuOTYyIC0wLjAwMDEyMjA3IDc1Mi40MDEgLTAuMDAwMTIyMDdINDI2LjAwMUM0MjQuNzU1IC0wLjAwMDEyMjA3IDQyMy42MzkgMC43NzAyNyA0MjMuMTk3IDEuOTM1MzVMMjM2Ljk2OCA0OTIuNkMyMzUuNzI5IDQ5NS44NjUgMjQwLjEyMyA0OTguMjU1IDI0Mi4xOTEgNDk1LjQ0MUw1NjkuMzU3IDUwLjExMzJDNTY5Ljc3OCA0OS41MzkyIDU3MC4zOTEgNDkuMTMzOSA1NzEuMDg0IDQ4Ljk3TDc1My4wOTIgNS45MTkzMloiLz4KICAgIDxwYXRoIGQ9Ik0xMS45NjY1IDQwLjIyODhDOS4xMDk0OSAzOC43NzcgMTAuMjEzNSAzNC40NTgzIDEzLjQxNjcgMzQuNTU1N0w0MDQuMjczIDQ2LjQzNjdDNDA2LjMzNCA0Ni40OTkzIDQwNy43MTkgNDguNTc0OSA0MDYuOTg2IDUwLjUwMjNMMzQ3LjQzOCAyMDYuOTgxQzM0Ni44MDQgMjA4LjY0NyAzNDQuODY1IDIwOS4zOTYgMzQzLjI3NSAyMDguNTg4TDExLjk2NjUgNDAuMjI4OFoiLz4KPC9zdmc+Cg=="><meta httpequiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1.00001,viewport-fit=cover"/><script defer="defer" src="/static/js/main.00b7179d.js"></script><link href="/static/css/main.054f6f32.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
1 change: 1 addition & 0 deletions kinode/src/register-ui/build/static/css/main.054f6f32.css

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

Loading