Creating an offline mobile password manager using Xamarin Forms

0
47

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 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.

While the complex ones I simple cannot remember. What really pushed me over the edge was failing to log on to facebook after exhausting all possible combinations of the passwords I like to use.

In the past I have also tried tricks like replacing “a”s with “@”s, 3s with “E”s, it hasn’t been easy for me.

So I need a solution and hopefully the same solution works for you.

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,

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

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 – Testing to make sure password requirements are met

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 is a .NetStandard.

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

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 line

“imports”: “portable-net45+win8+wpa81+wp8”

So this is about what the file would look 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. Install Xamarin Forms back to the solution

Using the code

Password generation

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

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

and create the password by calling

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? Sure we can try all combinations. Try doing that ten times. Remember, none of the password generated make any sense.

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 , it’s a pity I couldn’t get Realm to work, this is what I really wanted to try.

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

SqliteStorage.InitializeStorage(IoCProviders.GetProvider().GetStoragePath(), databaseName);

Then we can store the appropriate settings using

ServicePersistor.Persist(serviceName, requirement);

So now we can generate password, store password schem, we can also retrieve password scheme using

var serviceEntity = ServicePersistor.GetPasswordSettings(serviceName);

Simple, huh?

What’s this IoCProviders?

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.

Unfortunately, the Core project is common, 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 common interface in Core, and each platform will return their own implementation, and I can use these implementation to do 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

public class IoCProviders { private static IDictionary _providers; private static IDictionary Providers { get { if (_providers == null) { _providers = new Dictionary(); } return _providers; } } public static void Register(object provider) { Providers[typeof(TType)] = provider; } public static TType GetProvider() { return (TType)Providers[typeof(TType)]; }
}

What about Mobile?

Everything I have covered so far is logic, I still don’t have an app to use, don’t you worry, it’s coming.

So I have chosen to use Xamarin Forms, just for curiosity’s sake. To be honest I wasn’t entirely looking forward to the XAML experience and was hoping to develop using a code based approach.

But since XAML is what the default VS template creates, I guess I will learn it.

What it 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

What about Code?

What I have discovered is that XAML provides a real nice way of visualizing the control flow, once I have my binding context set

ViewModel = new PasswordRequestViewModel();

It becomes a matter of setting values inside of PasswordRequestViewModel().

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

  • 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

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

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

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

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

public App ( IKnowStorage storageProvider, ICopyToClipboard clipboardProvider, IProvideNotifications notificationProvider )
{ InitializeComponent(); IoCProviders.Register(storageProvider); IoCProviders.Register(clipboardProvider); IoCProviders.Register(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()
{ ((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

It still annoys me that iOS has no checkbox, at home I could get around it by using a button, no such luck at work 🙂

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

Originally 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 need 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?

Of course, I wish to move this code on either an Arduino or Raspberry Pi device to really brick it.

Acknowledgement

Ha, long time lurker, first time author. 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

May 22, 2017 – Initial Draft

LEAVE A REPLY