<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: kekeli🦀</title>
    <description>The latest articles on Forem by kekeli🦀 (@dompehbright).</description>
    <link>https://forem.com/dompehbright</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1169133%2Fc419cbe3-f0e1-4ea3-8cf0-69aeffd8b8aa.jpg</url>
      <title>Forem: kekeli🦀</title>
      <link>https://forem.com/dompehbright</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dompehbright"/>
    <language>en</language>
    <item>
      <title>about kelvin, a terminal password manager i'm building</title>
      <dc:creator>kekeli🦀</dc:creator>
      <pubDate>Sun, 09 Jun 2024 19:03:16 +0000</pubDate>
      <link>https://forem.com/dompehbright/about-kelvin-a-terminal-password-manager-im-building-a1c</link>
      <guid>https://forem.com/dompehbright/about-kelvin-a-terminal-password-manager-im-building-a1c</guid>
      <description>&lt;h3&gt;
  
  
  overview
&lt;/h3&gt;

&lt;p&gt;kelvin is a password manager for the linux terminal, it generates passwords, and it could be used as a vault to save and secure passwords. kelvin creates your vault locally. vault is encrypted and made a hidden directory.&lt;/p&gt;

&lt;p&gt;in building kelvin, i depended on a skeleton of three structs, admin, deck and deck_data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub struct Admin {
    pub username: String,
    pub password: String,
}

pub struct Deck {
    pub domain: String,
    pub plaintext: String,
}

pub struct DeckData {
    pub domain: String,
    pub ciphertext: Vec&amp;lt;u8&amp;gt;,
    pub admin_data: Admin,
    pub rsa_public_key: String,
    pub rsa_private_key: String,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  admin.rs
&lt;/h3&gt;

&lt;p&gt;the admin struct has the username and passwords fields. implementations on admin struct mainly deal with creating an administrator, validating administator and serialization and deserialization.&lt;/p&gt;

&lt;h3&gt;
  
  
  implemetations on admin struct
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;new()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a constructor method for creating an Admin instance.&lt;/li&gt;
&lt;li&gt;It takes a name (username) and a password as arguments.&lt;/li&gt;
&lt;li&gt;It initializes the Admin struct with the provided username and password.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;hash_password()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This method hashes the admin's password for security.&lt;/li&gt;
&lt;li&gt;It uses the bcrypt crate to hash the password with a default cost.&lt;/li&gt;
&lt;li&gt;The hashed password replaces the original password in the struct.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;verify_password()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This method verifies a password against the hashed password stored in the Admin struct.&lt;/li&gt;
&lt;li&gt;It compares the provided password with the stored hashed password.&lt;/li&gt;
&lt;li&gt;Returns true if the provided password matches the stored hashed password, otherwise false.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;save_to_json()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serializes the Admin struct to JSON and saves it to a file.&lt;/li&gt;
&lt;li&gt;It converts the struct to a JSON string using serde_json.&lt;/li&gt;
&lt;li&gt;Constructs a filepath based on the admin's username and a predefined constant VAULT_PATH.&lt;/li&gt;
&lt;li&gt;Writes the JSON string representation of the admin data to the file.&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;encrypt_directory()&lt;/code&gt; to encrypt the directory containing the file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;read_data_from_json()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads admin data from a JSON file and deserializes it into an Admin struct.&lt;/li&gt;
&lt;li&gt;Constructs a filepath based on the admin's username and &lt;code&gt;VAULT_PATH&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;decrypt_directory()&lt;/code&gt; to decrypt the directory containing the file.&lt;/li&gt;
&lt;li&gt;Reads the contents of the file into a string.&lt;/li&gt;
&lt;li&gt;Deserializes the JSON string into an Admin struct.&lt;/li&gt;
&lt;li&gt;Returns the deserialized Admin struct.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;prompt_auth()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts for authentication by comparing provided username and password with stored admin credentials.&lt;/li&gt;
&lt;li&gt;Reads admin data from JSON using &lt;code&gt;read_data_from_json()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Compares the provided username with the stored username and verifies the provided password.&lt;/li&gt;
&lt;li&gt;Returns true if both username and password match, otherwise false.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  deck.rs
&lt;/h3&gt;

&lt;p&gt;deck struct manages the creation of a deck, a single data that has a domain and it's password(plaintext).&lt;/p&gt;

&lt;h3&gt;
  
  
  implementation`s on deck struct
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;new()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Constructor method for creating a new Deck instance.&lt;/li&gt;
&lt;li&gt;Takes a domain and plaintext as arguments.&lt;/li&gt;
&lt;li&gt;Initializes the Deck struct with the provided domain and plaintext.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;encrypt()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encrypts the plaintext data of the deck using RSA encryption.&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;get_keys()&lt;/code&gt; to obtain RSA keys and a random number generator.&lt;/li&gt;
&lt;li&gt;Converts the plaintext to bytes.&lt;/li&gt;
&lt;li&gt;Encrypts the plaintext using RSA public key encryption (PKCS#1 v1.5 padding).&lt;/li&gt;
&lt;li&gt;Returns a tuple containing the encrypted data and the RSA keys.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;read_data_from_json():&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads deck data from a JSON file and deserializes it into a DeckData struct (not defined in this snippet).&lt;/li&gt;
&lt;li&gt;Constructs a filepath based on the deck's domain and a predefined constant &lt;code&gt;VAULT_PATH&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;decrypt_directory()&lt;/code&gt; to decrypt the directory containing the file.&lt;/li&gt;
&lt;li&gt;Reads the contents of the file into a string.&lt;/li&gt;
&lt;li&gt;Deserializes the JSON string into a &lt;code&gt;Vec&amp;lt;DeckData&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Returns the first DeckData from the vector or an error if no data is found.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  deckdata.rs
&lt;/h3&gt;

&lt;p&gt;deckdata struct deals serializing of the deck to a json file and saving the deck.&lt;/p&gt;

&lt;h3&gt;
  
  
  implementations on deckdata struct
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;new()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a constructor method for &lt;code&gt;DeckData&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It takes arguments to initialize the fields of &lt;code&gt;DeckData&lt;/code&gt;, including Admin data, domain, ciphertext, RSA public key, and RSA private key.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It converts RSA public and private keys to PKCS#1 PEM format and initializes the struct.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;serialize_struct()&lt;/code&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Serializes the struct to a JSON string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uses the serde_json crate to convert the struct into a JSON string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Returns the JSON string representation of the struct.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;save_to_json()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serializes the struct to JSON and saves it to a file.&lt;/li&gt;
&lt;li&gt;Constructs a filepath based on the domain and a predefined constant &lt;code&gt;VAULT_PATH&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Writes the JSON string representation of the struct to the file.&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;encrypt_directory()&lt;/code&gt; (defined in data.rs) to encrypt the directory.&lt;/li&gt;
&lt;li&gt;Returns a Result indicating success or failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;read_data_from_json()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads JSON data from a file, deserializes it into a &lt;code&gt;DeckData&lt;/code&gt; struct.&lt;/li&gt;
&lt;li&gt;Constructs a filepath based on the domain and &lt;code&gt;VAULT_PATH&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;decrypt_directory() &lt;/code&gt;(defined in data.rs) to decrypt the directory.&lt;/li&gt;
&lt;li&gt;Reads the contents of the file into a string.&lt;/li&gt;
&lt;li&gt;Deserializes the JSON string into a &lt;code&gt;Vec&amp;lt;DeckData&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Returns the first &lt;code&gt;DeckData&lt;/code&gt; from the vector or an error if no data is found.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;decrypt()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decrypts the ciphertext using RSA private key.&lt;/li&gt;
&lt;li&gt;Parses the RSA public and private keys from their PEM representations.&lt;/li&gt;
&lt;li&gt;Decrypts the ciphertext using RSA with PKCS#1 v1.5 padding.&lt;/li&gt;
&lt;li&gt;Returns the decrypted data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  helping scripts
&lt;/h3&gt;

&lt;p&gt;aside the main skeleton, other scripts contain helping functions that help make kelvin work as a whole.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;data.rs&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;check_file_exists(username: &amp;amp;str, directory_path: &amp;amp;str) -&amp;gt; bool&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checks if a file with the given username exists in the directory_path.&lt;/li&gt;
&lt;li&gt;Iterates through the directory to find the file.&lt;/li&gt;
&lt;li&gt;Returns true if the file exists, otherwise false.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;read_user_data(username: &amp;amp;str, directory_path: &amp;amp;str) -&amp;gt; Option&amp;lt;Admin&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads user data from a file specified by username and directory_path.&lt;/li&gt;
&lt;li&gt;If the file exists, reads its content, deserializes it into an Admin struct, and returns it.&lt;/li&gt;
&lt;li&gt;Returns None if the file doesn't exist or if there's an error in reading/deserializing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;read_deck_data(domain: &amp;amp;str) -&amp;gt; Option&amp;lt;deckdata::DeckData&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads deck data from a JSON file specified by domain and &lt;code&gt;VAULT_PATH&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the file exists, reads its content, deserializes it into a DeckData struct, and returns it.&lt;/li&gt;
&lt;li&gt;Returns None if the file doesn't exist or if there's an error in reading/deserializing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;encrypt_directory() -&amp;gt; std::io::Result&amp;lt;()&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encrypts the directory containing encrypted data.&lt;/li&gt;
&lt;li&gt;Archives the directory into a .tar.gz file.&lt;/li&gt;
&lt;li&gt;Encrypts the .tar.gz file using gpg.&lt;/li&gt;
&lt;li&gt;Deletes the original directory and the .tar.gz file.&lt;/li&gt;
&lt;li&gt;Returns a Result indicating success or failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;decrypt_directory() -&amp;gt; std::io::Result&amp;lt;()&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decrypts the directory containing encrypted data.&lt;/li&gt;
&lt;li&gt;Decrypts the .tar.gz.gpg file using gpg.&lt;/li&gt;
&lt;li&gt;Extracts the decrypted .tar.gz file.&lt;/li&gt;
&lt;li&gt;Deletes the encrypted .tar.gz.gpg file.&lt;/li&gt;
&lt;li&gt;Returns a Result indicating success or failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;password.rs&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;generate_password(length: usize) -&amp;gt; String&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generates a password from printable ASCII characters, including symbols, digits, uppercase, and lowercase letters.&lt;/li&gt;
&lt;li&gt;Randomly selects characters from the ASCII character set to create the password of the specified length.&lt;/li&gt;
&lt;li&gt;Shuffles the characters within the password to enhance randomness and security.&lt;/li&gt;
&lt;li&gt;Returns the generated password as a string.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;prompt.rs&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;prompt_deck()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts the user to enter a domain and its password.&lt;/li&gt;
&lt;li&gt;Reads input from the user for domain and password.&lt;/li&gt;
&lt;li&gt;Returns a tuple containing the entered domain and password.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;prompt_deck_open_sesame()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts the user to enter a domain.&lt;/li&gt;
&lt;li&gt;Reads input from the user for the domain.&lt;/li&gt;
&lt;li&gt;Returns the entered domain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;prompt_logins()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts the user to enter an admin username and password.&lt;/li&gt;
&lt;li&gt;Reads input from the user for the admin username and password.&lt;/li&gt;
&lt;li&gt;Returns a tuple containing the entered admin username and password.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;initialize_vault()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checks if the vault directory exists, and if not, creates it.&lt;/li&gt;
&lt;li&gt;Initializes the vault directory for storing encrypted data.&lt;/li&gt;
&lt;li&gt;Returns a result indicating success or failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;clip(text: &amp;amp;str)&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sets the system clipboard content to the provided text.&lt;/li&gt;
&lt;li&gt;Uses the clipboard crate to interact with the system clipboard.&lt;/li&gt;
&lt;li&gt;Pauses execution for 2 seconds to ensure the clipboard content is set before returning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  kelvin as a whole
&lt;/h3&gt;

&lt;p&gt;in &lt;code&gt;main.rs&lt;/code&gt; is where kelvin works as a whole. clap is used as the argument parser where kelvin demands commands to channel it's operations.&lt;/p&gt;

&lt;p&gt;commands include;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;generate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;create-admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deck&lt;/code&gt; whick is used to add or create a deck&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reset&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;open-sesame&lt;/code&gt; which is used to get a password to a domain in the vault&lt;/li&gt;
&lt;li&gt;&lt;code&gt;help&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  conclusion
&lt;/h3&gt;

&lt;p&gt;this project appears to be laying the groundwork for a terminal-based password manager, or "vault," with a focus on secure storage and retrieval of user and domain credentials. working features include adding a deck, retrieving passwords, generating passwords and interacting with the system clipboard.&lt;/p&gt;

&lt;p&gt;in the future, the project aims to evolve into a fully functional terminal vault with a user-friendly terminal interface. It will likely include features such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secure storage of user credentials and domain passwords.&lt;/li&gt;
&lt;li&gt;User authentication to access stored credentials.&lt;/li&gt;
&lt;li&gt;Terminal-based user interface for easy interaction.&lt;/li&gt;
&lt;li&gt;Daemonization to allow the vault to run persistently in the background.&lt;/li&gt;
&lt;li&gt;Command-line interface for starting, stopping, and managing the vault daemon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;overall, the project aims to provide a convenient and secure solution for managing passwords and sensitive data from the terminal, offering both ease of use and robust security features.&lt;/p&gt;

&lt;p&gt;contribute to kelvin on &lt;a href="//github.com/db-keli/kelvin"&gt;github&lt;/a&gt;&lt;br&gt;
text me on discord to join contributors &lt;a href="//discordapp.com/users/1083741166492733500"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>security</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
