Пример #1
0
        public GenericGcmModeCryptoTransform(IGenericBlockCipher cipher, bool forEncryption,
                                             byte[] iv, byte[] additional, int tagLength)
        {
            if (cipher == null)
            {
                throw new ArgumentNullException("cipher");
            }
            if (cipher.BlockSize != BLOCK_SIZE)
            {
                throw new ArgumentException("cipher");
            }
            if (iv == null)
            {
                throw new ArgumentNullException("iv");
            }
            if (additional == null)
            {
                throw new ArgumentNullException("additional");
            }
            if (tagLength < 12 || tagLength > 16)
            {
                throw new ArgumentException("tagLength " + tagLength);
            }

            _cipher     = cipher;
            _encrypting = forEncryption;
            _tagLength  = tagLength;
            _cipher.Encrypt(_H, 0, _H, 0);

            if (iv.Length == 12)
            {
                Buffer.BlockCopy(iv, 0, _J0, 0, 12);
                _J0[_J0.Length - 1] = 0x01;
            }
            else
            {
                // Construct last hashed block from IV length
                byte[] lengthBytes = BitConverter.GetBytes((UInt64)iv.Length * 8);
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(lengthBytes);
                }
                byte[] lastBlock = new byte[BLOCK_SIZE];
                Buffer.BlockCopy(lengthBytes, 0, lastBlock, 8, 8);

                // Hash the IV and length block to get J0
                GHASH(iv, _J0);
                GHASH(_J0, lastBlock, 0, lastBlock.Length, _J0);
            }

            GHASH(additional, _originalS);
            _additionalLength = (UInt64)additional.Length;

            Reset();
        }
		public GenericGcmModeCryptoTransform(IGenericBlockCipher cipher, bool forEncryption,
		                                     byte[] iv, byte[] additional, int tagLength)
		{
			if (cipher == null)
				throw new ArgumentNullException("cipher");
			if (cipher.BlockSize != BLOCK_SIZE)
				throw new ArgumentException("cipher");
			if (iv == null)
				throw new ArgumentNullException("iv");
			if (additional == null)
				throw new ArgumentNullException("additional");
			if (tagLength < 12 || tagLength > 16)
				throw new ArgumentException("tagLength " + tagLength);
			
			_cipher = cipher;
			_encrypting = forEncryption;
			_tagLength = tagLength;
			_cipher.Encrypt(_H, 0, _H, 0);
			
			if (iv.Length == 12) {
				Buffer.BlockCopy(iv, 0, _J0, 0, 12);
				_J0[_J0.Length-1] = 0x01;
			} else {
				// Construct last hashed block from IV length
				byte[] lengthBytes = BitConverter.GetBytes((UInt64)iv.Length*8);
				if (BitConverter.IsLittleEndian) {
					Array.Reverse(lengthBytes);
				}
				byte[] lastBlock = new byte[BLOCK_SIZE];
				Buffer.BlockCopy(lengthBytes, 0, lastBlock, 8, 8);
				
				// Hash the IV and length block to get J0
				GHASH(iv, _J0);
				GHASH(_J0, lastBlock, 0, lastBlock.Length, _J0);
			}
			
			GHASH(additional, _originalS);
			_additionalLength = (UInt64)additional.Length;
			
			Reset();
		}
Пример #3
0
        // Takes only full data blocks for input, especially need to make sure that
        // the authentication tag is not given to TransformBlock while decrypting GCM
        // data, it needs to be handled in TransformFinalBlock instead
        public int TransformBlock(byte[] inputBuffer,
                                  int inputOffset,
                                  int inputCount,
                                  byte[] outputBuffer,
                                  int outputOffset)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (inputBuffer == null)
            {
                throw new ArgumentNullException("inputBuffer");
            }
            if (inputOffset < 0 || inputOffset > inputBuffer.Length)
            {
                throw new ArgumentOutOfRangeException("inputOffset");
            }
            if (inputCount < 0 || inputCount > inputBuffer.Length - inputOffset)
            {
                throw new ArgumentOutOfRangeException("inputCount");
            }
            if (inputCount % BLOCK_SIZE != 0)
            {
                throw new CryptographicException("inputCount");
            }
            if (outputBuffer == null)
            {
                throw new ArgumentNullException("outputBuffer");
            }
            if (outputOffset < 0 || outputOffset > outputBuffer.Length - inputCount)
            {
                throw new ArgumentOutOfRangeException("outputOffset");
            }

            for (int i = 0; i < inputCount; i += BLOCK_SIZE)
            {
                // Encrypt the next counter to the output buffer
                _cipher.Encrypt(_counter, 0, outputBuffer, outputOffset + i);
                Increment(32, _counter);

                // XOR input with the counter and place it in output
                for (int j = 0; j < BLOCK_SIZE; j++)
                {
                    outputBuffer[outputOffset + i + j] ^= inputBuffer[inputOffset + i + j];
                }

                if (_encrypting)
                {
                    GHASH(_currentS, outputBuffer, outputOffset + i, BLOCK_SIZE, _currentS);
                }
                else
                {
                    GHASH(_currentS, inputBuffer, inputOffset + i, BLOCK_SIZE, _currentS);
                }
                _ciphertextLength += BLOCK_SIZE;
            }

            return(inputCount);
        }
        public int TransformBlock(byte[] inputBuffer,
                                  int inputOffset,
                                  int inputCount,
                                  byte[] outputBuffer,
                                  int outputOffset)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (inputBuffer == null)
            {
                throw new ArgumentNullException("inputBuffer");
            }
            if (inputOffset < 0 || inputOffset >= inputBuffer.Length)
            {
                throw new ArgumentOutOfRangeException("inputOffset");
            }
            if (inputCount < 0 || inputCount > inputBuffer.Length - inputOffset)
            {
                throw new ArgumentOutOfRangeException("inputCount");
            }
            if (inputCount % _blockSize != 0)
            {
                throw new CryptographicException("inputCount");
            }
            if (outputBuffer == null)
            {
                throw new ArgumentNullException("outputBuffer");
            }
            if (outputOffset < 0 || outputOffset > outputBuffer.Length - inputCount)
            {
                throw new ArgumentOutOfRangeException("outputOffset");
            }

            // This is manual CBC handling
            for (int i = 0; i < inputCount; i += _blockSize)
            {
                if (_encrypting)
                {
                    for (int j = 0; j < _blockSize; j++)
                    {
                        _currentIV[j] ^= inputBuffer[inputOffset + i + j];
                    }
                    _cipher.Encrypt(_currentIV, 0, outputBuffer, outputOffset + i);
                    Array.Copy(outputBuffer, outputOffset + i, _currentIV, 0, _blockSize);
                }
                else
                {
                    _cipher.Decrypt(inputBuffer, inputOffset + i, outputBuffer, outputOffset + i);
                    for (int j = 0; j < _blockSize; j++)
                    {
                        outputBuffer[outputOffset + i + j] ^= _currentIV[j];
                    }
                    Array.Copy(inputBuffer, inputOffset + i, _currentIV, 0, _blockSize);
                }
            }

            return(inputCount);
        }