iOS: Store passwords in the keychain using MonoTouch

Tuesday, 1 February 2011 05:20 by Krumelur

EDIT: I have just updated this post a bit. Storing a password now supports data encryption. This means you can specify when the stored password is accessible (e.g. only if the device is unlocked).

After searching the web a lot I could not find a resource providing examples on how to store a password securely on an iOS device. StackOverflow.com pointed me to the iOS's KeyChain and I found this example which does the magic using ObjectiveC: https://github.com/ldandersen/scifihifi-iphone/

As I want to give the community something back I offer a MonoTouch implementation inspired by to code referenced above for download here.

My code contains three static methods:

/// <summary>
/// Deletes a username/password record.
/// </summary>
/// <param name="sUsername">the username to query. May not be NULL.</param>
/// <param name="sService">the service description to query. May not be NULL.</param>
/// <returns>SecStatusCode.Success if everything went fine, otherwise some other status</returns>
public static SecStatusCode DeletePasswordForUsername ( string sUsername, string sService )

/// <summary>
/// Sets a password for a specific username.
/// </summary>
/// <param name="sUsername">the username to add the password for. May not be NULL.</param>
/// <param name="sPassword">the password to associate with the record. May not be NULL.</param>
/// <param name="sService">the service description to use. May not be NULL.</param>
/// <param name="eSecAccessible">defines how the keychain record is protected</param>
/// <returns>SecStatusCode.Success if everything went fine, otherwise some other status</returns>
public static SecStatusCode SetPasswordForUsername ( string sUsername, string sPassword, string sService, SecAccessible eSecAccessible )

/// <summary>
/// Gets a password for a specific username.
/// </summary>
/// <param name="sUsername">the username to query. May not be NULL.</param>
/// <param name="sService">the service description to use. May not be NULL.</param>
/// <returns>
/// The password or NULL if no matching record was found.
/// </returns>
public static string GetPasswordForUsername ( string sUsername, string sService )

Find the MonoTouch C# file attached for download with this post.

2011_2_KeyChain_MT.cs (4,69 kb)

iOS: UIAlertView with a UITextField - a MonoTouch implementation

Friday, 28 January 2011 16:26 by Krumelur

I have searched the web for a way to subclass UIAlertView and add a UITextField to it, like Apple does it in the iTUnes store.

Apple however uses a private call which we "normal" developers are not allowed to use. So I came up with some code. It is not perfect yet, especially when rotating the device, but feel free to improve it.

I tested it on iPad using iOS 4.2 only.

 

using System;
using MonoTouch.UIKit;
using System.Drawing;
using System.Collections.Generic;
using MonoTouch.Foundation;
using MonoTouch.CoreGraphics;

namespace iBrainloop.Views
{
    public class InputAlertView : UIAlertView
    {
        public InputAlertView ( string sTitle, string sMessage, string sCancel, params string[] aOtherButtons ) : base( sTitle, sMessage, null, sCancel, aOtherButtons )
        {
            this.KeyboardType = UIKeyboardType.ASCIICapable;
            this.KeyboardReturnType = UIReturnKeyType.Done;
            this.InputFieldTextAlignment = UITextAlignment.Center;
            this.InputFieldCapitalization = UITextAutocapitalizationType.AllCharacters;
            this.InputFieldAutocorrection = UITextAutocorrectionType.No;
            this.InputFieldIsSecure = false;
            this.InputFieldPlaceholder = "";
            this.Presented += delegate
            {
                this.oTxtInput.BecomeFirstResponder (  );
                this.Transform = CGAffineTransform.MakeTranslation ( 0, -100 );
            };
        }
       
        private UITextField oTxtInput;
       
        // If the view has been dismissed, this property contains the entered text.
        public string EnteredText
        {
            get
            {
                return this.oTxtInput.Text;
            }
        }
       
        public UIKeyboardType KeyboardType
        {
            get;
            set;
        }
       
        public UIReturnKeyType KeyboardReturnType
        {
            get;
            set;
        }
       
        public UITextAlignment InputFieldTextAlignment
        {
            get;
            set;
        }
       
        public UITextAutocapitalizationType InputFieldCapitalization
        {
            get;
            set;
        }
       
        public UITextAutocorrectionType InputFieldAutocorrection
        {
            get;
            set;
        }
       
        public bool InputFieldIsSecure
        {
            get;
            set;
        }
       
        public string InputFieldPlaceholder
        {
            get;
            set;
        }
       
        public override void Show ()
        {
            base.Show ( );
           
            this.oTxtInput = new UITextField ( new System.Drawing.RectangleF ( 12f, 75f, 260f, 25f ) );
            this.oTxtInput.BackgroundColor = UIColor.White;
            this.oTxtInput.UserInteractionEnabled = true;
            this.oTxtInput.KeyboardType = this.KeyboardType;
            this.oTxtInput.ReturnKeyType = this.KeyboardReturnType;
            this.oTxtInput.TextAlignment = this.InputFieldTextAlignment;
            this.oTxtInput.AutocapitalizationType = this.InputFieldCapitalization;
            this.oTxtInput.AutocorrectionType = this.InputFieldAutocorrection;
            this.oTxtInput.SecureTextEntry = this.InputFieldIsSecure;
            this.oTxtInput.Placeholder = this.InputFieldPlaceholder;
           
            this.Frame = new RectangleF ( this.Frame.X, this.Frame.Y, this.Frame.Size.Width, this.Frame.Size.Height + this.oTxtInput.Bounds.Height + 20 );
           
            this.fInitialHeight = this.Bounds.Height;
            // Increase height of the alert view to have space for the textfield.
            this.AddSubview ( this.oTxtInput );
            this.Superview.SetNeedsLayout (  );
            this.SetNeedsLayout (  );
            this.fInitialY = this.Frame.Y;
        }
        private float fInitialHeight;
        private float fInitialY;
       
        public override void LayoutSubviews ()
        {
            base.LayoutSubviews (  );
            this.Frame = new RectangleF ( this.Frame.X, this.fInitialY - 80, this.Frame.Size.Width, this.fInitialHeight );
            foreach ( UIView oSubView in this.Subviews )
            {
                if ( oSubView is UITextField )
                {
                    oSubView.Frame = new RectangleF ( oSubView.Frame.X, this.Bounds.Height - oSubView.Frame.Height - 65, oSubView.Frame.Width, oSubView.Frame.Height );
                    continue;
                }
                if ( oSubView is UIControl )
                {
                    oSubView.Frame = new RectangleF ( oSubView.Frame.X, this.Bounds.Height - oSubView.Frame.Height - 20, oSubView.Frame.Width, oSubView.Frame.Height );
                }
            }
        }
    }
}