Esempio n. 1
0
        protected override byte[] DecryptBlock(
            byte[] inEnc,
            int inOff,
            int inLen)
        {
            // Ensure that the length of the input is greater than the MAC in bytes
            if (inLen < (V.Length + Mac.GetMacSize()))
            {
                throw new InvalidCipherTextException("Length of input must be greater than the MAC and V combined");
            }

            // note order is important: set up keys, do simple encryption, check mac, do final encryption.
            if (Cipher == null)
            {
                // Streaming mode.
                throw new ArgumentNullException(string.Format("{0}", "Cipher Cannot be Null in This Mode."));
            }
            // Block cipher mode.

            SetupBlockCipherAndMacKeyBytes(out byte[] k1, out byte[] k2);

            ICipherParameters cp = new KeyParameter(k1);

            // If IV provide use it to initialize the cipher
            if (Iv != null)
            {
                cp = new ParametersWithIV(cp, Iv);
            }

            Cipher.Init(false, cp);

            // Verify the MAC.
            byte[] t1 = new byte[Mac.GetMacSize()];
            Array.Copy(inEnc, V.Length, t1, 0, t1.Length);

            byte[] t2 = new byte[t1.Length];
            Mac.Init(new KeyParameter(k2));
            Mac.BlockUpdate(inEnc, inOff + V.Length + t2.Length, inLen - V.Length - t2.Length);

            Mac.DoFinal(t2, 0);

            if (!Arrays.ConstantTimeAreEqual(t1, t2))
            {
                throw new InvalidCipherTextException("invalid MAC");
            }

            return(Cipher.DoFinal(inEnc, inOff + V.Length + Mac.GetMacSize(),
                                  inLen - V.Length - t2.Length));
        }
        private byte[] DecryptBlock(
            byte[] inEnc,
            int inOff,
            int inLen,
            byte[] macData)
        {
            byte[] M = null, K = null, K1 = null, K2 = null;
            int    len;

            // Ensure that the length of the input is greater than the MAC in bytes
            if (inLen <= _iesParameters.MacKeySize / 8)
            {
                throw new InvalidCipherTextException("Length of input must be greater than the MAC");
            }

            if (Cipher == null)
            {
                // Streaming mode.
                K1 = new byte[inLen - V.Length - Mac.GetMacSize()];
                K2 = new byte[_iesParameters.MacKeySize / 8];
                K  = new byte[K1.Length + K2.Length];

                _kdf.GenerateBytes(K, 0, K.Length);

//            if (V.Length != 0)
//            {
//                Array.Copy(K, 0, K2, 0, K2.Length);
//                Array.Copy(K, K2.Length, K1, 0, K1.Length);
//            }
//            else
                {
                    Array.Copy(K, 0, K1, 0, K1.Length);
                    Array.Copy(K, K1.Length, K2, 0, K2.Length);
                }

                M = new byte[K1.Length];

                for (int i = 0; i != K1.Length; i++)
                {
                    M[i] = (byte)(inEnc[inOff + V.Length + i] ^ K1[i]);
                }

                len = K1.Length;
            }
            else
            {
                // Block cipher mode.
                K1 = new byte[((IesWithCipherParameters)_iesParameters).CipherKeySize / 8];
                K2 = new byte[_iesParameters.MacKeySize / 8];
                K  = new byte[K1.Length + K2.Length];

                _kdf.GenerateBytes(K, 0, K.Length);
                Array.Copy(K, 0, K1, 0, K1.Length);
                Array.Copy(K, K1.Length, K2, 0, K2.Length);

                // If IV provide use it to initialize the cipher
                if (_iv != null)
                {
                    Cipher.Init(false, new ParametersWithIV(new KeyParameter(K1), _iv));
                }
                else
                {
                    Cipher.Init(false, new KeyParameter(K1));
                }

                M    = new byte[Cipher.GetOutputSize(inLen - V.Length - Mac.GetMacSize())];
                len  = Cipher.ProcessBytes(inEnc, inOff + V.Length, inLen - V.Length - Mac.GetMacSize(), M, 0);
                len += Cipher.DoFinal(M, len);
            }


            // Convert the length of the encoding vector into a byte array.
            byte[] p2 = _iesParameters.GetEncodingV();

            // Verify the MAC.
            int end = inOff + inLen;

            byte[] t1 = Arrays.CopyOfRange(inEnc, end - Mac.GetMacSize(), end);

            byte[] t2 = new byte[t1.Length];
            byte[] k2A;
            if (HashK2)
            {
                k2A = new byte[_hash.GetDigestSize()];
                _hash.Reset();
                _hash.BlockUpdate(K2, 0, K2.Length);
                _hash.DoFinal(k2A, 0);
            }
            else
            {
                k2A = K2;
            }
            Mac.Init(new KeyParameter(k2A));
            Mac.BlockUpdate(_iv, 0, _iv.Length);
            Mac.BlockUpdate(inEnc, inOff + V.Length, inLen - V.Length - t2.Length);

            if (p2 != null)
            {
                Mac.BlockUpdate(p2, 0, p2.Length);
            }

            if (V.Length != 0 && p2 != null)
            {
//            byte[] L2 = new byte[4];
//            Pack.intToBigEndian(P2.Length * 8, L2, 0);
                byte[] L2 = (p2.Length * 8).ToBigEndianByteArray();
                Debug.Assert(L2.Length == 4, "expected to be 4 bytes long");

                Mac.BlockUpdate(L2, 0, L2.Length);
            }

            if (macData != null)
            {
                Mac.BlockUpdate(macData, 0, macData.Length);
            }

            Mac.DoFinal(t2, 0);

            if (!Arrays.ConstantTimeAreEqual(t1, t2))
            {
                throw new InvalidCipherTextException("Invalid MAC.");
            }

            // Output the message.
            return(Arrays.CopyOfRange(M, 0, len));
        }
        private byte[] EncryptBlock(
            byte[] input,
            int inOff,
            int inLen,
            byte[] macData)
        {
            byte[] c, k, k1, k2;
            int    len;

            if (Cipher == null)
            {
                // Streaming mode.
                k1 = new byte[inLen];
                k2 = new byte[_iesParameters.MacKeySize / 8];
                k  = new byte[k1.Length + k2.Length];

                _kdf.GenerateBytes(k, 0, k.Length);

//            if (V.Length != 0)
//            {
//                Array.Copy(K, 0, K2, 0, K2.Length);
//                Array.Copy(K, K2.Length, K1, 0, K1.Length);
//            }
//            else
                {
                    Array.Copy(k, 0, k1, 0, k1.Length);
                    Array.Copy(k, inLen, k2, 0, k2.Length);
                }

                c = new byte[inLen];

                for (int i = 0; i != inLen; i++)
                {
                    c[i] = (byte)(input[inOff + i] ^ k1[i]);
                }
                len = inLen;
            }
            else
            {
                // Block cipher mode.
                k1 = new byte[((IesWithCipherParameters)_iesParameters).CipherKeySize / 8];
                k2 = new byte[_iesParameters.MacKeySize / 8];
                k  = new byte[k1.Length + k2.Length];

                _kdf.GenerateBytes(k, 0, k.Length);
                Array.Copy(k, 0, k1, 0, k1.Length);
                Array.Copy(k, k1.Length, k2, 0, k2.Length);

                // If iv provided use it to initialise the cipher
                if (_iv != null)
                {
                    Cipher.Init(true, new ParametersWithIV(new KeyParameter(k1), _iv));
                }
                else
                {
                    Cipher.Init(true, new KeyParameter(k1));
                }

                c    = new byte[Cipher.GetOutputSize(inLen)];
                len  = Cipher.ProcessBytes(input, inOff, inLen, c, 0);
                len += Cipher.DoFinal(c, len);
            }


            // Convert the length of the encoding vector into a byte array.
            byte[] p2 = _iesParameters.GetEncodingV();

            // Apply the MAC.
            byte[] T = new byte[Mac.GetMacSize()];

            byte[] k2A;
            if (HashK2)
            {
                k2A = new byte[_hash.GetDigestSize()];
                _hash.Reset();
                _hash.BlockUpdate(k2, 0, k2.Length);
                _hash.DoFinal(k2A, 0);
            }
            else
            {
                k2A = k2;
            }
            Mac.Init(new KeyParameter(k2A));
            Mac.BlockUpdate(_iv, 0, _iv.Length);
            Mac.BlockUpdate(c, 0, c.Length);
            if (p2 != null)
            {
                Mac.BlockUpdate(p2, 0, p2.Length);
            }
            if (V.Length != 0 && p2 != null)
            {
//            byte[] L2 = new byte[4];
//            Pack.intToBigEndian(P2.Length * 8, L2, 0);
                byte[] L2 = (p2.Length * 8).ToBigEndianByteArray();
                Debug.Assert(L2.Length == 4, "expected to be 4 bytes long");
                Mac.BlockUpdate(L2, 0, L2.Length);
            }

            if (macData != null)
            {
                Mac.BlockUpdate(macData, 0, macData.Length);
            }

            Mac.DoFinal(T, 0);

            // Output the triple (V,C,T).
            byte[] Output = new byte[V.Length + len + T.Length];
            Array.Copy(V, 0, Output, 0, V.Length);
            Array.Copy(c, 0, Output, V.Length, len);
            Array.Copy(T, 0, Output, V.Length + len, T.Length);
            return(Output);
        }
Esempio n. 4
0
        protected override unsafe byte[] EncryptBlock(
            byte[] @in,
            int inOff,
            int inLen)
        {
            if (Cipher == null)
            {
                // Streaming mode.
                throw new ArgumentNullException(string.Format("{0}", "Cipher Cannot be Null in This Mode."));
            }
            // Block cipher mode.

            SetupBlockCipherAndMacKeyBytes(out byte[] k1, out byte[] k2);


            // If iv provided use it to initialise the cipher
            if (Iv != null)
            {
                Cipher.Init(true, new ParametersWithIV(new KeyParameter(k1), Iv));
            }
            else
            {
                Cipher.Init(true, new KeyParameter(k1));
            }

            byte[] c = Cipher.DoFinal(@in, inOff, inLen);


            // Apply the MAC.
            byte[] T = new byte[Mac.GetMacSize()];

            Mac.Init(new KeyParameter(k2));
            Mac.BlockUpdate(c, 0, c.Length);
            Mac.DoFinal(T, 0);

            int cipherBlockSize      = Cipher.GetBlockSize();
            int messageToEncryptSize = inLen - inOff;

            int messageToEncryptPadSize = (messageToEncryptSize % cipherBlockSize) == 0
                ? 0
                : cipherBlockSize -
                                          (messageToEncryptSize % cipherBlockSize);


            // Output the quadruple (SECURE_HEAD_DETAILS,V,T,C).
            // SECURE_HEAD_DETAILS :=
            // [0] := Convert Byte(Length(V)) to a ByteArray,
            // [1] := Convert Byte(Length(T)) to a ByteArray,
            // [2] and [3] := Convert UInt16(MessageToEncryptSize) to a ByteArray,
            // [4] and [5] := Convert UInt16(MessageToEncryptSize + MessageToEncryptPadSize) to a ByteArray,
            // V := Ephemeral Public Key
            // T := Authentication Message (MAC)
            // C := Encrypted Payload

            byte[] output = new byte[SecureHeadSize + V.Length + T.Length + c.Length];


            fixed(byte *ptrByteOutput = output)
            {
                ushort *ptrUShortOutput = (ushort *)ptrByteOutput;

                *ptrByteOutput = (byte)(V.Length);
                *(ptrByteOutput + 1)   = (byte)(T.Length);
                *(ptrUShortOutput + 1) = (ushort)(messageToEncryptSize);
                *(ptrUShortOutput + 2) = (ushort)(messageToEncryptSize + messageToEncryptPadSize);
            }

            Array.Copy(V, 0, output, SecureHeadSize, V.Length);
            Array.Copy(T, 0, output, SecureHeadSize + V.Length, T.Length);
            Array.Copy(c, 0, output, SecureHeadSize + V.Length + T.Length, c.Length);
            return(output);
        }