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); }
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); }