/** * Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message), * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key. * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be * used as the message. * * Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes: * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33. **/ protected void UpdateIntegrityHMAC(FileInfo tmpFile, int oleStreamSize) { // as the integrity hmac needs to contain the StreamSize, // it's not possible to calculate it on-the-fly while buffering // TODO: add stream size parameter to GetDataStream() AgileEncryptionVerifier ver = builder.GetVerifier(); HashAlgorithm hashAlgo = ver.HashAlgorithm; Mac integrityMD = CryptoFunctions.GetMac(hashAlgo); integrityMD.Init(new SecretKeySpec(integritySalt, hashAlgo.jceHmacId)); byte[] buf = new byte[1024]; LittleEndian.PutLong(buf, 0, oleStreamSize); integrityMD.Update(buf, 0, LittleEndian.LONG_SIZE); FileStream fis = tmpFile.Create(); try { int readBytes; while ((readBytes = fis.Read(buf, 0, buf.Length)) > 0) { integrityMD.Update(buf, 0, readBytes); } } finally { fis.Close(); } byte[] hmacValue = integrityMD.DoFinal(); AgileEncryptionHeader header = builder.GetHeader(); int blockSize = header.BlockSize; byte[] iv = CryptoFunctions.GenerateIv(header.HashAlgorithm, header.KeySalt, AgileDecryptor.kIntegrityValueBlock, blockSize); Cipher cipher = CryptoFunctions.GetCipher(GetSecretKey(), header.CipherAlgorithm, header.ChainingMode, iv, Cipher.ENCRYPT_MODE); byte[] hmacValueFilled = GetBlock0(hmacValue, AgileDecryptor.GetNextBlockSize(hmacValue.Length, blockSize)); byte[] encryptedHmacValue = cipher.DoFinal(hmacValueFilled); header.SetEncryptedHmacValue(encryptedHmacValue); }
public virtual void Update(byte[] foo, int s, int l) { mac.Update(foo, s, l); }