예제 #1
0
파일: CBCEncrypt.cs 프로젝트: ForNeVeR/pnet
        // Transform an input block into an output block.
        public static int TransformBlock(CryptoAPITransform transform,
                                         byte[] inputBuffer, int inputOffset,
                                         int inputCount, byte[] outputBuffer,
                                         int outputOffset)
        {
            int blockSize = transform.blockSize;

            byte[] iv     = transform.iv;
            IntPtr state  = transform.state;
            int    offset = outputOffset;
            int    index;

            // Process all of the blocks in the input.
            while (inputCount >= blockSize)
            {
                // XOR the plaintext with the IV.
                for (index = blockSize - 1; index >= 0; --index)
                {
                    iv[index] ^= inputBuffer[inputOffset + index];
                }

                // Encrypt the IV to get the ciphertext and the next IV.
                CryptoMethods.Encrypt(state, iv, 0, iv, 0);
                Array.Copy(iv, 0, outputBuffer, offset, blockSize);

                // Advance to the next block.
                inputOffset += blockSize;
                inputCount  -= blockSize;
                offset      += blockSize;
            }

            // Finished.
            return(offset - outputOffset);
        }
예제 #2
0
파일: CTSEncrypt.cs 프로젝트: ForNeVeR/pnet
        // Transform an input block into an output block.
        public static int TransformBlock(CryptoAPITransform transform,
                                         byte[] inputBuffer, int inputOffset,
                                         int inputCount, byte[] outputBuffer,
                                         int outputOffset)
        {
            int blockSize = transform.blockSize;

            byte[] iv     = transform.iv;
            IntPtr state  = transform.state;
            int    offset = outputOffset;

            byte[] tempBuffer = transform.tempBuffer;
            int    tempSize   = transform.tempSize;
            int    index;

            // Process all of the data in the input.  We need to keep
            // the last two blocks for the finalization process.
            while (inputCount >= blockSize)
            {
                // If the temporary buffer is full, then flush a block
                // through the cipher in CBC mode.
                if (tempSize > blockSize)
                {
                    // XOR the plaintext with the IV.
                    for (index = blockSize - 1; index >= 0; --index)
                    {
                        iv[index] ^= tempBuffer[index];
                    }

                    // Encrypt the IV to get the ciphertext and the next IV.
                    CryptoMethods.Encrypt(state, iv, 0, iv, 0);
                    Array.Copy(iv, 0, outputBuffer, offset, blockSize);

                    // Advance to the next output block.
                    offset += blockSize;

                    // Shift the second block down to the first position.
                    Array.Copy(tempBuffer, blockSize,
                               tempBuffer, 0, blockSize);
                    tempSize -= blockSize;
                }

                // Copy the next block into the temporary buffer.
                Array.Copy(inputBuffer, inputOffset,
                           tempBuffer, tempSize, blockSize);
                inputOffset += blockSize;
                inputCount  -= blockSize;
                tempSize    += blockSize;
            }
            transform.tempSize = tempSize;

            // Finished.
            return(offset - outputOffset);
        }
예제 #3
0
파일: OFBEncrypt.cs 프로젝트: ForNeVeR/pnet
        // Transform an input block into an output block.
        public static int TransformBlock(CryptoAPITransform transform,
                                         byte[] inputBuffer, int inputOffset,
                                         int inputCount, byte[] outputBuffer,
                                         int outputOffset)
        {
            int blockSize    = transform.blockSize;
            int feedbackSize = transform.feedbackBlockSize;

            byte[] iv     = transform.iv;
            IntPtr state  = transform.state;
            int    offset = outputOffset;

            byte[] tempBuffer = transform.tempBuffer;
            int    tempSize   = transform.tempSize;

            // Process all of the bytes in the input.
            while (inputCount > 0)
            {
                // Encrypt the queue if we need more keystream data.
                if (tempSize >= feedbackSize)
                {
                    CryptoMethods.Encrypt(state, tempBuffer,
                                          feedbackSize, tempBuffer, 0);
                    tempSize = 0;
                }

                // XOR the plaintext byte with the next keystream byte.
                outputBuffer[offset++] =
                    (byte)(tempBuffer[tempSize] ^
                           inputBuffer[inputOffset++]);
                --inputCount;

                // Feed the keystream byte back into the queue.
                tempBuffer[tempSize + blockSize] = tempBuffer[tempSize];
                ++tempSize;
            }
            transform.tempSize = tempSize;

            // Finished.
            return(offset - outputOffset);
        }
예제 #4
0
        // Transform an input block into an output block.
        public static int TransformBlock(CryptoAPITransform transform,
                                         byte[] inputBuffer, int inputOffset,
                                         int inputCount, byte[] outputBuffer,
                                         int outputOffset)
        {
            int    blockSize = transform.blockSize;
            IntPtr state     = transform.state;
            int    offset    = outputOffset;

            // Process all of the blocks in the input.
            while (inputCount >= blockSize)
            {
                CryptoMethods.Encrypt(state, inputBuffer, inputOffset,
                                      outputBuffer, offset);
                inputOffset += blockSize;
                inputCount  -= blockSize;
                offset      += blockSize;
            }

            // Finished.
            return(offset - outputOffset);
        }
예제 #5
0
        // Transform the final input block.
        public static byte[] TransformFinalBlock(CryptoAPITransform transform,
                                                 byte[] inputBuffer,
                                                 int inputOffset,
                                                 int inputCount)
        {
            int blockSize = transform.blockSize;

            byte[] iv    = transform.iv;
            IntPtr state = transform.state;
            int    offset;

            byte[] tempBuffer = transform.tempBuffer;
            byte[] outputBuffer;
            int    tempSize;
            int    index;

            // Allocate the output buffer.
            outputBuffer = new byte [inputCount + transform.tempSize];

            // Process as many full blocks as possible.
            index  = inputCount - (inputCount % blockSize);
            offset = TransformBlock(transform, inputBuffer,
                                    inputOffset, index,
                                    outputBuffer, 0);
            inputOffset += index;
            inputCount  -= index;

            // Flush the first block if we need the extra space.
            tempSize = transform.tempSize;
            if (tempSize > blockSize && inputCount > 0)
            {
                // Decrypt the ciphertext block and XOR with the IV.
                CryptoMethods.Decrypt(state, tempBuffer, blockSize,
                                      tempBuffer, 0);
                for (index = blockSize - 1; index >= 0; --index)
                {
                    tempBuffer[index] ^= iv[index];
                }

                // Copy the original ciphertext to the IV.
                Array.Copy(tempBuffer, blockSize, iv, 0, blockSize);

                // Copy the plaintext into place.
                Array.Copy(tempBuffer, 0, outputBuffer,
                           offset, blockSize);

                // Advance to the next output block.
                offset += blockSize;

                // Shift the second block down to the first position.
                Array.Copy(tempBuffer, blockSize * 2,
                           tempBuffer, blockSize, blockSize);
                tempSize -= blockSize;
            }

            // Copy the remainder of the data into the temporary buffer.
            Array.Copy(inputBuffer, inputOffset,
                       tempBuffer, tempSize + blockSize, inputCount);
            tempSize += inputCount;

            // "Applied Cryptography" describes Cipher Text Stealing
            // as taking two blocks to generate the short end-point.
            // If we less than one block, then use CFB instead.
            if (tempSize < blockSize)
            {
                // Decrypt the single block in CFB mode.
                CryptoMethods.Encrypt(transform.state2, iv, 0, iv, 0);
                for (index = 0; index < tempSize; ++index)
                {
                    outputBuffer[offset + index] =
                        (byte)(iv[index] ^ tempBuffer[index + blockSize]);
                }
            }
            else
            {
                // Decrypt the second last ciphertext block.
                CryptoMethods.Decrypt(state, tempBuffer, blockSize,
                                      tempBuffer, blockSize);

                // Rebuild the ciphertext for the last block.
                for (index = inputCount; index < blockSize; ++index)
                {
                    tempBuffer[blockSize * 2 + index] =
                        tempBuffer[blockSize + index];
                }

                // Get the last plaintext block from the second
                // last ciphertext block.
                for (index = inputCount - 1; index >= 0; --index)
                {
                    outputBuffer[offset + blockSize + index] =
                        (byte)(tempBuffer[blockSize + index] ^
                               tempBuffer[blockSize * 2 + index]);
                }

                // Decrypt the last ciphertext block that we rebuilt.
                CryptoMethods.Decrypt(state, tempBuffer, blockSize * 2,
                                      tempBuffer, 0);

                // XOR the block with the IV to get the second
                // last plaintext block.
                for (index = blockSize - 1; index >= 0; --index)
                {
                    outputBuffer[offset + index] =
                        (byte)(iv[index] ^ tempBuffer[index]);
                }
            }

            // Finished.
            return(outputBuffer);
        }
예제 #6
0
        // Transform the final input block.
        public static byte[] TransformFinalBlock(CryptoAPITransform transform,
                                                 byte[] inputBuffer,
                                                 int inputOffset,
                                                 int inputCount)
        {
            int    blockSize = transform.blockSize;
            IntPtr state = transform.state;
            int    offset = 0;
            int    size, index, pad;

            byte[] outputBuffer;

            // Allocate space for the final block.
            if (transform.padding == PaddingMode.PKCS7)
            {
                size = inputCount + blockSize - (inputCount % blockSize);
            }
            else
            {
                size = inputCount;
                if ((size % blockSize) != 0)
                {
                    size += blockSize - (inputCount % blockSize);
                }
            }
            outputBuffer = new byte [size];

            // Process full blocks in the input.
            while (inputCount >= blockSize)
            {
                CryptoMethods.Encrypt(state, inputBuffer, inputOffset,
                                      outputBuffer, offset);
                inputOffset += blockSize;
                inputCount  -= blockSize;
                offset      += blockSize;
            }

            // Format and encrypt the final partial block.
            if (transform.padding == PaddingMode.PKCS7)
            {
                // Pad the block according to PKCS #7.
                for (index = 0; index < inputCount; ++index)
                {
                    outputBuffer[offset + index] =
                        inputBuffer[inputOffset + index];
                }
                pad = blockSize - (inputCount % blockSize);
                while (index < blockSize)
                {
                    outputBuffer[offset + index] = (byte)pad;
                    ++index;
                }

                // Encrypt the block.
                CryptoMethods.Encrypt(state, outputBuffer,
                                      offset + index - blockSize,
                                      outputBuffer,
                                      offset + index - blockSize);
            }
            else if (inputCount > 0)
            {
                // Pad the block with zero bytes.
                for (index = 0; index < inputCount; ++index)
                {
                    outputBuffer[offset + index] =
                        inputBuffer[inputOffset + index];
                }
                while (index < blockSize)
                {
                    outputBuffer[offset + index] = (byte)0x00;
                    ++index;
                }

                // Encrypt the block.
                CryptoMethods.Encrypt(state, outputBuffer,
                                      offset + index - blockSize,
                                      outputBuffer,
                                      offset + index - blockSize);
            }

            // Finished.
            return(outputBuffer);
        }
예제 #7
0
파일: CBCEncrypt.cs 프로젝트: ForNeVeR/pnet
        // Transform the final input block.
        public static byte[] TransformFinalBlock(CryptoAPITransform transform,
                                                 byte[] inputBuffer,
                                                 int inputOffset,
                                                 int inputCount)
        {
            int blockSize = transform.blockSize;

            byte[] iv = transform.iv;
            IntPtr state = transform.state;
            int    offset = 0;
            int    size, pad, index;

            byte[] outputBuffer;

            // Allocate space for the final block.
            if (transform.padding == PaddingMode.PKCS7)
            {
                size = inputCount + blockSize - (inputCount % blockSize);
            }
            else
            {
                size = inputCount;
                if ((size % blockSize) != 0)
                {
                    size += blockSize - (inputCount % blockSize);
                }
            }
            outputBuffer = new byte [size];

            // Process full blocks in the input.
            while (inputCount >= blockSize)
            {
                // XOR the plaintext with the IV.
                for (index = blockSize - 1; index >= 0; --index)
                {
                    iv[index] ^= inputBuffer[inputOffset + index];
                }

                // Encrypt the IV to get the ciphertext and the next IV.
                CryptoMethods.Encrypt(state, iv, 0, iv, 0);
                Array.Copy(iv, 0, outputBuffer, offset, blockSize);

                // Advance to the next block.
                inputOffset += blockSize;
                inputCount  -= blockSize;
                offset      += blockSize;
            }

            // Format and encrypt the final partial block.
            if (transform.padding == PaddingMode.PKCS7)
            {
                // Pad the block according to PKCS #7 and XOR with the IV.
                for (index = 0; index < inputCount; ++index)
                {
                    iv[index] ^= inputBuffer[inputOffset + index];
                }
                pad = blockSize - (inputCount % blockSize);
                while (index < blockSize)
                {
                    iv[index] ^= (byte)pad;
                    ++index;
                }

                // Encrypt the IV to get the ciphertext and the next IV.
                CryptoMethods.Encrypt(state, iv, 0, iv, 0);
                Array.Copy(iv, 0, outputBuffer, offset, blockSize);
            }
            else if (inputCount > 0)
            {
                // Pad the block with zero bytes and XOR with the IV.
                // The zero padding is implicit.
                for (index = 0; index < inputCount; ++index)
                {
                    iv[index] ^= inputBuffer[inputOffset + index];
                }

                // Encrypt the IV to get the ciphertext and the next IV.
                CryptoMethods.Encrypt(state, iv, 0, iv, 0);
                Array.Copy(iv, 0, outputBuffer, offset, blockSize);
            }

            // Finished.
            return(outputBuffer);
        }