Last active
August 29, 2015 14:01
-
-
Save ismaelhamed/c88396b6ee8c5366b5dd to your computer and use it in GitHub Desktop.
PasswordVault class implementation for Windows Phone (Silverlight)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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