diff --git a/Directory.Build.props b/Directory.Build.props
index 0a0d59a5b4..a24f0ab2ac 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -7,7 +7,7 @@
2.0.1
2.0.1
preview
- 1.0.0-preview04
+ 1.0.0-preview05
1.1.0-preview3
10.0
$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md b/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md
index a17680a9f8..58fcf1d790 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md
@@ -3,6 +3,11 @@ Preview features are treated as a separate branch and will not be included in th
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+### [1.0.0-preview05](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption.Custom/1.0.0-preview05) - 2023-04-27
+
+#### Fixes
+- [#3809](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3809) Adds api FetchDataEncryptionKeyWithoutRawKeyAsync and FetchDataEncryptionKey to get DEK without and with raw key respectively.
+
### [1.0.0-preview04](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption.Custom/1.0.0-preview04) - 2022-08-16
#### Fixes
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosDataEncryptionKeyProvider.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosDataEncryptionKeyProvider.cs
index 1c8cffce8e..773845aa9e 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosDataEncryptionKeyProvider.cs
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosDataEncryptionKeyProvider.cs
@@ -166,11 +166,25 @@ public async Task InitializeAsync(
this.container = containerResponse.Container;
}
+ ///
+ public override async Task FetchDataEncryptionKeyWithoutRawKeyAsync(
+ string id,
+ string encryptionAlgorithm,
+ CancellationToken cancellationToken)
+ {
+ return await this.FetchDekAsync(id, encryptionAlgorithm, cancellationToken);
+ }
+
///
public override async Task FetchDataEncryptionKeyAsync(
string id,
string encryptionAlgorithm,
CancellationToken cancellationToken)
+ {
+ return await this.FetchDekAsync(id, encryptionAlgorithm, cancellationToken, true);
+ }
+
+ private async Task FetchDekAsync(string id, string encryptionAlgorithm, CancellationToken cancellationToken, bool withRawKey = false)
{
DataEncryptionKeyProperties dataEncryptionKeyProperties = await this.dataEncryptionKeyContainerCore.FetchDataEncryptionKeyPropertiesAsync(
id,
@@ -200,7 +214,8 @@ public override async Task FetchDataEncryptionKeyAsync(
InMemoryRawDek inMemoryRawDek = await this.dataEncryptionKeyContainerCore.FetchUnwrappedAsync(
dataEncryptionKeyProperties,
diagnosticsContext: CosmosDiagnosticsContext.Create(null),
- cancellationToken: cancellationToken);
+ cancellationToken: cancellationToken,
+ withRawKey);
return inMemoryRawDek.DataEncryptionKey;
}
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosEncryptor.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosEncryptor.cs
index 3a325e77b2..462bd56a1f 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosEncryptor.cs
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosEncryptor.cs
@@ -35,14 +35,14 @@ public override async Task DecryptAsync(
string encryptionAlgorithm,
CancellationToken cancellationToken = default)
{
- DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync(
+ DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync(
dataEncryptionKeyId,
encryptionAlgorithm,
cancellationToken);
if (dek == null)
{
- throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync)}.");
+ throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync)}.");
}
return dek.DecryptData(cipherText);
@@ -55,14 +55,14 @@ public override async Task EncryptAsync(
string encryptionAlgorithm,
CancellationToken cancellationToken = default)
{
- DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync(
+ DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync(
dataEncryptionKeyId,
encryptionAlgorithm,
cancellationToken);
if (dek == null)
{
- throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync)}.");
+ throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync)}.");
}
return dek.EncryptData(plainText);
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyContainerCore.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyContainerCore.cs
index b5f5d340c9..68e5414275 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyContainerCore.cs
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyContainerCore.cs
@@ -335,6 +335,7 @@ internal async Task FetchUnWrappedMdeSupportedLegacyDekAsync(
unwrapResult.DataEncryptionKey);
return new MdeEncryptionAlgorithm(
+ unwrapResult.DataEncryptionKey,
plaintextDataEncryptionKey,
Data.Encryption.Cryptography.EncryptionType.Randomized);
}
@@ -378,13 +379,14 @@ internal async Task FetchUnWrappedLegacySupportedMdeDekAsync(
internal async Task FetchUnwrappedAsync(
DataEncryptionKeyProperties dekProperties,
CosmosDiagnosticsContext diagnosticsContext,
- CancellationToken cancellationToken)
+ CancellationToken cancellationToken,
+ bool withRawKey = false)
{
try
{
if (string.Equals(dekProperties.EncryptionAlgorithm, CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized))
{
- DataEncryptionKey dek = this.InitMdeEncryptionAlgorithm(dekProperties);
+ DataEncryptionKey dek = this.InitMdeEncryptionAlgorithm(dekProperties, withRawKey);
// TTL is not used since DEK is not cached.
return new InMemoryRawDek(dek, TimeSpan.FromMilliseconds(0));
@@ -564,7 +566,7 @@ private async Task UnWrapDekMdeEncAlgoAsync(
return unwrapResult;
}
- internal DataEncryptionKey InitMdeEncryptionAlgorithm(DataEncryptionKeyProperties dekProperties)
+ internal DataEncryptionKey InitMdeEncryptionAlgorithm(DataEncryptionKeyProperties dekProperties, bool withRawKey = false)
{
if (this.DekProvider.MdeKeyWrapProvider == null)
{
@@ -576,7 +578,8 @@ internal DataEncryptionKey InitMdeEncryptionAlgorithm(DataEncryptionKeyPropertie
dekProperties,
Data.Encryption.Cryptography.EncryptionType.Randomized,
this.DekProvider.MdeKeyWrapProvider.EncryptionKeyStoreProvider,
- this.DekProvider.PdekCacheTimeToLive);
+ this.DekProvider.PdekCacheTimeToLive,
+ withRawKey);
}
private async Task ReadResourceAsync(
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyProvider.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyProvider.cs
index 502e14897b..c92df3fa60 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyProvider.cs
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyProvider.cs
@@ -14,7 +14,19 @@ namespace Microsoft.Azure.Cosmos.Encryption.Custom
public abstract class DataEncryptionKeyProvider
{
///
- /// Retrieves the data encryption key for the given id.
+ /// Retrieves the data encryption key for the given id without rawkey. RawKey will be set to null.
+ ///
+ /// Identifier of the data encryption key.
+ /// Encryption algorithm that the retrieved key will be used with.
+ /// Token for request cancellation.
+ /// Data encryption key bytes.
+ public abstract Task FetchDataEncryptionKeyWithoutRawKeyAsync(
+ string id,
+ string encryptionAlgorithm,
+ CancellationToken cancellationToken);
+
+ ///
+ /// Retrieves the data encryption key for the given id with RawKey value.
///
/// Identifier of the data encryption key.
/// Encryption algorithm that the retrieved key will be used with.
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/MdeServices/MdeEncryptionAlgorithm.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/MdeServices/MdeEncryptionAlgorithm.cs
index d9144a5c4f..68d863114e 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/MdeServices/MdeEncryptionAlgorithm.cs
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/MdeServices/MdeEncryptionAlgorithm.cs
@@ -14,8 +14,10 @@ internal sealed class MdeEncryptionAlgorithm : DataEncryptionKey
{
private readonly AeadAes256CbcHmac256EncryptionAlgorithm mdeAeadAes256CbcHmac256EncryptionAlgorithm;
+ private readonly byte[] unwrapKey;
+
// unused for MDE Algorithm.
- public override byte[] RawKey => null;
+ public override byte[] RawKey { get; }
public override string EncryptionAlgorithm => CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized;
@@ -32,7 +34,8 @@ public MdeEncryptionAlgorithm(
DataEncryptionKeyProperties dekProperties,
Data.Encryption.Cryptography.EncryptionType encryptionType,
EncryptionKeyStoreProvider encryptionKeyStoreProvider,
- TimeSpan? cacheTimeToLive)
+ TimeSpan? cacheTimeToLive,
+ bool withRawKey=false)
{
if (dekProperties == null)
{
@@ -49,36 +52,39 @@ public MdeEncryptionAlgorithm(
dekProperties.EncryptionKeyWrapMetadata.Value,
encryptionKeyStoreProvider);
- ProtectedDataEncryptionKey protectedDataEncryptionKey;
- if (cacheTimeToLive.HasValue)
+ if (!withRawKey)
{
- // no caching
- if (cacheTimeToLive.Value == TimeSpan.Zero)
- {
- protectedDataEncryptionKey = new ProtectedDataEncryptionKey(
+ ProtectedDataEncryptionKey protectedDataEncryptionKey = cacheTimeToLive.HasValue && cacheTimeToLive.Value == TimeSpan.Zero
+ ? new ProtectedDataEncryptionKey(
+ dekProperties.Id,
+ keyEncryptionKey,
+ dekProperties.WrappedDataEncryptionKey)
+ : ProtectedDataEncryptionKey.GetOrCreate(
dekProperties.Id,
keyEncryptionKey,
dekProperties.WrappedDataEncryptionKey);
- }
- else
- {
- protectedDataEncryptionKey = ProtectedDataEncryptionKey.GetOrCreate(
- dekProperties.Id,
- keyEncryptionKey,
- dekProperties.WrappedDataEncryptionKey);
- }
+ this.mdeAeadAes256CbcHmac256EncryptionAlgorithm = AeadAes256CbcHmac256EncryptionAlgorithm.GetOrCreate(
+ protectedDataEncryptionKey,
+ encryptionType);
}
else
{
- protectedDataEncryptionKey = ProtectedDataEncryptionKey.GetOrCreate(
- dekProperties.Id,
- keyEncryptionKey,
- dekProperties.WrappedDataEncryptionKey);
+ byte[] rawKey = keyEncryptionKey.DecryptEncryptionKey(dekProperties.WrappedDataEncryptionKey);
+ PlaintextDataEncryptionKey plaintextDataEncryptionKey = cacheTimeToLive.HasValue && (cacheTimeToLive.Value == TimeSpan.Zero)
+ ? new PlaintextDataEncryptionKey(
+ dekProperties.Id,
+ rawKey)
+ : PlaintextDataEncryptionKey.GetOrCreate(
+ dekProperties.Id,
+ rawKey);
+ this.RawKey = rawKey;
+ this.mdeAeadAes256CbcHmac256EncryptionAlgorithm = AeadAes256CbcHmac256EncryptionAlgorithm.GetOrCreate(
+ plaintextDataEncryptionKey,
+ encryptionType);
+
}
- this.mdeAeadAes256CbcHmac256EncryptionAlgorithm = AeadAes256CbcHmac256EncryptionAlgorithm.GetOrCreate(
- protectedDataEncryptionKey,
- encryptionType);
+
}
///
@@ -90,9 +96,11 @@ public MdeEncryptionAlgorithm(
/// Data Encryption Key
/// Encryption type
public MdeEncryptionAlgorithm(
+ byte[] rawkey,
Data.Encryption.Cryptography.DataEncryptionKey dataEncryptionKey,
Data.Encryption.Cryptography.EncryptionType encryptionType)
{
+ this.RawKey = rawkey;
this.mdeAeadAes256CbcHmac256EncryptionAlgorithm = AeadAes256CbcHmac256EncryptionAlgorithm.GetOrCreate(
dataEncryptionKey,
encryptionType);
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/LegacyEncryptionTests.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/LegacyEncryptionTests.cs
index 27f4567732..2785f04815 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/LegacyEncryptionTests.cs
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/LegacyEncryptionTests.cs
@@ -1747,14 +1747,14 @@ public override async Task DecryptAsync(
throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned.");
}
- DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync(
+ DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync(
dataEncryptionKeyId,
encryptionAlgorithm,
cancellationToken);
if (dek == null)
{
- throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync)}.");
+ throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync)}.");
}
return dek.DecryptData(cipherText);
@@ -1766,7 +1766,7 @@ public override async Task EncryptAsync(
string encryptionAlgorithm,
CancellationToken cancellationToken = default)
{
- DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync(
+ DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync(
dataEncryptionKeyId,
encryptionAlgorithm,
cancellationToken);
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/MdeCustomEncryptionTests.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/MdeCustomEncryptionTests.cs
index 3b2b8f8d97..e100268ea0 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/MdeCustomEncryptionTests.cs
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/MdeCustomEncryptionTests.cs
@@ -20,6 +20,7 @@ namespace Microsoft.Azure.Cosmos.Encryption.EmulatorTests
using EncryptionKeyWrapMetadata = Custom.EncryptionKeyWrapMetadata;
using DataEncryptionKey = Custom.DataEncryptionKey;
using Newtonsoft.Json.Linq;
+ using System.Buffers.Text;
[TestClass]
public class MdeCustomEncryptionTests
@@ -103,6 +104,47 @@ public async Task EncryptionCreateDek()
Assert.AreEqual(dekProperties, readProperties);
}
+ [TestMethod]
+ public async Task FetchDataEncryptionKeyWithRawKey()
+ {
+ CosmosDataEncryptionKeyProvider dekProvider = new CosmosDataEncryptionKeyProvider(new TestEncryptionKeyStoreProvider());
+ await dekProvider.InitializeAsync(MdeCustomEncryptionTests.database, MdeCustomEncryptionTests.keyContainer.Id);
+ DataEncryptionKey k = await dekProvider.FetchDataEncryptionKeyAsync(dekProperties.Id, dekProperties.EncryptionAlgorithm, CancellationToken.None);
+ Assert.IsNotNull(k.RawKey);
+ }
+
+ [TestMethod]
+ public async Task FetchDataEncryptionKeyWithoutRawKey()
+ {
+ CosmosDataEncryptionKeyProvider dekProvider = new CosmosDataEncryptionKeyProvider(new TestEncryptionKeyStoreProvider());
+ await dekProvider.InitializeAsync(MdeCustomEncryptionTests.database, MdeCustomEncryptionTests.keyContainer.Id);
+ DataEncryptionKey k = await dekProvider.FetchDataEncryptionKeyWithoutRawKeyAsync(dekProperties.Id, dekProperties.EncryptionAlgorithm, CancellationToken.None);
+ Assert.IsNull(k.RawKey);
+ }
+
+ [TestMethod]
+ [Obsolete]
+ public async Task FetchDataEncryptionKeyMdeDEKAndLegacyBasedAlgorithm()
+ {
+ CosmosDataEncryptionKeyProvider dekProvider = new CosmosDataEncryptionKeyProvider(new TestEncryptionKeyStoreProvider());
+ await dekProvider.InitializeAsync(MdeCustomEncryptionTests.database, MdeCustomEncryptionTests.keyContainer.Id);
+ DataEncryptionKey k = await dekProvider.FetchDataEncryptionKeyAsync(dekProperties.Id, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized, CancellationToken.None);
+ Assert.IsNotNull(k.RawKey);
+ }
+
+ [TestMethod]
+ [Obsolete]
+ public async Task FetchDataEncryptionKeyLegacyDEKAndMdeBasedAlgorithm()
+ {
+ string dekId = "legacyDEK";
+ DataEncryptionKeyProperties dekProperties = await MdeCustomEncryptionTests.CreateDekAsync(MdeCustomEncryptionTests.dekProvider, dekId, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized);
+ // Use different DEK provider to avoid (unintentional) cache impact
+ CosmosDataEncryptionKeyProvider dekProvider = new CosmosDataEncryptionKeyProvider(new TestKeyWrapProvider(), new TestEncryptionKeyStoreProvider());
+ await dekProvider.InitializeAsync(MdeCustomEncryptionTests.database, MdeCustomEncryptionTests.keyContainer.Id);
+ DataEncryptionKey k = await dekProvider.FetchDataEncryptionKeyAsync(dekProperties.Id, CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized, CancellationToken.None);
+ Assert.IsNotNull(k.RawKey);
+ }
+
[TestMethod]
public async Task EncryptionRewrapDek()
{
@@ -2190,14 +2232,14 @@ public override async Task DecryptAsync(
throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned.");
}
- DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync(
+ DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync(
dataEncryptionKeyId,
encryptionAlgorithm,
cancellationToken);
if (dek == null)
{
- throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync)}.");
+ throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync)}.");
}
return dek.DecryptData(cipherText);
@@ -2209,7 +2251,7 @@ public override async Task EncryptAsync(
string encryptionAlgorithm,
CancellationToken cancellationToken = default)
{
- DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync(
+ DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync(
dataEncryptionKeyId,
encryptionAlgorithm,
cancellationToken);
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/CosmosEncryptorTests.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/CosmosEncryptorTests.cs
index 747bf3e295..63c5b370d1 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/CosmosEncryptorTests.cs
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/CosmosEncryptorTests.cs
@@ -34,7 +34,7 @@ public static void ClassInitialize(TestContext testContext)
CosmosEncryptorTests.mockDataEncryptionKeyProvider = new Mock();
CosmosEncryptorTests.mockDataEncryptionKeyProvider
- .Setup(m => m.FetchDataEncryptionKeyAsync(It.IsAny(), It.IsAny(), It.IsAny()))
+ .Setup(m => m.FetchDataEncryptionKeyWithoutRawKeyAsync(It.IsAny(), It.IsAny(), It.IsAny()))
.ReturnsAsync((string dekId, string algo, CancellationToken cancellationToken) =>
dekId == CosmosEncryptorTests.dekId ? CosmosEncryptorTests.mockDataEncryptionKey.Object : null);
@@ -82,7 +82,7 @@ public async Task ValidateEncryptDecrypt()
Times.Once);
CosmosEncryptorTests.mockDataEncryptionKeyProvider.Verify(
- m => m.FetchDataEncryptionKeyAsync(
+ m => m.FetchDataEncryptionKeyWithoutRawKeyAsync(
CosmosEncryptorTests.dekId,
CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized,
It.IsAny()), Times.Exactly(2));