Monday, September 19, 2011

Come by and say 'hi!'

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.

Monday, June 20, 2011

And we're back!

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!

Thursday, March 10, 2011

Assistly Multipass SSO

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 (_)
        }
    }
}

Wednesday, March 9, 2011

New Stuff in Our Shop!


I just finished adding a few new products to our online shop. We now offer organic t-shirts, sweatshirts, and hoodies along with our regular shirts. Check them out at cafepress.com/sypher!

Friday, February 18, 2011

Sypher Sentence

If there's one sentence that you should know about Sypher today, it's this: Sypher Technology is launching a new coworking location in east Louisville very soon, and you can sign up for our trial offer and more details at sypher.co.

Please don't judge. We can use all the media attention we can get!

Monday, February 14, 2011

Coming Soon: Coworking at Sypher Technology

We've taken another step towards opening our office to coworking! At launch, we will be making our conference room and four of our desks available to people who normally work from home or in coffee shops. We don't have 8,000 square feet, but we do have a convenient east-end location. Check out the launch page at sypher.co and sign up to be one of the first to know when we officially open!

New Site Design

Sypher.com has a new design! Come check it out and let us know what you think!

Monday, January 3, 2011

Happy 8th birthday!

Sypher Technology is now eight years old! A big "thank you" to all of our clients over the past eight years!