Click here to Skip to main content
15,032,967 members
Articles / Mobile Apps / Xamarin
Article
Posted 22 May 2017

Stats

12.9K views
290 downloads
12 bookmarked

Creating an offline mobile password manager using Xamarin Forms

Rate me:
Please Sign up or sign in to vote.
4.39/5 (9 votes)
17 Jun 2017CPOL9 min read
or converting an old phone into a password manager

Introduction

I’ve been writing iOS apps in Xamarin for a while and have been wanting to try Xamarin forms, there’s a problem I needed to solve and here is my first journey onto the Xamarin Forms land

Problem

I have been creating a few new accounts on the Internet that require the use of complex password recently and my existing sets of passwords are no longer/or only barely enough to pass the password strength checkers.

I needed a solution that could 

a. allow me to come up with more secure password and
b. be easy enough to remember

My solution

Over the years, the idea of remembering one password and use a set of algorithm to generate passwords for all sites has been catching on. After seeing this article I really wanted to adopt the same system, the problem is I always forget the search term.

One day, I came across this article on Charles Leifer blog, we had the same problem and created a web service for his password generator.

I on the other hand, wish my algorithm to stay offline and in my control, and since I have a spare smartphone that I do not use, I decided to convert it into my special Password Generator which I will now have to carry around with me.

Background

Technology used: Xamarin Forms, .NetStandard

Techniques used: Dependency Injection (there are a lot of great articles on code project on this topic)

The Basic Idea

The basic idea here is to convert a common, easy to remember master string (ie. 'Password') into a more complex, harder to crack, impossible to remember password for specific websites/service.

The way to achieve it is simple,

  1. Take the master string as key,
  2. Add on to a specific salt, my convention here is to use the website name
  3. Encrypt it using SHA
  4. Since SHA returns all letters and numbers, I create a map of all available characters and translate using that map
  5. Verify the generated password meets the requirement
  6. Add additional character to fulfill the requirements

Code Structure

My project has the following components:

Core - Handles the password generation and storage of password scheme, it's a .NetStandard library

Core.Test - Unit tests to make sure the generated passwords are consistent and meet the requirement

PasswordManager (Portable) - Created for Xamarin Forms, I shall refer to this as "The PCL" from now on. It is the backbone of this Xamarin forms application. Both the Android and iOS project launches the App from the PCL

PasswordManager.Android - Android project

PasswordManager.iOS - iOS project, ignore since I don't have iOS developer subscription

Converting the PCL to .NetStandard library

I've been using Xamarin to write iOS in the past bit, it caught me by surprise that I could not add any framework dll reference to the Xamarin Forms portable library, which is a problem because it means I could not use System.Security.Cryptography namespace.

What's the solution? Apparently it is to use a .NetStandard library instead. That is why the Core project needs to be a .NetStandard library.

However, I could not simply add the .NetStandard library back to the PCL, it would not compile.

So we would have to convert the PCL to target .NetStandard

Which involved three extra steps as outlined here

  1. Use Nuget to remove Xamarin Forms from the solution
  2. Right click on the PCL and open the property window
  3. Target .NetStandard

    Image 1

  4. Select at least .Net Standard 1.3 to include Cryptography namespace
  5. A project.json file should have been generated, click on it to edit
  6. Under Frameworks, add the following line under frameworks
XML
"imports": "portable-net45+win8+wpa81+wp8"

So this is about what the file would look something like

{

  "supports": {},
  "dependencies": {
    "Microsoft.NETCore.Portable.Compatibility": "1.0.1",
    "NETStandard.Library": "1.6.0",
  },
  "frameworks": {
    "netstandard1.4": {
      "imports": "portable-net45+win8+wpa81+wp8"
    }
  }

7. Using Nuget, add Xamarin Forms back to the solution

Using the code

Password generation

Password generation is simple, simply create an instance of the PasswordGenerator like so

C#
var passwordGen = new PasswordGenerator(PasswordRequirements.SymbolRequired | PasswordRequirements.UpperCaseRequired | PasswordRequirements.NumberRequired);           

and create the password by calling

C#
var password = passwordGen.GeneratePassword(sourceKey, salt, minimumLength);

Once again, here are the steps the PasswordGenerator takes

  1. Take the master string,
  2. Add on to a specific salt, my convention here is to use the website name
  3. Encrypt it using SHA
  4. Since SHA returns all letters and numbers, but I needed to use symbols, I create a map of all available characters and translate using that map
  5. Verify the generated password meets the requirement
  6. Add additional character to meet unmet requirements

Storing Password scheme

Why?

Now we have a password generated with different options, how do we remember what the options were? One option is to try all combinations. Try doing that ten times. Remember, the goal here is to create a password that is hard for computer to guess.

So we need to store the password scheme somehow, one benefit of storing a password per website/service is now we can write additional logic to check if two services are really the same.

For example, we don’t want to generate a different password for “Facebook” vs “facebook”

Ok, how?

For storage, I have chosen Sql-net-PCL.

To persist our password scheme, we need to create the database first

C#
SqliteStorage.InitializeStorage(IoCProviders.GetProvider<IKnowStorage>().GetStoragePath(), databaseName);

Then we can store the appropriate settings using

C#
ServicePersistor.Persist(serviceName, requirement);

So now we can generate password, store the options used to generate the password and we can retrieve password scheme using

C#
var serviceEntity = ServicePersistor.GetPasswordSettings(serviceName);

Simple, huh?

What's this IoCProviders?

First challenge anyone would enounter is where would the database live?

iOS and Android have different file systems, I needed each platform to give me a location that I can use to store the db file.

Since the Core project is made to work with both iOS and Android, it doesn’t know about these platform-specific intricacies. How could I possibly know where to store/look for these files?

This is where dependency injection comes in, and there are tons of articles about this on Codeproject.

The idea is I can define a interface in Core that allows specific implementation detail to be created within the platform specific projects and I can use these implementation to perform platform-specific tasks.

The IoCProvidershere is a simple dictionary to keep track of these implementations.

Here’s the IoCProviders(Naming is hard) in all of its glory

C#
public class IoCProviders

{
    private static IDictionary<Type, object> _providers;
    private static IDictionary<Type, object> Providers
    {
        get
        {
            if (_providers == null)
            {
                _providers = new Dictionary<Type, object>();
            }
            return _providers;
        }

    }


    public static void Register<TType>(object provider)
    {
        Providers[typeof(TType)] = provider;
    }


    public static TType GetProvider<TType>()
    {
        return (TType)Providers[typeof(TType)];
    }
}

What about Mobile?

I have my way to generate password, and I can store it, how do I actually use it?

Well, I did promise an app didn't I.

I have chosen to use Xamarin Forms for curiosity’s sake. 

To be honest, I wasn't quite looking forward to write user interface in XAML but I changed my mind after this experience.

What the app looks like

The App workflow looks like this

  1. Enter master password
  2. Enter service name
  3. Make sure settings are correct
  4. Get password
  5. Store the given password scheme for the service
  6. Copies password to clipboard (Platform specific)
  7. Notifies user password has been copied (Platform specific)
  8. User may choose to generate a new password with different settings

(If they chose the same setting, the same password will be generated again)

And here’s what the App looks like

Image 2

What about Code?

What I have discovered is that XAML provides a real nice way of visualizing the control flow, once I have a ViewModel created

C#
ViewModel = new PasswordRequestViewModel();

Controlling UI behaviour becomes a matter of setting using properties of PasswordRequestViewModel().

Here is an annotated view of what each of these variables control

Image 3

  • MasterPassword – Text value of the master password textbox
  • ShowOrHideMasterPasswordTitle – Title of the Show button
  • ServiceName – Text value of the Service name textbox
  • IncludeNumbersString – Title of the Include Numbers button
  • IncludeSymbolsString – Title of the Include Symbols button
  • IncludeUppercaseString – Title of the Include Upper case button
  • PasswordVisible – Controls whether the password field will show
  • CreateNewPassword – Controls visibility of the generate new password button which isn’t shown on the diagram

Here’s an example implementation for one of the properties

C#
private string showOrHideMasterPasswordTitle;
public string ShowOrHideMasterPasswordTitle
{
    get
    {
        return showOrHideMasterPasswordTitle;
    }
    set
    {
        if (showOrHideMasterPasswordTitle != value)
        {
            showOrHideMasterPasswordTitle = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ShowOrHideMasterPasswordTitle"));
        }
    }
}

And here’s what it looks like in XAML

<Button Text="{Binding ShowOrHideMasterPasswordTitle}" BackgroundColor="Transparent" Clicked="ShowHide_Clicked" />

I won’t get in details about the Clicked event, but that’s basically where visibilities and title of buttons get changed.

Come on, no checkbox?

One annoyance here is Xamarin Forms does not come with built in Checkbox/Radio boxes, I guess it's because iOS doesn't really like them. I took the lazy way out and used buttons instead.

For example, this is what the Include Uppercase button looks like

I would update the text in click events by changing the value of IncludeUppercase

C#
private bool includeUppercase;
public bool IncludeUppercase
{
    get { return includeUppercase; }
    set
    {
        if (includeUppercase != value)
        {
            includeUppercase = value;
            IncludeUppercaseString = value ? "[x] Include Upper case" : "[ ] Include Upper case";
        }
    }
}

IncludeUppercase here is the real deal, whereas IncludeUppercaseString is only used for UI

Platform specific implementation

I talked about platform specific implementations, it really is simple things that cannot be written in common code.

For example, iOS and Android has their own APIs for handling clipboard, Android has Toast, iOS has local notification.

Which is why I have the following interfaces

C#
public interface ICopyToClipboard
{
    void CopyToClipboard(string value);
}

public interface IKnowStorage
{
    string GetStoragePath();
}

public interface IProvideNotifications
{
    void Notify(string title, string message);
}

And the implementations are simple. For Android

C#
public class ClipboardProvider : ICopyToClipboard
{
    Context FormContext;
    public ClipboardProvider(Context context)
    {
        FormContext = context;
    }

    public void CopyToClipboard(string value)
    {
        ClipboardManager clipboard = (ClipboardManager)FormContext.GetSystemService(Context.ClipboardService);
        ClipData clip = ClipData.NewPlainText("Clipboard", value);
        clipboard.PrimaryClip = clip;
    }
}

public class NotificationProvider : IProvideNotifications
{
    Context FormContext;
    public NotificationProvider(Context context)
    {
        FormContext = context;
    }


    public void Notify(string title, string message)
    {
        Toast.MakeText(FormContext, message, ToastLength.Short).Show();
    }
}

public class StorageProvider : IKnowStorage
{
    public string GetStoragePath()
    {
        return Environment.GetFolderPath(Environment.SpecialFolder.Personal);
    }
 }

These implementations are passed into the App and the app registers them with the IoCProviders

C#
public App
    (
        IKnowStorage storageProvider,
        ICopyToClipboard clipboardProvider,
        IProvideNotifications notificationProvider
    )
{
    InitializeComponent();

    IoCProviders.Register<IKnowStorage>(storageProvider);
    IoCProviders.Register<ICopyToClipboard>(clipboardProvider);
    IoCProviders.Register<IProvideNotifications>(notificationProvider);
    MainPage = new PasswordManager.MainPage();
}

One Last Thing

When your app is in the background, and a random person walks by, you probably do NOT wish that person to open the app and see your master password. That is why I clear password and Master password whenever the app is resumed.

Xamarin Forms provides a nice method to override

protected override void OnResume()
{
    // Handle when your app resumes
    ((PasswordManager.MainPage)MainPage).ClearEnteredData();
}

So to recap, this is how the Mobile app code works

  1. Create instances platform specific Storage, Notification and Clipboard Providers
  2. Register the providers with IoCProviders
  3. Start App with MainPage
  4. XAML file describes the layout of the app, it defines the labels, and texts and events
  5. The control properties such as Title, Visibility are bound to variables in PasswordRequestViewModel
  6. Click events toggles the title, visibility and text values of the controls

Points of Interest

For me the real big question is, is this safe? How can I make it really safe?

I wanted to create a different database (with encrypted filename of course) for one master password, but I felt that’s leaving at least a bit of a trace for a potential attacker and I didn’t like that.

So now I use the same db for everything, leaving absolutely no trace, if I needed a different password, I could always append something to the master.

On the other hand, they also would have to figure out my username, maybe this is a motivation to not use the same set of usernames on every website?

This is really an experimental project for me, I expect everyone would have a slightly different idea of a secure password (for example, maybe the length of the password could be adjustable) Feel free to tweak to fit your liking, in fact I encourage it. I'm a big fan of tweaking to a specific need as opposed to creating a generic solution that tries to make everyone happy.

Acknowledgement

I'd like to thank everyone who write these amazing articles on Code Project. I learned so much from these articles early in my career, and this time I finally found something worth writing about.

Special acknowledgement to Charles Leifer, I really enjoyed your Saturday project ideas and it really encouraged me to try something like this myself

Source Code

Download PasswordManager.zip

History

June 17, 2017 - Cleaned up the language

May 22, 2017 – Initial Draft

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Lurker1315
Canada Canada
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --