Skip to content

Commit bd12c47

Browse files
Bouncy Castle cryptography: .NET 10, OAEP, 2048-bit DSA, derived Blowfish key
- Retarget both projects to net10.0; BouncyCastle.Cryptography 2.3.1 to 2.7.0; Microsoft.NET.Test.Sdk 18.10.1, coverlet.collector 10.1.0, MSTest 4.5.1. - RSA: Pkcs1Encoding to OaepEncoding over SHA-256. - DSA: 2048-bit parameters through DsaParameterGenerationParameters (the Init(size, certainty) overload stops at 1024 bits). - Blowfish: derive the key from the password with PBKDF2 (HMAC-SHA256, random salt) instead of using the password bytes as the key; static class, file-scoped namespace, redundant usings removed. - Program.cs: hash the article's input string and print the DSA signature instead of the Blowfish ciphertext. - Tests: fix the "pasword" typo, add MD5 and SHA-256 known-answer tests, discard unused out values.
1 parent 62ea252 commit bd12c47

9 files changed

Lines changed: 85 additions & 57 deletions

File tree

‎authorization-dotnet/BouncyCastleCryptography/BouncyCastleCryptography/AsymmetricEncryption/DsaEncryptor.cs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Org.BouncyCastle.Crypto.Generators;
1+
using Org.BouncyCastle.Crypto.Digests;
2+
using Org.BouncyCastle.Crypto.Generators;
23
using Org.BouncyCastle.Crypto.Parameters;
34
using Org.BouncyCastle.Crypto;
45
using Org.BouncyCastle.Security;
@@ -11,9 +12,9 @@ public static class DsaEncryptor
1112
public static AsymmetricCipherKeyPair GenerateDsaKeyPair()
1213
{
1314
// Create DSA parameters
14-
var dsaParamsGenerator = new DsaParametersGenerator();
15+
var dsaParamsGenerator = new DsaParametersGenerator(new Sha256Digest());
1516
var random = new SecureRandom();
16-
dsaParamsGenerator.Init(1024, 80, random); // key size: 1024 bits, certainty: 80
17+
dsaParamsGenerator.Init(new DsaParameterGenerationParameters(2048, 256, 80, random)); // key size: 2048 bits, q size: 256 bits, certainty: 80
1718

1819
// Generate DSA key pair
1920
var dsaParams = dsaParamsGenerator.GenerateParameters();

‎authorization-dotnet/BouncyCastleCryptography/BouncyCastleCryptography/AsymmetricEncryption/RsaEncryptor.cs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Org.BouncyCastle.Crypto.Encodings;
1+
using Org.BouncyCastle.Crypto.Digests;
2+
using Org.BouncyCastle.Crypto.Encodings;
23
using Org.BouncyCastle.Crypto.Engines;
34
using Org.BouncyCastle.Crypto.Generators;
45
using Org.BouncyCastle.Crypto;
@@ -21,7 +22,7 @@ public static byte[] RsaEncrypt(string input, AsymmetricKeyParameter publicKey)
2122
{
2223
var inputBytes = Encoding.UTF8.GetBytes(input);
2324

24-
var cipher = new Pkcs1Encoding(new RsaEngine());
25+
var cipher = new OaepEncoding(new RsaEngine(), new Sha256Digest());
2526

2627
cipher.Init(true, publicKey);
2728

@@ -30,7 +31,7 @@ public static byte[] RsaEncrypt(string input, AsymmetricKeyParameter publicKey)
3031

3132
public static string RsaDecrypt(byte[] encryptedBytes, AsymmetricKeyParameter privateKey)
3233
{
33-
var cipher = new Pkcs1Encoding(new RsaEngine());
34+
var cipher = new OaepEncoding(new RsaEngine(), new Sha256Digest());
3435

3536
// Initialize the cipher for decryption with the private key
3637
cipher.Init(false, privateKey);

‎authorization-dotnet/BouncyCastleCryptography/BouncyCastleCryptography/BouncyCastleCryptography.csproj‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net8.0</TargetFramework>
5+
<TargetFramework>net10.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
88
</PropertyGroup>
@@ -14,7 +14,7 @@
1414
</ItemGroup>
1515

1616
<ItemGroup>
17-
<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.1" />
17+
<PackageReference Include="BouncyCastle.Cryptography" Version="2.7.0" />
1818
</ItemGroup>
1919

2020
</Project>

‎authorization-dotnet/BouncyCastleCryptography/BouncyCastleCryptography/Program.cs‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
using BouncyCastleCryptography.SymmetricEncryption;
44

55
var input = "Hello, Bouncy Castle!";
6+
var secretValue = "This is my password! Dont read me!";
67

78
// HASHING
89
Console.WriteLine("Hashing:");
910

10-
var hash = Md5Hasher.Md5Hash(input);
11+
var hash = Md5Hasher.Md5Hash(secretValue);
1112

1213
var hashAsStr = Convert.ToBase64String(hash);
1314

1415
Console.WriteLine("MD5 hash result: " + hashAsStr);
1516

16-
hash = ShaHasher.ShaHash(input);
17+
hash = ShaHasher.ShaHash(secretValue);
1718

1819
hashAsStr = Convert.ToBase64String(hash);
1920

@@ -32,7 +33,7 @@
3233

3334
var password = "mysecretpassword";
3435

35-
encryptedData = BlowfishEncryptor.BlowfishEncrypt(input, password, out byte[] iv2);
36+
encryptedData = BlowfishEncryptor.BlowfishEncrypt(input, password, out byte[] salt, out byte[] iv2);
3637

3738
encryptedString = Convert.ToBase64String(encryptedData);
3839

@@ -55,7 +56,7 @@
5556

5657
var signature = DsaEncryptor.DsaSign(input, keyPair2.Private);
5758

58-
var signatureAsStr = Convert.ToBase64String(encryptedData);
59+
var signatureAsStr = Convert.ToBase64String(signature);
5960

6061
var isSignatureValid = DsaEncryptor.DsaVerify(input, signature, keyPair2.Public);
6162

‎authorization-dotnet/BouncyCastleCryptography/BouncyCastleCryptography/SymmetricEncryption/AesEncryptor.cs‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ public static string AesDecrypt(byte[] key, byte[] iv, byte[] encryptedBytes)
3535
// Decrypt the encrypted data
3636
var decryptedBytes = cipher.DoFinal(encryptedBytes);
3737

38-
var decryptedString = Encoding.UTF8.GetString(decryptedBytes);
39-
40-
return decryptedString;
38+
return Encoding.UTF8.GetString(decryptedBytes);
4139
}
4240
}
Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,53 @@
1-
using Org.BouncyCastle.Crypto.Parameters;
2-
using Org.BouncyCastle.Crypto;
1+
using Org.BouncyCastle.Crypto.Digests;
2+
using Org.BouncyCastle.Crypto.Generators;
3+
using Org.BouncyCastle.Crypto.Parameters;
34
using Org.BouncyCastle.Security;
4-
using System;
5-
using System.Collections.Generic;
6-
using System.Linq;
75
using System.Text;
8-
using System.Threading.Tasks;
96

10-
namespace BouncyCastleCryptography.SymmetricEncryption
7+
namespace BouncyCastleCryptography.SymmetricEncryption;
8+
9+
public static class BlowfishEncryptor
1110
{
12-
public class BlowfishEncryptor
11+
private const int Iterations = 600_000;
12+
13+
public static byte[] BlowfishEncrypt(string input, string password, out byte[] salt, out byte[] iv)
1314
{
14-
public static byte[] BlowfishEncrypt(string input, string password, out byte[] iv)
15-
{
16-
var inputBytes = Encoding.UTF8.GetBytes(input);
15+
var inputBytes = Encoding.UTF8.GetBytes(input);
16+
17+
var random = new SecureRandom();
18+
salt = new byte[16];
19+
random.NextBytes(salt);
20+
iv = new byte[8]; // Blowfish uses an 8-byte (64-bit) IV
21+
random.NextBytes(iv);
22+
23+
var cipher = CipherUtilities.GetCipher("Blowfish/CBC/PKCS7Padding");
1724

18-
var random = new SecureRandom();
19-
iv = new byte[8]; // Blowfish uses an 8-byte (64-bit) IV
20-
random.NextBytes(iv);
25+
var keyParam = DeriveKey(password, salt);
2126

22-
var cipher = CipherUtilities.GetCipher("Blowfish/CBC/PKCS7Padding");
27+
cipher.Init(true, new ParametersWithIV(keyParam, iv));
2328

24-
var keyBytes = Encoding.UTF8.GetBytes(password);
25-
var keyParam = new KeyParameter(keyBytes);
29+
return cipher.DoFinal(inputBytes);
30+
}
2631

27-
cipher.Init(true, new ParametersWithIV(keyParam, iv));
32+
public static string BlowfishDecrypt(byte[] encryptedBytes, string password, byte[] salt, byte[] iv)
33+
{
34+
var cipher = CipherUtilities.GetCipher("Blowfish/CBC/PKCS7Padding");
2835

29-
return cipher.DoFinal(inputBytes);
30-
}
36+
var keyParam = DeriveKey(password, salt);
3137

32-
public static string BlowfishDecrypt(byte[] encryptedBytes, string password, byte[] iv)
33-
{
34-
var cipher = CipherUtilities.GetCipher("Blowfish/CBC/PKCS7Padding");
38+
cipher.Init(false, new ParametersWithIV(keyParam, iv));
3539

36-
var keyBytes = Encoding.UTF8.GetBytes(password);
37-
var keyParam = new KeyParameter(keyBytes);
40+
var plainBytes = cipher.DoFinal(encryptedBytes);
3841

39-
cipher.Init(false, new ParametersWithIV(keyParam, iv));
42+
return Encoding.UTF8.GetString(plainBytes);
43+
}
4044

41-
var plainBytes = cipher.DoFinal(encryptedBytes);
45+
private static KeyParameter DeriveKey(string password, byte[] salt)
46+
{
47+
// PBKDF2 with HMAC-SHA256 stretches the password and salt into a 128-bit key
48+
var generator = new Pkcs5S2ParametersGenerator(new Sha256Digest());
49+
generator.Init(Encoding.UTF8.GetBytes(password), salt, Iterations);
4250

43-
return Encoding.UTF8.GetString(plainBytes);
44-
}
51+
return (KeyParameter)generator.GenerateDerivedParameters("Blowfish", 128);
4552
}
4653
}

‎authorization-dotnet/BouncyCastleCryptography/BouncyCastleCryptographyTests/BouncyCastleCryptographyTests.csproj‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFramework>net10.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77

@@ -10,10 +10,10 @@
1010
</PropertyGroup>
1111

1212
<ItemGroup>
13-
<PackageReference Include="coverlet.collector" Version="6.0.0" />
14-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
15-
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
16-
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
13+
<PackageReference Include="coverlet.collector" Version="10.1.0" />
14+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.1" />
15+
<PackageReference Include="MSTest.TestAdapter" Version="4.5.1" />
16+
<PackageReference Include="MSTest.TestFramework" Version="4.5.1" />
1717
</ItemGroup>
1818

1919
<ItemGroup>

‎authorization-dotnet/BouncyCastleCryptography/BouncyCastleCryptographyTests/HashingUnitTests.cs‎

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public class HashingUnitTests
88
[TestMethod]
99
public void GivenSecretData_WhenMd5IsUsed_ThenSecretIsHashed()
1010
{
11-
var secretValue = "This is my pasword! Dont read me!";
11+
var secretValue = "This is my password! Dont read me!";
1212

1313
var hash = Md5Hasher.Md5Hash(secretValue);
1414

@@ -18,7 +18,7 @@ public void GivenSecretData_WhenMd5IsUsed_ThenSecretIsHashed()
1818
[TestMethod]
1919
public void GivenSecretData_WhenMd5HashingMultipleTimes_ThenResultIsDeterministic()
2020
{
21-
var secretValue = "This is my pasword! Dont read me!";
21+
var secretValue = "This is my password! Dont read me!";
2222

2323
var hash = Md5Hasher.Md5Hash(secretValue);
2424

@@ -30,7 +30,7 @@ public void GivenSecretData_WhenMd5HashingMultipleTimes_ThenResultIsDeterministi
3030
[TestMethod]
3131
public void GivenSecretData_WhenShaIsUsed_ThenSecretIsHashed()
3232
{
33-
var secretValue = "This is my pasword! Dont read me!";
33+
var secretValue = "This is my password! Dont read me!";
3434

3535
var hash = ShaHasher.ShaHash(secretValue);
3636

@@ -40,12 +40,32 @@ public void GivenSecretData_WhenShaIsUsed_ThenSecretIsHashed()
4040
[TestMethod]
4141
public void GivenSecretData_WhenShaHashingMultipleTimes_ThenResultIsDeterministic()
4242
{
43-
var secretValue = "This is my pasword! Dont read me!";
43+
var secretValue = "This is my password! Dont read me!";
4444

4545
var hash = ShaHasher.ShaHash(secretValue);
4646

4747
var hash2 = ShaHasher.ShaHash(secretValue);
4848

4949
CollectionAssert.AreEqual(hash, hash2);
5050
}
51+
52+
[TestMethod]
53+
public void GivenSecretData_WhenMd5IsUsed_ThenHashMatchesKnownValue()
54+
{
55+
var secretValue = "This is my password! Dont read me!";
56+
57+
var hash = Md5Hasher.Md5Hash(secretValue);
58+
59+
Assert.AreEqual("l5aMGrOOPOxm6i6cRK/sqA==", Convert.ToBase64String(hash));
60+
}
61+
62+
[TestMethod]
63+
public void GivenSecretData_WhenShaIsUsed_ThenHashMatchesKnownValue()
64+
{
65+
var secretValue = "This is my password! Dont read me!";
66+
67+
var hash = ShaHasher.ShaHash(secretValue);
68+
69+
Assert.AreEqual("SSNYFZG3vQSGtXqZVaSZry4QBm4uueLwegd/gd6H8ns=", Convert.ToBase64String(hash));
70+
}
5171
}

‎authorization-dotnet/BouncyCastleCryptography/BouncyCastleCryptographyTests/SymmetricEncryptionUnitTests.cs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public void GivenSecretData_WhenAesEncrypting_ThenDataIsEncrypted()
1010
{
1111
var input = "Hello, Bouncy Castle!";
1212

13-
var encryptedData = AesEncryptor.AesEncrypt(input, out byte[] iv, out byte[] key);
13+
var encryptedData = AesEncryptor.AesEncrypt(input, out _, out _);
1414

1515
var encryptedString = Convert.ToBase64String(encryptedData);
1616

@@ -39,7 +39,7 @@ public void GivenSecretData_WhenBlowfishEncrypting_ThenDataIsEncrypted()
3939
var input = "Hello, Bouncy Castle!";
4040
var password = "mysecretpassword";
4141

42-
var encryptedBytes = BlowfishEncryptor.BlowfishEncrypt(input, password, out byte[] iv);
42+
var encryptedBytes = BlowfishEncryptor.BlowfishEncrypt(input, password, out _, out _);
4343

4444
var encryptedString = Convert.ToBase64String(encryptedBytes);
4545

@@ -53,9 +53,9 @@ public void GivenSecretData_WhenBlowfishEncrypting_ThenDataCanBeDecrypted()
5353
var input = "Hello, Bouncy Castle!";
5454
var password = "mysecretpassword";
5555

56-
var encryptedBytes = BlowfishEncryptor.BlowfishEncrypt(input, password, out byte[] iv);
56+
var encryptedBytes = BlowfishEncryptor.BlowfishEncrypt(input, password, out byte[] salt, out byte[] iv);
5757

58-
var myDecryptedStr = BlowfishEncryptor.BlowfishDecrypt(encryptedBytes, password, iv);
58+
var myDecryptedStr = BlowfishEncryptor.BlowfishDecrypt(encryptedBytes, password, salt, iv);
5959

6060
Assert.IsNotNull(myDecryptedStr);
6161
Assert.AreEqual(input, myDecryptedStr);

0 commit comments

Comments
 (0)