• Passing Symmetric Keys with Asymmetric Encryption

    Well, i didn't get nearly as far in my book as I wanted... I did go see a good show last night at the Grand Emporium with a good friends' bands: www.fivedefy.com and http://myspace.com/thewaitinglist

    When i got home, i figured a late night of programming would be fun. Don't laugh. Using Graham Wihlidals Encryption helper class and my own additional methods for Asymmetric encryption (ganked from the public samples on MSDN) i came up with the following helper class:

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Security.Cryptography;

     

    namespace JPeckham.Samples.Encryption

    {

        public class EncryptionHelper

        {

            #region Asymmetric Methods

            public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)

            {

                    //Create a new instance of RSACryptoServiceProvider.

                    RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

     

                    //Import the RSA Key information. This only needs

                    //toinclude the public key information.

                    RSA.ImportParameters(RSAKeyInfo);

     

                    //Encrypt the passed byte array and specify OAEP padding. 

                    //OAEP padding is only available on Microsoft Windows XP or

                    //later. 

                    return RSA.Encrypt(DataToEncrypt, DoOAEPPadding);

         

            }

     

            public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)

            {

               

                    //Create a new instance of RSACryptoServiceProvider.

                    RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

     

                    //Import the RSA Key information. This needs

                    //to include the private key information.

                    RSA.ImportParameters(RSAKeyInfo);

     

                    //Decrypt the passed byte array and specify OAEP padding. 

                    //OAEP padding is only available on Microsoft Windows XP or

                    //later. 

                    return RSA.Decrypt(DataToDecrypt, DoOAEPPadding);

            }

            #endregion

     

     

                #region Symmetric

                /// <summary>

                /// Generates the initialization vector

                /// </summary>

                /// <param name="key">Your key</param>

                /// <param name="size">the size of the vector you want</param>

                /// <returns>The initialization vector as a byte array</returns>

                internal byte[] GenerateIV(byte[] key, int size)

                {

                    byte[] result = new byte[size];

     

                    SHA384Managed sha384 = new SHA384Managed();

                    sha384.ComputeHash(key);

     

                    for (int byteIndex = 0; byteIndex < result.Length; byteIndex++)

                    {

                        result[byteIndex] = sha384.Hash[byteIndex];

                    }

                    return result;

                }//end GenerateIV

     

                /// <summary>

                /// Creates a key. Info withheld for security.

                /// </summary>

                /// <param name="key">your key</param>

                /// <param name="size">the size of result key desired</param>

                /// <returns>The generated key as a byte array.</returns>

                internal byte[] GenerateKey(byte[] key, int size)

                {

                    byte[] result = new byte[size];

     

                    SHA384Managed sha384 = new SHA384Managed();

                    sha384.ComputeHash(key);

     

                    int counter = 0;

     

                    for (int byteIndex = sha384.Hash.Length - 1;

                        byteIndex >= (sha384.Hash.Length - size);

                        byteIndex--)

                    {

                        result[counter++] = sha384.Hash[byteIndex];

                    }

                    return result;

                }//end generate key

     

                /// <summary>

                /// Encrypts your data and returns a byte array of the encrypted version.

                /// </summary>

                /// <param name="cipher">Send a cipher (ie Rijndael/RC2)</param>

                /// <param name="key">Your key</param>

                /// <param name="plainText">Your data</param>

                /// <returns>Your encrypted data</returns>

                public byte[] EncryptMessage(SymmetricAlgorithm cipher, byte[] key, byte[] plainText)

                {

                    ICryptoTransform transform = cipher.CreateEncryptor(GenerateKey(key, cipher.KeySize / 8), GenerateIV(key, cipher.BlockSize / 8));

     

                    byte[] result = transform.TransformFinalBlock(plainText, 0, plainText.Length);

     

                    return result;

                }

     

                /// <summary>

                /// Decrypts your encrypted data and returns a byte array of the decrypted version.

                /// </summary>

                /// <param name="cipher">Send the same cipher used to encrypt (ie Rijndael/RC2)</param>

                /// <param name="key">Send the same key you used to encrypt.</param>

                /// <param name="cipherText">Your Encrytpted data</param>

                /// <returns>Your decrypted data</returns>

                public byte[] DecryptMessage(SymmetricAlgorithm cipher, byte[] key, byte[] cipherText)

                {

                    ICryptoTransform transform = cipher.CreateDecryptor(GenerateKey(key, cipher.KeySize / 8), GenerateIV(key, cipher.BlockSize / 8));

     

                    byte[] result = transform.TransformFinalBlock(cipherText, 0, cipherText.Length);

                    return result;

                }

                #endregion

     

     

            }

           

        }

     

    I then used the helper class to create a 'simulation' of sending an asymmetric public key across the wire to the server then the server sending back the symmetric key to the client. This allows two way communication using the much more efficient symmetric key.

     

    Here's a shot of it in action:

    Asymmetric.jpg

     

    and the source code if you want to play around with it:

     Source Code

     

    Full story

    Comments (0)

  • Verifying Data Integrity with a Hash Algorithm

    Still on chapter 12 of this beast of a book. Ironically, when women say _they_ are going to clean up your office. Try as you may to ignore the commotion going on... it means you're helping :)

     

    Anyhow here's the relavant code to my little hashing program, which is nothing more than radio buttons to choose a hashing algorithm, a text entry field, and a display of the hash result (in hex).

    hashingprogram.jpg

    Soure Code (this has the previous encryptiong project in it to i noticed)

    Full story

    Comments (0)

  • Encrypting with Symmetric Keys

    It's been a long while since i've been reading in my 70-536 training kit because i was caught up with learning wpf and wcf. I am, however, revisiting it this weekend, and hopefully going to get through the last 200-odd pages. First step along the way was working with Encryption. You remember the first time your math teacher showed you a linear algebra equation, before you even knew what variables were? That's about how I felt reading some of the descriptions in this book.

    The first thing they wanted to talk about was the SymmetricAlgorithm sub-classes, Rjindael, Des, TripleDes, AES .... There's quite a few properties on here and the descriptions in the book made me scratch my head, but I think after doing the example it started to make sense.

    from what i've read, these are the conclusions i've come to.

    Basically you Will need to create a key and IV (initialization vector) that both the cryptor and decryptor will need to have when they generate your SymmetricAlgorithm. Both of these Key and IV properties of your Algorithm class are Byte arrays. The size that they need to be (ironically) is defined in bits by the KeySize and BlockSize properties of the algorithm(respectively). So we have to take the size and divide it by 8 to figure out how big of a key we need.

    Once we have our algorithm initialized with it's key and IV, we can create an instance of an ICryptoTransform as an Encryptor or a Decryptor. (the CreateEncryptor() and CreateDecryptor() methods on your provider, respectively)

    Here's my example:(based on the 70-535 training kit example)

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Security.Cryptography;

     

    namespace EncryptingSample1

    {

        class Program

        {

            static void Main(string[] args)

            {

                string password =@"password";

                RijndaelManaged myAlg = new RijndaelManaged();

                byte[] salt = Encoding.ASCII.GetBytes("salt");

                /*salt has to be at least 8 bytes so we pad it out if it isn't... normally

                 * we should probably make an 8 byte or bigger salt...

                 * */

               

                List<byte> byteList = new List<byte>();

                byteList.AddRange(salt);

                if (byteList.Count < 8)

                {

                    for (int i = byteList.Count - 1; i < 8; i++)

                    {

                        byteList.Insert(i, new byte());

                    }

                }

                Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password,byteList.ToArray());

                //this is from the mcts training kit, not sure how likely you'd ever use the same key for the key and IV

     

                //now let's get the key bytes, the Keysize is in bits so we divide by 8

                myAlg.Key = key.GetBytes(myAlg.KeySize / 8);

                //now the initialization vector, again stored in size of bits so dividing by 8

                myAlg.IV = key.GetBytes(myAlg.BlockSize / 8);

     

                string message = "Hello, whats up?";

                byte[] messageBytes = Encoding.ASCII.GetBytes(message);

               

                ICryptoTransform cryptor = myAlg.CreateEncryptor();

                byte[] encryptedBytes = cryptor.TransformFinalBlock(messageBytes, 0, messageBytes.Length);

               

                Console.WriteLine("Encrypted: {0}",Encoding.ASCII.GetString(encryptedBytes));

                ICryptoTransform decryptor = myAlg.CreateDecryptor();

                byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);

     

                string decryptedMessage = Encoding.ASCII.GetString(decryptedBytes);

                Console.WriteLine("Decrypted: {0}",decryptedMessage);

                Console.ReadKey();

            }

        }

    }

     

    Full story

    Comments (0)

  • Masking input in wpf

    I found a great blog about masking input with wpf here

    http://karlhulme.wordpress.com/2007/02/15/masking-input-to-a-wpf-textbox/#comment-452

     

    Basically, i was using this code to create textboxes that inherit from System.Windows.Controls.TextBox for Ssn, Phone, and zipcode.

    To start out with , i just want to limit user input to numbers, so i have created a simple static method to handle that (based off Karl's work)

        internal class NumericOnlyMask

        {

            internal static bool IsTextAllowed(string text)

            {

                return Array.TrueForAll<char>(text.ToCharArray(),

                    delegate(char c) { return char.IsDigit(c); });

            }

        }

    Then my PhoneTextBox is pretty simple, it only cares about having 10characters and using the above numeric only mask.

        public class PhoneTextBox : System.Windows.Controls.TextBox

        {

            protected override void OnTextInput(System.Windows.Input.TextCompositionEventArgs e)

            {

                e.Handled = !(Srg.Applications.TempApply.Converters.NumericOnlyMask.IsTextAllowed(e.Text)

                    && (this.Text.Length + e.Text.Length - this.SelectedText.Length) <= 10);

     

                base.OnTextInput(e);

            }

     

        }

    Putting the control onto my xaml page was pretty simple, first i had to add the clr-namespace

     

    <Page

          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

          xmlns:d="http://schemas.microsoft.com/expression/blend/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"

      xmlns:controls="clr-namespace:Srg.Applications.TempApply.Controls"

          >

    Then just use it:

     

            <controls:PhoneTextBox Height="Auto" Text="{Binding HomePhone}" TextWrapping="Wrap" x:Name="txtPhoneNumber" HorizontalAlignment="Left" Margin="8,145.851,0,0" ToolTip="Your primary phone number in which you prefer to be contacted" VerticalAlignment="Top" Width="159.9" Grid.Column="2" Grid.Row="1">

            </controls:PhoneTextBox>

     

    Full story

    Comments (0)

  • May 2007 Smart Client Factory released!

    http://www.microsoft.com/downloads/details.aspx?FamilyID=2B6A10F9-8410-4F13-AD53-05A202FBDB63&displaylang=en

    I was pretty excited about using the CAB with winforms, but was a little disappointed at the convoluted install combined with entlib 3.0. Hopefully this smart client factory is a little more friendly... we shall see.

    edit: one thing i'm noticing is that i am having to install EVERYTHING P&P related to get the new GAX to install so i can install this...

    edit2: redeemed itself wholly! Although i had to uninstall entlib3.0, the gax, the gat, my webservice factory, cab, and my scsf... once reinstalled gax, gat, the mobile sql, and then ran this installer, it went off without a hitch!

    More to come...

    Full story

    Comments (0)

  • Dynamic Sorting with custom paging

    Still wasn't satisfied with the procedure because i couldn't sort... made another change. Also learned that ORDER BY @param will pass syntax checking, won't error when executed either, but doesn't work.

    ALTER PROCEDURE [dbo].[GetPersonContactByName]

          (

          @length int,

          @page int,

        @firstname nvarchar(50),

        @lastname nvarchar(50),

        @orderby nvarchar(50)

          )

         

    AS

     

    declare @totalrows float

    set @totalrows = ( SELECT  COUNT(*) from Person.Contact where LastName like (@lastname) and FirstName like (@firstname));

    declare @lastrow int

    set @lastrow = (@page - 1) * @length

    declare @lastpage int

    set @lastpage = CEILING(@totalrows / @length)

    if (@page > @lastpage) set @page = @lastpage

    if(@page < 1) set @page = 1;

          /* SET NOCOUNT ON */

    WITH Ordered AS

          (SELECT     ROW_NUMBER()

                OVER

                (    

                            ORDER BY CASE

                                              WHEN @orderby = N'EmailAddress' THEN EmailAddress

                                              WHEN @orderby = N'FirstName' THEN FirstName

                                              WHEN @orderby = N'Title' THEN Title

                                              WHEN @orderby = N'MiddleName' THEN MiddleName

                                              WHEN @orderby = N'Suffix' THEN Suffix

                                              WHEN @orderby = N'Phone' THEN Phone

                                        ELSE LastName

                                  END,

                                  CASE WHEN @orderby = N'EmailAddress' THEN LastName

                                              WHEN @orderby = N'FirstName' THEN LastName

                                              WHEN @orderby = N'Title' THEN LastName

                                              WHEN @orderby = N'MiddleName' THEN LastName

                                              WHEN @orderby = N'Suffix' THEN LastName

                                              WHEN @orderby = N'Phone' THEN LastName

                                        ELSE FirstName

                                  END

                )

                      AS

                      rownum, ContactID, NameStyle, Title, FirstName, MiddleName,

                      LastName, Suffix, EmailAddress, EmailPromotion, Phone, PasswordHash,

                      PasswordSalt, AdditionalContactInfo, rowguid, ModifiedDate

                      FROM Person.Contact

                      WHERE LastName like (@lastname) and FirstName like (@firstname)

          )

     

    SELECT  TOP (@length)

                @page as Page, @lastpage as TotalPages,  ContactID, NameStyle, Title, FirstName, MiddleName,

                LastName, Suffix, EmailAddress, EmailPromotion, Phone, PasswordHash, PasswordSalt, AdditionalContactInfo, rowguid, ModifiedDate

    FROM         Ordered

    WHERE     rownum > @lastrow

     

    return @totalrows

     

     

    image002.jpg

     

    Full story

    Comments (0)

  • Problem with .net 3.0 as a prerequisite in ClickOnce

    I ran into a new error today while trying to set .net 3.0 as a prereq for an internal app at work.

     

    Error 2 No 'PublicKey' or 'Hash' attribute specified for file 'NETFX30\Dotnetfx3.exe' in item '.NET Framework 3.0

    Error 3 No 'PublicKey' or 'Hash' attribute specified for file 'NETFX30\Dotnetfx3_x64.exe' in item '.NET Framework

    Basically, from what i read HERE: http://forums.microsoft.com/msdn/showpost.aspx?postid=797508&siteid=1

    you just need to download your redists for x86 and x64 to

    C:\program files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages\NETFX30

    you can get the redists here on this page (not the download button, but in links below it)

    http://www.microsoft.com/downloads/details.aspx?familyid=10CC340B-F857-4A14-83F5-25634C3BF043&displaylang=en

    Full story

    Comments (0)

  • I revised my custom paging stored procedure

    I really wanted to be able to send the page number i wanted and the number of records per page i wanted. so irregardless of what stage of things i was in i'd get the correct records. (and i added first name as searchable) 

    ie: if i was looking at a data grid on page 5 and i had my records per page set to 50 and i changed to 30 and then to page 3, the sproc would get me page 3 of 30 records per page. Again i believe much of this functionality like ROW_COUNT and  Top (@variable) are mssql 2005 features.

    USE [AdventureWorks]

    GO

    /****** Object:  StoredProcedure [dbo].[GetPersonContact]    Script Date: 05/10/2007 21:59:45 ******/

    SET ANSI_NULLS ON

    GO

    SET QUOTED_IDENTIFIER ON

    GO

    alter PROCEDURE [dbo].[GetPersonContactByName]

          (

          @length int,

          @page int,

        @firstname nvarchar(50),

        @lastname nvarchar(50)

          )

         

    AS

     

    declare @totalrows float

    set @totalrows = ( SELECT  COUNT(*) from Person.Contact where LastName like (@lastname) and FirstName like (@firstname));

    declare @lastrow int

    set @lastrow = (@page - 1) * @length

    declare @lastpage int

    set @lastpage = CEILING(@totalrows / @length)

    if (@page > @lastpage) set @page = @lastpage

    if(@page < 1) set @page = 1;

          /* SET NOCOUNT ON */

    WITH Ordered AS (SELECT     ROW_NUMBER() OVER (ORDER BY LastName, FirstName) AS rownum, ContactID, NameStyle, Title, FirstName, MiddleName,

    LastName, Suffix, EmailAddress, EmailPromotion, Phone, PasswordHash, PasswordSalt, AdditionalContactInfo, rowguid, ModifiedDate

    FROM         Person.Contact where LastName like (@lastname) and FirstName like (@firstname))

        SELECT  TOP (@length) @page as Page, @lastpage as TotalPages,  ContactID, NameStyle, Title, FirstName, MiddleName,

    LastName, Suffix, EmailAddress, EmailPromotion, Phone, PasswordHash, PasswordSalt, AdditionalContactInfo, rowguid, ModifiedDate

         FROM         Ordered

         WHERE     rownum > @lastrow

     

    return @totalrows

     

     

    image001.jpg

     

    Full story

    Comments (0)

  • Custom Paging Stored Procedure in Sql Server 2005

    A good friend of mine, Grundle, helped me figure out a pretty slick custom paging procedure for use in sql 2005 ( don't think variables in select top or ROW_COUNT() work in any lower versions)

     

    here's the procedure, i'll do up a bit more on the data access layer changes (they're minor, basically adding a row number field to the PersonContact object of my adventureworks service)

     

    USE [AdventureWorks]

    GO

    /****** Object:  StoredProcedure [dbo].[GetPersonContact]    Script Date: 05/10/2007 21:59:45 ******/

    SET ANSI_NULLS ON

    GO

    SET QUOTED_IDENTIFIER ON

    GO

    alter PROCEDURE [dbo].[GetPersonContactByName]

          (

          @length int,

          @lastrow int,

        @lastname nvarchar(50)

          )

         

    AS

    declare @totalrows int

    set @totalrows = ( SELECT  COUNT(*) from Person.Contact where LastName like (@lastname));

          /* SET NOCOUNT ON */

    WITH Ordered AS (SELECT     ROW_NUMBER() OVER (ORDER BY LastName, FirstName) AS rownum, ContactID, NameStyle, Title, FirstName, MiddleName,

    LastName, Suffix, EmailAddress, EmailPromotion, Phone, PasswordHash, PasswordSalt, AdditionalContactInfo, rowguid, ModifiedDate

    FROM         Person.Contact where LastName like (@lastname) )

        SELECT  TOP (@length)   *

         FROM         Ordered

         WHERE     rownum > @lastrow

     

    return @totalrows

     image001.jpg

    Full story

    Comments (0)

  • Transactions using Microsoft Distributed Transaction Coordinator in .Net

       I was working with data access this morning at work, and was dealing with rewriting some very ugly try/catch blocks to make use of System.Transactions.TransactionScope. I had read about it on the MSDN forums at some point and finally got a chance to get down to it in my Service.

     

       One thing I wasn’t sure of was whether or not I should be doing my transaction scope within my business logic or the data access layer.  I’m still a bit uncertain of exactly where those lines of demarcation should really be. I generally like my assemblies to have a simple interface or a façade pattern and factories to get instances out of it. Since the Enterprise library data access layer had the Repository and identify factories making one simple entry point into that assembly and I felt I didn’t want to confuse that implementation, I went with putting it in my business logic. Plus that’s where my try/catch blocks were at anyhow…

     

    Basically I had something that looked like this:

    try

    {

                InsertPerson(person);

    foreach(WorkHistory history in historyCollection)

    {

                Insert(history);

    }

    Foreach(Skill skill in skillCollection)

    {

                Insert(skill);

    }

                (…..)

    }

    Catch(Exception ex)

    {

               /*roll back everything*/

                Throw ex;//re throw.

    }

     

    I rewrote that to be like this:

    Using(TransactionScope scope = new TransactionScope())

    {

                InsertPerson(person);

    foreach(WorkHistory history in historyCollection)

    {

                Insert(history);

    }

    foreach(Skill skill in skillCollection)

    {

                Insert(skill);

    }

                (…..)

                scope.Complete();

    }

     

    Really simple code! Unfortunately, it didn’t work and the error message I got was pretty descriptive, but at the same time not completely useful. I should have wrote it down but it was something like “MSDTC Network transactions are disabled, enable Use Network Transactions in MSDTC configuration”.

    (Mental note to put the real error message in this text so it's web searchable)

     

    Ok, simple enough… my first question was. “Where is MSDTC configuration?”

    I don’t remember where I found it, but it’s “dcomcnfg” (which slightly annoyed me because theres bootcfg, ipconfig, pagefileconfig, msconfig… where is the naming scheme MS???)

    Basically once you’re there you expand component services and the computers folder then right click and hit “properties” on “My Computer”

    image001.jpg

    image002.jpg

    I saw the use local coordinator box, and then it asked me to choose a server. Well I didn’t want to remotely coordinate my transactions I just wanted to remotely RUN transactions on my remote sql server. So I checked use local coordinator back again. Did some googling, no luck. Opened security configuration:

     

    image003.jpg

    Now I finally got the stuff I wanted…

    So I checked network dtc access

    Checked allow remote clients

    Checked allow inbound and allow outbound

    Left mutual authentication required

    And I enabled TIP and XA transactions for the heck of it. Turn it all on, I say!

    I left the dtc logon account as it was, figured windows services are always suppose to be on local service and this is operating over the network so sure, network service sounded good.

    Running my app worked just fine after that.

     

    A good way to tell it was running was opening up the transaction statistics in dcomcnfg and watching the transactions come in and pass, then I modified the code to throw an exception in the using() block and it propertly aborted the transaction and I verified my data had been rolled back (and it joyously was).

    image004.jpg

     

     

    Full story

    Comments (0)

  1. 1
  2. 2
  3. Next page