Skip to content

Instantly share code, notes, and snippets.

@ismaelhamed
Last active August 29, 2015 14:01
Show Gist options
  • Save ismaelhamed/c88396b6ee8c5366b5dd to your computer and use it in GitHub Desktop.
Save ismaelhamed/c88396b6ee8c5366b5dd to your computer and use it in GitHub Desktop.
PasswordVault class implementation for Windows Phone (Silverlight)
using System;
using System.Collections.Generic;
#if WINDOWS_PHONE_8
namespace Windows.Security.Credentials
#else
namespace System.Security.Credentials
#endif
{
/// <summary>
/// Represents the password credential store.
/// </summary>
public class PasswordCredential
{
/// <summary>
/// Gets or sets the resource of the credential.
/// </summary>
public string Resource { get; set; }
/// <summary>
/// Gets or sets the user name of the credential.
/// </summary>
public string UserName { get; set; }
/// <summary>
/// Gets or sets the password string of the credential.
/// </summary>
public string Password { get; set; }
/// <summary>
/// Creates and initializes a new, empty instance of the PasswordCredential object.
/// </summary>
public PasswordCredential()
{ }
/// <summary>
/// Creates and initializes a new instance of the PasswordCredential object that contains the provided credential data.
/// </summary>
/// <param name="resource">The resource for which the credentials are used.</param>
/// <param name="userName">The user name that must be present in the credentials.</param>
/// <param name="password">The password for the created credentials.</param>
public PasswordCredential(string resource, string userName, string password)
{
if (string.IsNullOrWhiteSpace(resource)) throw new ArgumentNullException("resource");
if (string.IsNullOrWhiteSpace(userName)) throw new ArgumentNullException("userName");
if (string.IsNullOrWhiteSpace(password)) throw new ArgumentNullException("password");
Resource = resource;
UserName = userName;
Password = password;
}
/// <summary>
/// Populates the password for the credential. After the operation returns successfully, you can get the password
/// from the Password property.
/// </summary>
public void RetrievePassword()
{
// Intentionally left blank. This is kept for compatibility purpouses only.
}
}
}
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Runtime.Serialization;
using System.Security.Cryptography;
#if WINDOWS_PHONE_8
namespace Windows.Security.Credentials
#else
namespace System.Security.Credentials
#endif
{
/// <summary>
/// Represents a Credential Locker of credentials. The contents of the locker are specific to the app or
/// service. Apps and services don't have access to credentials associated with other apps or services.
/// </summary>
public class PasswordVault
{
// Fields
private const string STORAGE_FOLDER = "_PasswordVault";
/// <summary>
/// Adds a credential to the Credential Locker.
/// </summary>
/// <param name="credential">The credential to be added.</param>
/// <remarks>You can only store up to ten credentials per app in the Credential Locker. If you try to store more than ten credentials, you will encounter an Exception.</remarks>
public void Add(PasswordCredential credential)
{
if (credential == null)
throw new ArgumentNullException("credential");
var path = GenerateStoredKey(credential.Resource, credential.UserName);
using (var file = IsolatedStorageFile.GetUserStoreForApplication())
using (var fileStream = new IsolatedStorageFileStream(path, FileMode.Create, FileAccess.Write, file))
{
var ms = new MemoryStream();
(new DataContractSerializer(typeof(PasswordCredential))).WriteObject(ms, credential);
var data = ProtectedData.Protect(ms.ToArray(), null);
fileStream.Write(data, 0, data.Length);
fileStream.Flush();
}
}
/// <summary>
/// Removes a credential from the Credential Locker.
/// </summary>
/// <param name="credential">The credential to be removed.</param>
public void Remove(PasswordCredential credential)
{
if (credential == null)
throw new ArgumentNullException("credential");
using (var storage = IsolatedStorageFile.GetUserStoreForApplication())
{
var path = GenerateStoredKey(credential.Resource, credential.UserName);
storage.DeleteFile(path);
}
}
/// <summary>
/// Reads a credential from the Credential Locker.
/// </summary>
/// <param name="resource">The resource for which the credential is used.</param>
/// <param name="userName">The user name that must be present in the credential.</param>
/// <returns>The returned credential that contains all the data.</returns>
public PasswordCredential Retrieve(string resource, string userName)
{
var path = GenerateStoredKey(resource, userName);
using (var file = IsolatedStorageFile.GetUserStoreForApplication())
using (var fileStream = new IsolatedStorageFileStream(path, FileMode.Open, FileAccess.Read, file))
{
var bytes = new byte[fileStream.Length];
fileStream.Read(bytes, 0, bytes.Length);
var ms = new MemoryStream(ProtectedData.Unprotect(bytes, null));
var serializer = new DataContractSerializer(typeof(PasswordCredential));
return (PasswordCredential)serializer.ReadObject(ms);
}
}
/// <summary>
/// Searches the Credential Locker for credentials matching the resource specified.
/// </summary>
/// <param name="resource">The resource to be searched for.</param>
/// <remarks>Each object returned will have the proper resource and user name, but it will not include the password.</remarks>
#if WINDOWS_PHONE_8
public IReadOnlyList<PasswordCredential> FindAllByResource(string resource)
#else
public ReadOnlyCollection<PasswordCredential> FindAllByResource(string resource)
#endif
{
return GetAllPasswordCredentials().Where(c => c.Resource.Equals(resource)).ToList().AsReadOnly();
}
/// <summary>
/// Searches the Credential Locker for credentials that match the user name specified.
/// </summary>
/// <param name="userName">The user name to be searched for.</param>
/// <remarks>Each object returned will have the proper resource and user name, but it will not include the password.</remarks>
#if WINDOWS_PHONE_8
public IReadOnlyList<PasswordCredential> FindAllByUserName(string userName)
#else
public ReadOnlyCollection<PasswordCredential> FindAllByUserName(string userName)
#endif
{
return GetAllPasswordCredentials().Where(c => c.UserName.Equals(userName)).ToList().AsReadOnly();
}
/// <summary>
/// Retrieves all of the credentials stored in the Credential Locker.
/// </summary>
#if WINDOWS_PHONE_8
public IReadOnlyList<PasswordCredential> RetrieveAll()
#else
public ReadOnlyCollection<PasswordCredential> RetrieveAll()
#endif
{
return GetAllPasswordCredentials().AsReadOnly();
}
private static string GenerateStoredKey(string resource, string userName)
{
using (var file = IsolatedStorageFile.GetUserStoreForApplication())
{
// Ensures the STORAGE_FOLDER exists
if (!file.DirectoryExists(STORAGE_FOLDER))
file.CreateDirectory(STORAGE_FOLDER);
}
return string.Format("{0}\\{1}.{2}", STORAGE_FOLDER, resource, userName);
}
private static List<PasswordCredential> GetAllPasswordCredentials()
{
var credentials = new List<PasswordCredential>();
using (var file = IsolatedStorageFile.GetUserStoreForApplication())
{
var fileNames = file.GetFileNames(string.Format("./{0}/*.*", STORAGE_FOLDER));
if (fileNames.Any())
{
foreach (var path in fileNames.Select(fileName => string.Format("{0}\\{1}", STORAGE_FOLDER, fileName)))
{
using (var fileStream = new IsolatedStorageFileStream(path, FileMode.Open, FileAccess.Read, file))
{
var bytes = new byte[fileStream.Length];
fileStream.Read(bytes, 0, bytes.Length);
var ms = new MemoryStream(ProtectedData.Unprotect(bytes, null));
var serializer = new DataContractSerializer(typeof(PasswordCredential));
var content = (PasswordCredential)serializer.ReadObject(ms);
credentials.Add(content);
}
}
}
}
return credentials;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment