Skip to content

CS410-510Rust-Password-Manager-CLI/CS510-password-manager-

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Password Manager CLI

Authors: Tareq Jallad, Haohan Jiang

Guide

Description

This project uses Rust to implement a command line password manager. This CLI application allows the user to create, delete, list, and modify secret entries and secret stores, all through the command line. For user security, all input passwords and usernames are encrypted by a randomly generated RSA Private key.

Usage quick guide

Build

This project can be built with cargo build

and the binary will be located at target/debug/password_manager

Binary can also be downloaded from the release page

Terminology

Secret Entry - A secret entry is a named username and password pair

Secret Store - A list of secret entries

Create a new store

    password_manager -s <NAME> --op init

Add a new secret to the store

    password_manager -s <NAME> --op create

List all secrets in a store

    password_manager -s <NAME> --op list

Delete a secrets store

    password_manager -s <NAME> --op delete-store

Delete a secret entry in a secrets store

    password_manager -s <NAME> --op delete-entry -e <ENTRY_NAME>

Modify an existing entry in a secrets store

    password_manager -s <NAME> --op modify -e <ENTRY_NAME>

Get an existing entry in a secrets store

    password_manager -s <NAME> --op get -e <ENTRY_NAME>

Usage Example

As a new user, I want to create new store with the name foobar. I have a new World of Warcraft subscription and want to put my username and password into this password manager to store.

I would first need to create the store with:

    password_manager -s foobar --op init

Then, to add the user information into the password manager, I would need to run:

    password_manager -s foobar --op create

This will prompt the user to enter in a name for the secret entry and the username and password to store. In this example, my store name will be called wow.

When I want to login to World of Warcraft, I can get the secrets with:

  password_manager -s foobar --op get -e wow

Detailed guide

Directory structure

At the root project level, src contains the source code for the project. resources contains a test file for unit testing.

Top level main.rs

The entry point for the application. Houses command line argument logic and calls different modules based on user input.

Operations /operations/

  • create.rs
  • delete.rs
  • get.rs
  • init.rs
  • list.rs
  • modify.rs

Operations directory contains the logic required for each specific operation.

Generic /generic/

  • common.rs
  • encryption.rs
  • errors.rs

Generics directory contains functionality that is used across the app.

Models /models/

-data_model.rs

Models directory contains the data model that is serialized and deserialized through JSON.

Mocks /mocks/

-test_mocks.rs

Mocks directory contains a function that is used to override an external function during unit testing. test_mocks.rs contains a function that is only called during unit tests which raises a compiler warning during build. So, we decided to suppress the warning with the macro #![allow(dead_code)]

Home directory for application

The base directory for this application is: HOME/.passmanager.

All secrets stores are located at: HOME/.passmanager/.stores/<STORE_NAME>.json

All secret keys are located at: HOME/.passmanager/.keys/<KEY_NAME>.pem

How secrets are encrypted

Secrets and secret stores are encrypted in two different ways. First, we encrypt the store name and the entry name. Second, we also encrypt the username and password for each entry using a RSA private key generated specifically for that secret entry.

Hashed Values

Secret store names and RSA private keys are stored under hashed value.

RSA Encrypted Values

Usernames and passwords are encrypted by a RSA public key generated from it's RSA private key. The key is stored under the hashed entry name so that the private key can be retrieved to decrypt the username and password.

Error handling

Application errors can handled under /generics/errors. External library errors are caught and re-raised as an internal error up to the top level caller.

Testing

We preformed integration testing by hand. We did not have a library crate and could not figure out a way to import the project into an integration test module to live in the /tests/ directory. We hand tested each functionality to ensure functionality.

Unit tests exist within files when appropriate for the function. Certain modules were mocked by selective imports with #[cfg(test)] and #[cfg(not(test))] macros.

Post-project retrospective

We thought that most things in the project went pretty well. Nothing was too troublesome. The problem arose during unit testing of the library functions that the different components used. When researching how to unit test functions, most rust mocking frameworks limited you to mocking only traits and the project was not built with traits in mind.

Perhaps this was an un-rust like way to code the project.

We are satisfied with the results as we believe that we created a great simple app that can be useful to the right target audience. We went into this project with the goal of creating a usable product and to that end I think we succeeded.

License

This project is available under the MIT license