private static async Task DecryptContentAsync(Stream source, Stream destination, int recordSize, byte[] contentEncryptionKeyInfoParameterHash, byte[] nonceInfoParameterHash) { using (Aes128GcmCipher aes128GcmCipher = new Aes128GcmCipher(contentEncryptionKeyInfoParameterHash, nonceInfoParameterHash)) { int maxPlainTextLength = recordSize - RECORD_ENCRYPTION_OVERHEAD_SIZE - RECORD_DELIMITER_SIZE; byte[] plainTextBuffer = _arrayPool.Rent(maxPlainTextLength + RECORD_DELIMITER_SIZE); byte[] cipherTextBuffer = _arrayPool.Rent(recordSize); try { int recordDelimiterIndex = 0; ulong recordSequenceNumber = 0; do { int cipherTextLength = await source.ReadAsync(cipherTextBuffer, 0, recordSize).ConfigureAwait(false); if (cipherTextLength == 0) { ThrowInvalidOrderOrMissingRecordException(); } int plainTextLength = aes128GcmCipher.Decrypt(cipherTextBuffer, cipherTextLength, plainTextBuffer, recordSequenceNumber++); recordDelimiterIndex = GetRecordDelimiterIndex(plainTextBuffer, plainTextLength, maxPlainTextLength); if ((plainTextBuffer[recordDelimiterIndex] == LAST_RECORD_DELIMITER) && (source.ReadByte() != -1)) { ThrowInvalidOrderOrMissingRecordException(); } await destination.WriteAsync(plainTextBuffer, 0, recordDelimiterIndex).ConfigureAwait(false); }while (plainTextBuffer[recordDelimiterIndex] != LAST_RECORD_DELIMITER); } finally { _arrayPool.Return(plainTextBuffer, true); _arrayPool.Return(cipherTextBuffer, true); } } }
private static async Task EncryptContentAsync(Stream source, Stream destination, int recordSize, byte[] contentEncryptionKeyInfoParameterHash, byte[] nonceInfoParameterHash) { using (Aes128GcmCipher aes128GcmCipher = new Aes128GcmCipher(contentEncryptionKeyInfoParameterHash, nonceInfoParameterHash)) { int maxPlainTextLength = recordSize - RECORD_ENCRYPTION_OVERHEAD_SIZE - RECORD_DELIMITER_SIZE; byte[] plainTextBuffer = _arrayPool.Rent(maxPlainTextLength + RECORD_DELIMITER_SIZE); byte[] cipherTextBuffer = _arrayPool.Rent(recordSize); try { int plainTextLength; int?peekedPlainTextByte = null; ulong recordSequenceNumber = 0; do { plainTextLength = await GetPlainTextAsync(source, plainTextBuffer, maxPlainTextLength, (byte?)peekedPlainTextByte).ConfigureAwait(false); if (plainTextBuffer[plainTextLength - 1] != LAST_RECORD_DELIMITER) { peekedPlainTextByte = source.ReadByte(); if (peekedPlainTextByte == -1) { plainTextBuffer[plainTextLength - 1] = LAST_RECORD_DELIMITER; } } int cipherTextLength = aes128GcmCipher.Encrypt(plainTextBuffer, plainTextLength, cipherTextBuffer, recordSequenceNumber++); await destination.WriteAsync(cipherTextBuffer, 0, cipherTextLength).ConfigureAwait(false); }while (plainTextBuffer[plainTextLength - 1] != LAST_RECORD_DELIMITER); } finally { _arrayPool.Return(plainTextBuffer, true); _arrayPool.Return(cipherTextBuffer, true); } } }