Example #1
0
        /// <summary>
        /// Run the Inverse ThreeFish transform on a block of bytes, recovering the original length.
        /// Padding assumed to be always applied using System.Security.Cryptography.PaddingMode.ANSIX923 mode.
        /// </summary>
        /// <param name="data">The data to be untransformed.  Cannot be null or empty.  Must be length which is a multiple of 32.</param>
        /// <param name="key">The key byte array against which the data was originally transformed.  Cannot be null and must be length 32.</param>
        /// <param name="tweak">[OPTIONAL] The tweak used during the original ThreeFish transform.  Must be of length less than/equal to 16 bytes.  Default = Null (no tweak)</param>
        /// <returns>The resulting transformed data in a byte array.  The length of the resulting array will be shorter than the input array.</returns>
        static byte[] InvThreeFishBytes(int wordwidth, byte[] data, byte[] key, byte[] tweak = null)
        {
            int BYTEWIDTH = wordwidth * 8;

            if (data == null || data.Length % BYTEWIDTH != 0 || data.Length == 0)
            {
                throw new ArgumentNullException("data", "InvThreeFish256Bytes:  data MUST be at a length which is a multiple of " +
                                                BYTEWIDTH.ToString() + " and not null or empty");
            }
            if (key == null || key.Length != BYTEWIDTH)
            {
                throw new ArgumentException("key MUST be length " + BYTEWIDTH.ToString() + " and not null", "key");
            }
            if (tweak != null && tweak.Length > 16)
            {
                throw new ArgumentException("tweak MUST not exceed length 16", "tweak");
            }

            int totalBlocks = data.Length / BYTEWIDTH;

            UInt64[] localKey = new UInt64[wordwidth];
            Buffer.BlockCopy(key, 0, localKey, 0, key.Length);
            UInt64[] localTweak = new UInt64[] { 0, 0 };
            if (tweak != null)
            {
                Buffer.BlockCopy(tweak, 0, localTweak, 0, tweak.Length);
            }
            byte[]   interimResult = new byte[Buffer.ByteLength(data)];
            UInt64[] tempData      = new UInt64[wordwidth];
            for (int block = 0; block < totalBlocks; block++)
            {
                Buffer.BlockCopy(data, block * BYTEWIDTH, tempData, 0, BYTEWIDTH);
                //InvThreeFish256Internal(tempData, localKey, localTweak, ref tempData);
                ThreeFishCore.InvProcess256(tempData, localKey, localTweak, tempData);
                Buffer.BlockCopy(tempData, 0, interimResult, block * BYTEWIDTH, BYTEWIDTH);
            }
            SkeinCore.ClearQWords(ref tempData[0], tempData.Length);
            SkeinCore.ClearQWords(ref localKey[0], localKey.Length);
            SkeinCore.ClearQWords(ref localTweak[0], localTweak.Length);

            // not going to do any error checking (besides the obvious) that could give away information.
            byte finalPaddingLength = interimResult[interimResult.GetUpperBound(0)];

            byte[] finalResult = new byte[data.Length - finalPaddingLength];
            Buffer.BlockCopy(interimResult, 0, finalResult, 0, finalResult.Length);
            SkeinCore.ClearBytes(ref interimResult[0], interimResult.Length);
            //System.GC.Collect();
            return(finalResult);
        }
Example #2
0
        /// <summary>
        /// Run the ThreeFish transform on a block of bytes of arbitrarty length.
        /// Padding is always applied using System.Security.Cryptography.PaddingMode.ANSIX923 mode.
        /// </summary>
        /// <param name="data">The data to be transformed.  Cannot be null or empty.</param>
        /// <param name="key">The key byte array against which to transform the data.  Cannot be null and must be length 32.</param>
        /// <param name="tweak">[OPTIONAL] The tweak used during the ThreeFish transform.  Must be of length less than/equal to 16 bytes.  Default = Null (no tweak)</param>
        /// <returns>The resulting transformed data in a byte array.  The length of the resulting array will be longer than the input array.</returns>
        static byte[] ThreeFishBytes(int wordwidth, byte[] data, byte[] key, byte[] tweak = null)
        {
            int BYTEWIDTH = wordwidth * 8;

            if (data == null || data.Length < 1)
            {
                throw new ArgumentNullException("data", "data MUST be at least length 1 and not null");
            }
            if (key == null || key.Length != BYTEWIDTH)
            {
                throw new ArgumentException("key MUST be length " + BYTEWIDTH.ToString() + " and not null", "key");
            }
            if (tweak != null && tweak.Length > 16)
            {
                throw new ArgumentException("tweak MUST not exceed length 16", "tweak");
            }

            int  totalBlocks   = (int)Math.Ceiling((double)data.Length / BYTEWIDTH);
            byte paddingLength = (byte)(BYTEWIDTH - (data.Length % BYTEWIDTH));

            if (paddingLength == 0 || paddingLength == BYTEWIDTH)
            {
                totalBlocks++;
                paddingLength = (byte)BYTEWIDTH;
            }
            byte[] localLastData = new byte[BYTEWIDTH];
            if (totalBlocks == 1)
            {
                Buffer.BlockCopy(data, 0, localLastData, 0, data.Length);
            }
            else
            if (data.Length % BYTEWIDTH != 0)
            {
                Buffer.BlockCopy(data, (totalBlocks - 1) * BYTEWIDTH, localLastData, 0, data.Length % BYTEWIDTH);
            }
            localLastData[localLastData.GetUpperBound(0)] = paddingLength;

            UInt64[] localKey = new UInt64[wordwidth];
            Buffer.BlockCopy(key, 0, localKey, 0, key.Length);
            UInt64[] localTweak = new UInt64[] { 0, 0 };
            if (tweak != null)
            {
                Buffer.BlockCopy(tweak, 0, localTweak, 0, tweak.Length);
            }
            byte[]   finalResult = new byte[totalBlocks * BYTEWIDTH];
            UInt64[] tempData    = new UInt64[wordwidth];
            for (int block = 0; block < totalBlocks; block++)
            {
                if (block + 1 == totalBlocks)
                {
                    Buffer.BlockCopy(localLastData, 0, tempData, 0, BYTEWIDTH);
                }
                else
                {
                    Buffer.BlockCopy(data, block * BYTEWIDTH, tempData, 0, BYTEWIDTH);
                }
                Skein.ThreeFishCore.Process256(tempData, localKey, localTweak, false, tempData);
                Buffer.BlockCopy(tempData, 0, finalResult, block * BYTEWIDTH, BYTEWIDTH);
            }
            SkeinCore.ClearQWords(ref tempData[0], tempData.Length);
            SkeinCore.ClearBytes(ref localLastData[0], localLastData.Length);
            SkeinCore.ClearQWords(ref localKey[0], localKey.Length);
            SkeinCore.ClearQWords(ref localTweak[0], localTweak.Length);
            //System.GC.Collect();
            return(finalResult);
        }