Skip to content

Commit 2d3acc6

Browse files
vcsjonesbartonjs
andauthored
Add one-shot CFB encrypt/decrypt to SymmetricAlgorithm
Adds the CFB versions similar to the already-added ECB and CBC versions. Co-authored-by: Jeremy Barton <jbarton@microsoft.com>
1 parent 59ab54c commit 2d3acc6

File tree

28 files changed

+2857
-176
lines changed

28 files changed

+2857
-176
lines changed

src/libraries/Common/src/Internal/Cryptography/Helpers.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,9 @@ internal static partial class Helpers
3030
return (byte[])(src.Clone());
3131
}
3232

33-
public static int GetPaddingSize(this SymmetricAlgorithm algorithm, CipherMode mode, int feedbackSizeBits)
33+
public static int GetPaddingSize(this SymmetricAlgorithm algorithm, CipherMode mode, int feedbackSizeInBits)
3434
{
35-
// CFB8 does not require any padding at all
36-
// otherwise, it is always required to pad for block size
37-
if (mode == CipherMode.CFB && feedbackSizeBits == 8)
38-
return 1;
39-
40-
return algorithm.BlockSize / 8;
35+
return (mode == CipherMode.CFB ? feedbackSizeInBits : algorithm.BlockSize) / 8;
4136
}
4237

4338
internal static bool TryCopyToDestination(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten)

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherOneShotTests.cs

Lines changed: 579 additions & 26 deletions
Large diffs are not rendered by default.

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,7 @@ private static void TestAesTransformDirectKey(
11241124
{
11251125
aes.Mode = cipherMode;
11261126
aes.Padding = paddingMode;
1127+
aes.Key = key;
11271128

11281129
if (feedbackSize.HasValue)
11291130
{
@@ -1135,16 +1136,19 @@ private static void TestAesTransformDirectKey(
11351136

11361137
if (cipherMode == CipherMode.ECB)
11371138
{
1138-
aes.Key = key;
11391139
liveOneShotDecryptBytes = aes.DecryptEcb(cipherBytes, paddingMode);
11401140
liveOneShotEncryptBytes = aes.EncryptEcb(plainBytes, paddingMode);
11411141
}
11421142
else if (cipherMode == CipherMode.CBC)
11431143
{
1144-
aes.Key = key;
11451144
liveOneShotDecryptBytes = aes.DecryptCbc(cipherBytes, iv, paddingMode);
11461145
liveOneShotEncryptBytes = aes.EncryptCbc(plainBytes, iv, paddingMode);
11471146
}
1147+
else if (cipherMode == CipherMode.CFB)
1148+
{
1149+
liveOneShotDecryptBytes = aes.DecryptCfb(cipherBytes, iv, paddingMode, feedbackSizeInBits: feedbackSize.Value);
1150+
liveOneShotEncryptBytes = aes.EncryptCfb(plainBytes, iv, paddingMode, feedbackSizeInBits: feedbackSize.Value);
1151+
}
11481152
}
11491153

11501154
Assert.Equal(cipherBytes, liveEncryptBytes);

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESCipherOneShotTests.cs

Lines changed: 273 additions & 26 deletions
Large diffs are not rendered by default.

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESCipherTests.cs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ private static void TestDESTransformDirectKey(
531531
{
532532
des.Mode = cipherMode;
533533
des.Padding = paddingMode;
534+
des.Key = key;
534535

535536
if (feedbackSize.HasValue)
536537
{
@@ -540,17 +541,23 @@ private static void TestDESTransformDirectKey(
540541
liveEncryptBytes = DESEncryptDirectKey(des, key, iv, plainBytes);
541542
liveDecryptBytes = DESDecryptDirectKey(des, key, iv, cipherBytes);
542543

543-
if (cipherMode == CipherMode.ECB)
544-
{
545-
des.Key = key;
546-
liveOneShotDecryptBytes = des.DecryptEcb(cipherBytes, paddingMode);
547-
liveOneShotEncryptBytes = des.EncryptEcb(plainBytes, paddingMode);
548-
}
549-
else if (cipherMode == CipherMode.CBC)
544+
if (DESFactory.OneShotSupported)
550545
{
551-
des.Key = key;
552-
liveOneShotDecryptBytes = des.DecryptCbc(cipherBytes, iv, paddingMode);
553-
liveOneShotEncryptBytes = des.EncryptCbc(plainBytes, iv, paddingMode);
546+
if (cipherMode == CipherMode.ECB)
547+
{
548+
liveOneShotDecryptBytes = des.DecryptEcb(cipherBytes, paddingMode);
549+
liveOneShotEncryptBytes = des.EncryptEcb(plainBytes, paddingMode);
550+
}
551+
else if (cipherMode == CipherMode.CBC)
552+
{
553+
liveOneShotDecryptBytes = des.DecryptCbc(cipherBytes, iv, paddingMode);
554+
liveOneShotEncryptBytes = des.EncryptCbc(plainBytes, iv, paddingMode);
555+
}
556+
else if (cipherMode == CipherMode.CFB)
557+
{
558+
liveOneShotDecryptBytes = des.DecryptCfb(cipherBytes, iv, paddingMode, feedbackSizeInBits: feedbackSize.Value);
559+
liveOneShotEncryptBytes = des.EncryptCfb(plainBytes, iv, paddingMode, feedbackSizeInBits: feedbackSize.Value);
560+
}
554561
}
555562
}
556563

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESFactory.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ namespace System.Security.Cryptography.Encryption.Des.Tests
66
public interface IDESProvider
77
{
88
DES Create();
9+
bool OneShotSupported { get; }
910
}
1011

1112
public static partial class DESFactory
1213
{
13-
public static DES Create()
14-
{
15-
return s_provider.Create();
16-
}
14+
public static DES Create() => s_provider.Create();
15+
public static bool OneShotSupported => s_provider.OneShotSupported;
1716
}
1817
}

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2CipherOneShotTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,26 @@ public void DecryptOneShot_Array(byte[] plaintext, byte[] ciphertext, PaddingMod
9090
public void EncryptOneShot_Array(byte[] plaintext, byte[] ciphertext, PaddingMode padding, CipherMode mode) =>
9191
EncryptOneShot_ArrayTest(plaintext, ciphertext, padding, mode);
9292

93+
[Fact]
94+
public void EncryptOneShot_CfbNotSupported()
95+
{
96+
using (SymmetricAlgorithm alg = CreateAlgorithm())
97+
{
98+
Assert.ThrowsAny<CryptographicException>(() =>
99+
alg.TryEncryptCfb(ReadOnlySpan<byte>.Empty, IV, Span<byte>.Empty, out _));
100+
}
101+
}
102+
103+
[Fact]
104+
public void DecryptOneShot_CfbNotSupported()
105+
{
106+
using (SymmetricAlgorithm alg = CreateAlgorithm())
107+
{
108+
Assert.ThrowsAny<CryptographicException>(() =>
109+
alg.TryDecryptCfb(ReadOnlySpan<byte>.Empty, IV, Span<byte>.Empty, out _));
110+
}
111+
}
112+
93113
public static IEnumerable<object[]> TestCases
94114
{
95115
get

0 commit comments

Comments
 (0)