/// <summary>
        /// Constructs a new FeatureLicenseData object from the given product key, using the passed Machine identifier to
        /// decrypt it's contents.
        /// </summary>
        /// <param name="fromproductcode"></param>
        /// <param name="IDString"></param>
        public ProductKey(String fromproductcode, String IDString)
            : this()
        {
            //remove any hyphens/dashes, first.
            MachineID       = IDString;
            fromproductcode = fromproductcode.Replace("-", "");
            //convert the string to a byte array via zBase32:

            ZBase32Encoder zb = new ZBase32Encoder();

            byte[] acquiredcode = zb.Decode(fromproductcode);


            //byte[] acquiredcode = Enumerable.Range(0, fromproductcode.Length)
            //         .Where(x => x % 2 == 0)
            //         .Select(x => Convert.ToByte(fromproductcode.Substring(x, 2), 16))
            //         .ToArray();


            //now, we need to decrypt it...
            byte[] decrypted = Decrypt(acquiredcode, MachineID);

            //armed with the decrypted data, toss it into a memory stream
            MemoryStream ms = new MemoryStream(decrypted);

            ms.Seek(0, SeekOrigin.Begin);

            //now, invoke FromStream...
            FromStream(ms);
        }
        /// <summary>
        /// Creates a ProductCode, or Key, from the data stored in this class and the MachineID.
        /// </summary>
        /// <returns></returns>
        public String GetProductCode()
        {
            MemoryStream mstream = new MemoryStream();

            //first, write our data out to a memorystream.
            DataToStream(mstream);


            //seek to the start, read as a string.
            mstream.Seek(0, SeekOrigin.Begin);
            //read it back, as a array of bytes.
            Byte[] readdata = new byte[mstream.Length];
            mstream.Read(readdata, 0, readdata.Length);

            //Encrypt the array of bytes using the MachineID. this is set in the constructor to getLocalMachineID(), but can of course
            //be changed by the caller before calling GetProductCode (for example, for generating the key elsewhere)
            Byte[] encrypted = Encrypt(readdata, MachineID);

            //now we need a readable form, so encode using zBase32, which has
            //good results for a human readable key.
            ZBase32Encoder zb = new ZBase32Encoder();


            return(zb.Encode(encrypted).ToUpper());
        }