Sypher Technology can help you design, develop, test, and support your custom software solution.  We love making the Web a better place with simplicity, creativity, and leading-edge technology. And if you normally work from home but could occasionally use a meeting room or desk space, check out our co-working space at sypher.co. Software Development (.com)

Recent Updates

Come by and say 'hi!'

September 19, 2011 - 12:47 PM ET - Bryan Siders

In an effort to break up my monotonous days of coding, I am opening up a few hours every week to answer questions and generally talk about anything you'd like.  Sign up for a time slot at http://link.sypher.com/bts-appt, come in to my office at Sypher, and discuss web development, running a small business, photography, or something completely different.  Just don't try to sell me something.  I've already got one.

And we're back!

June 20, 2011 - 11:07 AM ET - Bryan

There's nothing like having a server crash right before you leave for a week! One of our servers lost two hard drives (yes, the second server to do that) on June 9th, right before our Connections Online User Roundtable in Orlando.  We moved all of our customers' sites over to a new server but forgot to move our main site (www.sypher.com), so it has been down while we took a few days off in Orlando.  Everything should be back to normal now.  If you notice your hosted site is still missing, e-mail us!

Assistly Multipass SSO

March 10, 2011 - 03:09 PM ET - Bryan

Over the last 24 hours, I've been playing around with the single sign-on (SSO) capability of Assistly. They have PHP and Ruby examples of how to do it, but I needed to get it working in C#. After many rounds of failure and impossible debugging, I finally got it working! Here's the code in case someone else wants to do the same. This is the code-behind file for a blank Login.aspx file using ASP.NET 4.0.

using System;
using System.Configuration;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Web.Script.Serialization;

namespace Sypher.Multipass
{
public partial class _Login : System.Web.UI.Page
{
protected class UserData
{
public string uid;
public string expires;
public string customer_email;
public string customer_name;
public string customer_custom_siteid; // custom fields
public string customer_custom_sitename; // add your own as needed
}

protected void Page_Load(object sender, EventArgs e)
{
UserData user_data = new UserData();

// Set these values however you need
user_data.uid = "12345678-0000-0000-0000-123456789012";
user_data.expires = DateTime.UtcNow.AddMinutes(2).ToString("yyyy-MM-ddTHH:mm:sszzz"); // ISO 8601 like 2011-12-29T10:25:28-08:00
user_data.customer_email = "testing@testing.com";
user_data.customer_name = "Test User";
user_data.customer_custom_siteid = "01234567-0000-0000-0000-890123456789";
user_data.customer_custom_sitename = "Test Organization";

string assistly_url = string.Format("http://{0}.assistly.com/customer/authentication/multipass/callback?multipass={1}",
ConfigurationManager.AppSettings["assistly-site-key"], // See encryptUserData for appSettings example
encryptUserData(user_data));

Response.Redirect(assistly_url);
}

protected static string encryptUserData(UserData user_data)
{
// Encode the data into a JSON object
JavaScriptSerializer s = new JavaScriptSerializer();
string json_data = s.Serialize(user_data);

// Example of web.config configuration/appSettings section:
// <add key="assistly-site-key" value="sitename" /> <!-- from sitename.assistly.com -->
// <add key="assistly-api-key" value="0123456789abcdef0123456789abcdef" />
// <add key="assistly-iv" value="OpenSSL for Ruby" /> <!-- Static value from Assistly -->
string site_key = ConfigurationManager.AppSettings["assistly-site-key"];
string api_key = ConfigurationManager.AppSettings["assistly-api-key"];
string iv = ConfigurationManager.AppSettings["assistly-iv"];

// Using byte arrays now instead of strings
byte[] encrypted = null;
byte[] bIV = Encoding.ASCII.GetBytes(iv);
byte[] data = Encoding.ASCII.GetBytes(json_data);

// XOR the first block (16 bytes)
// once before the full XOR
// so it gets double XORed
for (var i = 0; i < 16; i++)
data[i] = (byte)(data[i] ^ bIV[i]);

// Pad using block size of 16 bytes
int pad = 16 - (data.Length % 16);
Array.Resize(ref data, data.Length + pad);
for (var i = 0; i < pad; i++)
data[data.Length - pad + i] = (byte)pad;

// Use the AesManaged object to do the encryption
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.IV = bIV;
aesAlg.KeySize = 16 * 8; // = 128-bit, originally defaulted to 256

// Create the 16-byte salted hash
SHA1 sha1 = SHA1.Create();
byte[] saltedHash = sha1.ComputeHash(Encoding.ASCII.GetBytes(api_key + site_key), 0, (api_key + site_key).Length);
Array.Resize(ref saltedHash, 16);
aesAlg.Key = saltedHash;

// Encrypt using the AES Managed object
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(data, 0, data.Length);
csEncrypt.FlushFinalBlock();
}
encrypted = msEncrypt.ToArray();
}
}

// Return the Base64-encoded encrypted data
return Convert.ToBase64String(encrypted, Base64FormattingOptions.None)
.TrimEnd("=".ToCharArray()) // Remove trailing equal (=) characters
.Replace("+", "-") // Change any plus (+) characters to dashes (-)
.Replace("/", "_"); // Change any slashes (/) characters to underscores (_)
}
}
}

Want More?

Older news articles can be found on the Sypher Technology News Blog.