Skip to content

Commit 7c27c0d

Browse files
authored
init
0 parents  commit 7c27c0d

File tree

7 files changed

+877
-0
lines changed

7 files changed

+877
-0
lines changed

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "data_storage"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
aes-gcm = "0.10.1"
8+
rand = "0.8.5"
9+
chrono = { version = "0.4", features = ["serde"] }
10+
serde = { version = "1.0", features = ["derive"] }
11+
bincode = "1.3"

LICENSE

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# IntelliLog-Database
2+
Database for IntelliLog Open Source Project
3+
4+
5+
# Docs
6+
7+
- We are storing all the data in ```.itlg``` custom file format made for IntelliLog Project, Pronounce as "It Log"
8+
9+
### Usage
10+
- ```cargo build``` for building
11+
- ```cargo run write myFileName "header" "body"``` for writing into itlg db
12+
- ```cargo run read myFileName``` for reading itlg db
13+
14+
### Note
15+
- Data Format ```TIME HEADER BODY```
16+
- The project is still under development, The above are subjected to change
17+
18+
### Contributors
19+
20+
**Creator/Founder**: Sugam Kuber ([Github](https://github.com/sugamkuber)) ([LinkedIn](https://linkedin.com/in/sugamkuber))

src/helper/crypto.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use aes_gcm::{
2+
aead::{Aead, KeyInit, OsRng},
3+
Aes256Gcm, Nonce
4+
};
5+
use rand::Rng;
6+
7+
pub fn encrypt(data: &[u8], key: &[u8; 32]) -> Vec<u8> {
8+
let cipher = Aes256Gcm::new_from_slice(key).unwrap();
9+
let nonce_bytes = random_nonce();
10+
let nonce = Nonce::from_slice(&nonce_bytes);
11+
let ciphertext = cipher.encrypt(nonce, data).unwrap();
12+
[&nonce_bytes[..], &ciphertext].concat()
13+
}
14+
15+
pub fn decrypt(encrypted_data: &[u8], key: &[u8; 32]) -> Option<Vec<u8>> {
16+
if encrypted_data.len() < 12 {
17+
return None;
18+
}
19+
let (nonce, ciphertext) = encrypted_data.split_at(12);
20+
let cipher = Aes256Gcm::new_from_slice(key).unwrap();
21+
cipher.decrypt(Nonce::from_slice(nonce), ciphertext).ok()
22+
}
23+
24+
fn random_nonce() -> [u8; 12] {
25+
let mut rng = OsRng;
26+
rng.gen()
27+
}

src/main.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
mod ops {
2+
pub mod read;
3+
pub mod write;
4+
}
5+
6+
mod helper {
7+
pub mod crypto;
8+
}
9+
10+
use std::env;
11+
use std::io;
12+
13+
fn main() -> io::Result<()> {
14+
let args: Vec<String> = env::args().collect();
15+
16+
// This should be securely stored and retrieved in a real application
17+
let key: [u8; 32] = [1; 32]; // Example key, don't use this in production!
18+
19+
if args.len() < 3 {
20+
eprintln!("Usage: {} [write <filename> <headers> <body> | read <filename>]", args[0]);
21+
return Ok(());
22+
}
23+
24+
match args[1].as_str() {
25+
"write" => {
26+
if args.len() != 5 {
27+
eprintln!("Usage: {} write <filename> <headers> <body>", args[0]);
28+
} else {
29+
let filename = format!("{}.itlg", args[2]);
30+
let headers = args[3].clone();
31+
let body = args[4].clone();
32+
ops::write::write_record(&filename, headers, body, &key)?;
33+
}
34+
},
35+
"read" => {
36+
if args.len() != 3 {
37+
eprintln!("Usage: {} read <filename>", args[0]);
38+
} else {
39+
let filename = format!("{}.itlg", args[2]);
40+
ops::read::read_records(&filename, &key)?;
41+
}
42+
},
43+
_ => {
44+
eprintln!("Unknown command: {}", args[1]);
45+
}
46+
}
47+
48+
Ok(())
49+
}

src/ops/read.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use std::fs::File;
2+
use std::io::{self, BufReader, Read, Seek, SeekFrom};
3+
use chrono::prelude::*;
4+
use serde::{Serialize, Deserialize};
5+
use bincode;
6+
use crate::helper::crypto;
7+
8+
#[derive(Serialize, Deserialize, Debug)]
9+
pub struct DataRecord {
10+
pub time: DateTime<Utc>,
11+
pub headers: String,
12+
pub body: String,
13+
}
14+
15+
pub fn read_records(filename: &str, key: &[u8; 32]) -> io::Result<()> {
16+
let mut file = File::open(filename)?;
17+
let file_len = file.metadata()?.len();
18+
let mut position = 0;
19+
20+
while position < file_len {
21+
file.seek(SeekFrom::Start(position))?;
22+
let mut reader = BufReader::new(&file);
23+
let mut size_buffer = [0u8; 4];
24+
25+
reader.read_exact(&mut size_buffer)?;
26+
let size = u32::from_be_bytes(size_buffer) as usize;
27+
28+
let mut encrypted_buffer = vec![0u8; size];
29+
reader.read_exact(&mut encrypted_buffer)?;
30+
31+
if let Some(decrypted) = crypto::decrypt(&encrypted_buffer, key) {
32+
match bincode::deserialize::<DataRecord>(&decrypted) {
33+
Ok(record) => println!("{:?}", record),
34+
Err(e) => eprintln!("Error deserializing record: {}", e),
35+
}
36+
} else {
37+
eprintln!("Error decrypting record");
38+
}
39+
40+
position += 4 + size as u64;
41+
}
42+
43+
Ok(())
44+
}

src/ops/write.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use std::fs::{OpenOptions};
2+
use std::io::{self, Write, Read, Seek, SeekFrom};
3+
use chrono::prelude::*;
4+
use serde::{Serialize, Deserialize};
5+
use bincode;
6+
use crate::helper::crypto;
7+
8+
#[derive(Serialize, Deserialize, Debug)]
9+
pub struct DataRecord {
10+
pub time: DateTime<Utc>,
11+
pub headers: String,
12+
pub body: String,
13+
}
14+
15+
impl DataRecord {
16+
pub fn new(headers: String, body: String) -> Self {
17+
Self {
18+
time: Utc::now(),
19+
headers,
20+
body,
21+
}
22+
}
23+
}
24+
25+
pub fn write_record(filename: &str, headers: String, body: String, key: &[u8; 32]) -> io::Result<()> {
26+
let record = DataRecord::new(headers, body);
27+
let mut file = OpenOptions::new()
28+
.read(true)
29+
.write(true)
30+
.create(true)
31+
.open(filename)?;
32+
33+
let encoded: Vec<u8> = bincode::serialize(&record).unwrap();
34+
let encrypted = crypto::encrypt(&encoded, key);
35+
let new_record = (encrypted.len() as u32).to_be_bytes().to_vec();
36+
let new_record = [new_record, encrypted].concat();
37+
38+
// Read existing content
39+
let mut existing_content = Vec::new();
40+
file.read_to_end(&mut existing_content)?;
41+
42+
// Move file cursor to the beginning
43+
file.seek(SeekFrom::Start(0))?;
44+
45+
// Write new record followed by existing content
46+
file.write_all(&new_record)?;
47+
file.write_all(&existing_content)?;
48+
file.set_len(new_record.len() as u64 + existing_content.len() as u64)?;
49+
file.flush()?;
50+
51+
Ok(())
52+
}

0 commit comments

Comments
 (0)