@@ -21,109 +21,130 @@ foreach ((string mode, (string modeCode, CipherMode? bclMode)) in modes)
21
21
{
22
22
foreach (int keySize in new int[] { 128, 192, 256 })
23
23
{
24
- foreach (int inputLength in new int[] { 16, 32 , 64 })
24
+ foreach (int inputLength in new int[] { 16, 35 , 64 })
25
25
{
26
- byte[] input = new byte[inputLength];
27
- random.NextBytes(input);
26
+ foreach (bool pad in new bool[] { false, true })
27
+ {
28
+ // It is not allowed to use no padding on non-block lengths
29
+ // It makes sense in cfb, ctr and ofb modes
30
+ if (!pad && inputLength % 16 != 0 && mode is not "cfb" or "ctr" or "ofb")
31
+ {
32
+ continue;
33
+ }
28
34
29
- byte[] key = new byte[keySize / 8];
30
- random.NextBytes(key);
35
+ // It does not make sense to test padding for stream cipher modes
36
+ // (and the OpenSSL, BCL implementations differ)
37
+ if (pad && mode is "cfb" or "ctr" or "ofb")
38
+ {
39
+ continue;
40
+ }
31
41
32
- byte[] iv = new byte[16 ];
33
- random.NextBytes(iv );
42
+ byte[] input = new byte[inputLength ];
43
+ random.NextBytes(input );
34
44
35
- StringBuilder openSslCmd = new();
45
+ byte[] key = new byte[keySize / 8];
46
+ random.NextBytes(key);
36
47
37
- openSslCmd.Append($"echo -n -e '{string.Join("", input.Select(b => $"\\x{b:x2}"))}' |");
38
- openSslCmd.Append($" openssl enc -e -aes-{keySize}-{mode}");
39
- openSslCmd.Append($" -K {Convert.ToHexString(key)}");
40
- if (mode != "ecb")
41
- {
42
- openSslCmd.Append($" -iv {Convert.ToHexString(iv)}");
43
- }
44
- openSslCmd.Append(" -nopad");
48
+ byte[] iv = new byte[16];
49
+ random.NextBytes(iv);
45
50
46
- ProcessStartInfo pi = new("wsl", openSslCmd.ToString())
47
- {
48
- RedirectStandardOutput = true,
49
- RedirectStandardError = true,
50
- };
51
+ StringBuilder openSslCmd = new();
51
52
52
- byte[] expected;
53
- string error;
53
+ openSslCmd.Append($"echo -n -e '{string.Join("", input.Select(b => $"\\x{b:x2}"))}' |");
54
+ openSslCmd.Append($" openssl enc -e -aes-{keySize}-{mode}");
55
+ openSslCmd.Append($" -K {Convert.ToHexString(key)}");
56
+ if (mode != "ecb")
57
+ {
58
+ openSslCmd.Append($" -iv {Convert.ToHexString(iv)}");
59
+ }
54
60
55
- using (MemoryStream ms = new())
56
- {
57
- var p = Process.Start(pi);
58
- p.StandardOutput.BaseStream.CopyTo(ms);
59
- error = p.StandardError.ReadToEnd();
61
+ if (!pad)
62
+ {
63
+ openSslCmd.Append(" -nopad");
64
+ }
60
65
61
- p.WaitForExit();
66
+ ProcessStartInfo pi = new("wsl", openSslCmd.ToString())
67
+ {
68
+ RedirectStandardOutput = true,
69
+ RedirectStandardError = true,
70
+ };
62
71
63
- expected = ms.ToArray() ;
64
- }
72
+ byte[] expected ;
73
+ string error;
65
74
66
- tw.WriteLine("[TestMethod]");
67
- tw.WriteLine($"public void AES_{mode.ToUpper()}_{keySize}_Length{inputLength}()");
68
- tw.WriteLine("{");
69
- tw.Indent++;
75
+ using (MemoryStream ms = new())
76
+ {
77
+ var p = Process.Start(pi);
78
+ p.StandardOutput.BaseStream.CopyTo(ms);
79
+ error = p.StandardError.ReadToEnd();
70
80
71
- WriteBytes(input);
72
- WriteBytes(key);
73
- if (mode != "ecb")
74
- {
75
- WriteBytes(iv);
76
- }
77
- tw.WriteLine();
81
+ p.WaitForExit();
78
82
79
- if (!string.IsNullOrWhiteSpace(error))
80
- {
81
- tw.WriteLine($"// {openSslCmd}");
82
- tw.WriteLine($"Assert.Fail(@\"{error}\");");
83
+ expected = ms.ToArray();
84
+ }
83
85
84
- tw.Indent--;
85
- tw.WriteLine("}");
86
- tw.WriteLine();
87
- continue;
88
- }
86
+ tw.WriteLine("[TestMethod]");
87
+ tw.WriteLine($"public void AES_{mode.ToUpper()}_{keySize}_Length{inputLength}_{(pad ? "Pad" : "NoPad")}()");
88
+ tw.WriteLine("{");
89
+ tw.Indent++;
89
90
90
- tw.WriteLine($"// {openSslCmd} | hd"); // pipe to hexdump
91
- WriteBytes(expected);
92
- tw.WriteLine();
93
- tw.WriteLine($"var actual = new AesCipher(key, {modeCode}, pkcs7Padding: false).Encrypt(input);");
94
- tw.WriteLine();
95
- tw.WriteLine($"CollectionAssert.AreEqual(expected, actual);");
91
+ WriteBytes(input);
92
+ WriteBytes(key);
93
+ if (mode != "ecb")
94
+ {
95
+ WriteBytes(iv);
96
+ }
97
+ tw.WriteLine();
96
98
97
- if (bclMode is not null and not CipherMode.OFB)
98
- {
99
- // Verify the OpenSSL result is the same as the .NET BCL, just to be sure
100
- Aes bcl = Aes.Create();
101
- bcl.Key = key;
102
- bcl.IV = iv;
103
- bcl.Mode = bclMode.Value;
104
- bcl.Padding = PaddingMode.None;
105
- bcl.FeedbackSize = 128; // .NET is CFB8 by default, OpenSSL is CFB128
106
- byte[] bclBytes = bcl.CreateEncryptor().TransformFinalBlock(input, 0, input.Length);
107
-
108
- if (!bclBytes.AsSpan().SequenceEqual(expected))
99
+ if (!string.IsNullOrWhiteSpace(error))
109
100
{
110
- tw.WriteLine();
111
- tw.WriteLine(@"Assert.Inconclusive(@""OpenSSL does not match the .NET BCL");
112
- tw.Indent++;
113
- tw.WriteLine($@"OpenSSL: {Convert.ToHexString(expected)}");
114
- tw.WriteLine($@"BCL: {Convert.ToHexString(bclBytes)}"");");
101
+ tw.WriteLine($"// {openSslCmd}");
102
+ tw.WriteLine($"Assert.Fail(@\"{error}\");");
103
+
115
104
tw.Indent--;
105
+ tw.WriteLine("}");
106
+ tw.WriteLine();
107
+ continue;
116
108
}
117
- }
118
109
119
- tw.WriteLine();
120
- tw.WriteLine($"var decrypted = new AesCipher(key, {modeCode}, pkcs7Padding: false).Decrypt(actual);");
121
- tw.WriteLine();
122
- tw.WriteLine($"CollectionAssert.AreEqual(input, decrypted);");
110
+ tw.WriteLine($"// {openSslCmd} | hd"); // pipe to hexdump
111
+ WriteBytes(expected);
112
+ tw.WriteLine();
113
+ tw.WriteLine($"var actual = new AesCipher(key, {modeCode}, pkcs7Padding: {(pad ? "true" : "false")}).Encrypt(input);");
114
+ tw.WriteLine();
115
+ tw.WriteLine($"CollectionAssert.AreEqual(expected, actual);");
116
+
117
+ if (bclMode is not null and not CipherMode.OFB and not CipherMode.CFB)
118
+ {
119
+ // Verify the OpenSSL result is the same as the .NET BCL, just to be sure
120
+ Aes bcl = Aes.Create();
121
+ bcl.Key = key;
122
+ bcl.IV = iv;
123
+ bcl.Mode = bclMode.Value;
124
+ bcl.Padding = pad ? PaddingMode.PKCS7 : PaddingMode.None;
125
+ bcl.FeedbackSize = 128; // .NET is CFB8 by default, OpenSSL is CFB128
126
+ byte[] bclBytes = bcl.CreateEncryptor().TransformFinalBlock(input, 0, input.Length);
127
+
128
+ if (!bclBytes.AsSpan().SequenceEqual(expected))
129
+ {
130
+ tw.WriteLine();
131
+ tw.WriteLine(@"Assert.Inconclusive(@""OpenSSL does not match the .NET BCL");
132
+ tw.Indent++;
133
+ tw.WriteLine($@"OpenSSL: {Convert.ToHexString(expected)}");
134
+ tw.WriteLine($@"BCL: {Convert.ToHexString(bclBytes)}"");");
135
+ tw.Indent--;
136
+ }
137
+ }
123
138
124
- tw.Indent--;
125
- tw.WriteLine("}");
126
- tw.WriteLine();
139
+ tw.WriteLine();
140
+ tw.WriteLine($"var decrypted = new AesCipher(key, {modeCode}, pkcs7Padding: {(pad ? "true" : "false")}).Decrypt(actual);");
141
+ tw.WriteLine();
142
+ tw.WriteLine($"CollectionAssert.AreEqual(input, decrypted);");
143
+
144
+ tw.Indent--;
145
+ tw.WriteLine("}");
146
+ tw.WriteLine();
147
+ }
127
148
}
128
149
}
129
150
}
0 commit comments