### Install BouncyCastle via NuGet Package Manager Source: https://github.com/bcgit/bc-csharp/blob/master/README.md Use this command in the Package Manager Console to install the BouncyCastle.Cryptography NuGet package. ```powershell Install-Package BouncyCastle.Cryptography ``` -------------------------------- ### Install Bouncy Castle Cryptography Package Source: https://context7.com/bcgit/bc-csharp/llms.txt Install the Bouncy Castle Cryptography library via NuGet Package Manager or the .NET CLI. ```bash # Via NuGet Package Manager Install-Package BouncyCastle.Cryptography ``` ```bash # Via .NET CLI dotnet add package BouncyCastle.Cryptography ``` -------------------------------- ### S/MIME Message Example 4.1.bin Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt Binary representation of an S/MIME message. ```text MIIDt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0 dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm +H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX EiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3iEFJbQ169MWMwYQIBATAYMBIxEDAOBgNV BAMTB0NhcmxEU1MCAgDIMAcGBSsOAwIaMAkGByqGSM44BAMELjAsAhQJkf7r0mn1GLfXzV X0geoqQmqtAwIUOgfMwyG+4RpLfz61Ddu6HOq8zYk= ``` -------------------------------- ### Sample Content and Hashes Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt The raw string content used in examples, along with its MD5 and SHA-1 hash representations. ```text 5468 6973 2069 7320 736f 6d65 2073 616d 706c 6520 636f 6e74 656e 742e ``` ```text 9898 cac8 fab7 691f f89d c207 24e7 4a04 ``` ```text 406a ec08 5279 ba6e 1602 2d9e 0629 c022 9687 dd48 ``` -------------------------------- ### Example 4.10 .bin S/MIME Content Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt This snippet represents binary S/MIME content, likely an encrypted or signed message, in .bin format. It starts with a base64 encoded structure typical of S/MIME messages. ```bin MIIH/wYJKoZIhvcNAQcCoIIH8DCCB+wCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCAuAwggLcMIICm6ADAgECAgIAyDAJ BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMj MxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYwggErBgcqhkjOOAQBMIIBHgKB gQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2T DINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0 dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm +H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX ``` -------------------------------- ### S/MIME Message Example 4.3.bin Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt Binary representation of an S/MIME message. ```text MIIDdwYJKoZIhvcNAQcCoIIDaDCCA2QCAQExCTAHBgUrDgMCGjALBgkqhkiG9w0BBwGggg LgMIIC3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4X DTk5MDgxNzAxMTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1Mwgg G2MIIBKwYHKoZIzjgEATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauECE// lOFzSH4M1vNESNH+n6+koYkv4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny/dQ6 iLVPE/sAcIR01diMPDtbPjVQh11Tl2EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDiR6Ya RWa4E8baj7g3IStii/eTzQKBgCY40BSJMqo5+z5t2UtZakx2IzkEAjVc8ssaMMMeUF3dm1 nizaoFPVjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3qnMkhijt2FOnOLl2jB80jhbgvMAF8 bUmJEYk2RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGBSmA5ujY5A4GEAAKBgFzjuV p1FJYLqXrd4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/+onyohs+JH09B41b Y8i7RaWgSuOF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTSljf2YUeyxD KE8H5BQP1Gp2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMC BsAwHwYDVR0jBBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sobPjwf ftQ3CkzhMB4v3jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkGByqG SM44BAMDMAAwLQIUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4hBSW0 NevTFjMGECAQEwGDASMRAwDgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGjAJBgcqhkjO OAQDBC4wLAIUBvvHKiTVNIn3i7X9cySlhsgPWmwCFGZpGbxoWNGNsZ1SP9oUiA39yaG4 ``` -------------------------------- ### S/MIME Message Example 4.4.bin Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt Binary representation of an S/MIME message. ```text MIILDQYJKoZIhvcNAQcCoIIK/jCCCvoCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCB68wggIsMIIBlaADAgECAhBGNGvH gABWvBHTbi7EELOwMA0GCSqGSIb3DQEBBQUAMBIxEDAOBgNVBAMTB0NhcmxSU0EwHhcNOT kwOTE5MDEwODQ3WhcNMzkxMjMxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZVJTQTCBnzAN BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4IlzOY3Y9fXoh3Y5f06wBbtTg94Pt6vcfcd1KQ 0FLm0S36aGJtTSb6pYKfyX7PqCUQ8wgL6xUJ5GRPEsu9gyz8ZobwfZsGCsvu40CWoT9fcF BZPfXro1Vtlh/xl/yYHm+Gzqh0Bw76xtLHSfLfpVOrmZdwKmSFKMTvNXOFd0V18CAwEAAa OBgTB/MAwGA1UdEwEB/wQCMAAwDgYDRV0PAQH/BAQDAgbAMB8GA1UdIwQYMBaAFOngkCes eCB6mtNM8kI3TiKunji7MB0GA1UdDgQWBBR30rTRt0yKiqPORZ3O7DygOuP/UDAfBgNVHR EEGDAWgRRBbGljZVJTQUBleGFtcGxlLmNvbTANBgkqhkiG9w0BAQUFAAOBgQA+cEeoSMwT WI/KUXFrTjYYXQR+gLGNTczKo4/MfVbIvM9usxxZqSCqBYGoTiWtp3AUdS/1x5vRDulj0m S3xmZucyFU3/S6JV19SdOUayI2dHO4SuwvZO3TPdKnQsXoN4q0259n5L2f+f507+r57mNq 2D9LJQm12Bp2ruub20mwIjCCApswggJaoAMCAQICAQEwCQYHKoZIzjgEAzASMRAwDgYDVQ QDEwdDYXJsRFNTMB4XDTk5MDgxNjIyNTA1MFoXDTM5MTIzMTIzNTk1OVowEjEQMA4GA1UE AxMHQ2FybERTUzCCAbcwggErBgcqhkjOOAQBMIIBHgKBgQC2SRg+ikTBKXGUTAHEEsF6ec tUTasegfvGTLMOlAkG6wHUschxS8dFwFAlXZz82uRt0+KGSISCfboVlUoW9kbt3faY0rt+ ``` -------------------------------- ### TLS Client Connection with Bouncy Castle C# Source: https://context7.com/bcgit/bc-csharp/llms.txt Illustrates establishing a TLS client connection using Bouncy Castle's TlsClientProtocol. This example shows how to perform the TLS handshake, send an HTTP request, and receive a response over a secure connection. Custom TLS client authentication can be implemented in SimpleTlsClient and SimpleTlsAuthentication. ```csharp using Org.BouncyCastle.Tls; using Org.BouncyCastle.Tls.Crypto.Impl.BC; using Org.BouncyCastle.Security; using System; using System.IO; using System.Net.Sockets; using System.Text; // Custom TLS client implementation public class SimpleTlsClient : DefaultTlsClient { public SimpleTlsClient(BcTlsCrypto crypto) : base(crypto) { } public override TlsAuthentication GetAuthentication() { return new SimpleTlsAuthentication(); } } public class SimpleTlsAuthentication : TlsAuthentication { public TlsCredentials GetClientCredentials(CertificateRequest certificateRequest) => null; public void NotifyServerCertificate(TlsServerCertificate serverCertificate) { // Validate server certificate here Console.WriteLine($"Server presented {serverCertificate.Certificate.Length} certificate(s)"); } } // Connect to a TLS server using (TcpClient tcpClient = new TcpClient("example.com", 443)) using (NetworkStream networkStream = tcpClient.GetStream()) { // Create TLS client protocol in blocking mode TlsClientProtocol tlsProtocol = new TlsClientProtocol(networkStream); // Create crypto provider and TLS client BcTlsCrypto crypto = new BcTlsCrypto(new SecureRandom()); SimpleTlsClient tlsClient = new SimpleTlsClient(crypto); // Perform TLS handshake tlsProtocol.Connect(tlsClient); Console.WriteLine("TLS handshake completed"); // Send HTTP request over TLS Stream tlsStream = tlsProtocol.Stream; byte[] request = Encoding.ASCII.GetBytes("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"); tlsStream.Write(request, 0, request.Length); // Read response byte[] buffer = new byte[4096]; int bytesRead = tlsStream.Read(buffer, 0, buffer.Length); string response = Encoding.ASCII.GetString(buffer, 0, bytesRead); Console.WriteLine($"Response: {response.Substring(0, Math.Min(200, response.Length))}..."); // Close connection tlsProtocol.Close(); } ``` -------------------------------- ### S/MIME Message Example 4.2.bin Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt Binary representation of an S/MIME message. ```text MIIDUgYJKoZIhvcNAQcCoIIDQzCCAz8CAQExCzAJBgUrDgMCGgUAMCsGCSqGSIb3DQEHAa AeBBxUaGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQuoIICMDCCAiwwggGVoAMCAQICEEY0 a8eAAFa8EdNuLsQQs7AwDQYJKoZIhvcNAQEFBQAwEjEQMA4GA1UEAxMHQ2FybFJTQTAeFw 05OTA5MTkwMTA4NDdaFw0zOTEyMzEyMzU5NTlaMBMxETAPBgNVBAMTCEFsaWNlUlNBMIGf MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgiXM5jdj19eiHdjl/TrAFu1OD3g+3q9x9x3 UpDQUubRLfpoYm1NJvqlgp/Jfs+oJRDzCAvrFQnkZE8Sy72DLPxmhvB9mwYKy+7jQJahP1 9wUFk99eujVW2WH/GX/Jgeb4bOqHQHDvrG0sdJ8t+lU6uZl3AqZIUoxO81c4V3RXXwIDAQ ABo4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBsAwHwYDVR0jBBgwFoAU6eCQ J6x4IHqa00zyQjdOIq6eOLswHQYDVR0OBBYEFHfStNG3TIqKo85Fnc7sPKA64/9QMB8GA1 UdEQQYMBaBFEFsaWNlUlNBQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUAA4GBAD5wR6hI zBNYj8pRcWtONhhdBH6AsY1NzMqjj8x9Vsi8z26zHFmpIKoFgahOJa2ncBR1L/XHm9EO6W PSZLfGZm5zIVTf9LolXX1J05RrIjZ0c7hK7C9k7dM90qdCxeg3irTbn2fkvZ/5/nTv6vnu Y2rYP0slCbXYGnau65vbSbAiMYHLMIHIAgEBMCYwEjEQMA4GA1UEAxMHQ2FybFJTQQIQRj Rrx4AAVrwR024uxBCzsDAJBgUrDgMCGgUAMA0GCSqGSIb3DQEBAQUABIGALyOC0vMJX7gM WOtOnb+JmoHldcSRPdPQ1Xu21f6UoYqs48SE9c1gTieV9s8AhnZ1Pyvw59QCZ6f1x40WBK WztefZMvAk7+cgRNWfB8VTJPrOAR0PFxOnKpWdK+QDlRQL6TkNus5unJ4M6JjmVRPUaG/Q B9eisWJM44+v/eDVXcc= ``` -------------------------------- ### Install BouncyCastle via .NET Core CLI Source: https://github.com/bcgit/bc-csharp/blob/master/README.md Use this command with the .NET Core CLI to add the BouncyCastle.Cryptography NuGet package to your project. ```bash dotnet add package BouncyCastle.Cryptography ``` -------------------------------- ### Base64 Encoded File Examples Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt Sample data formats used by the extraction utility, including file markers and Base64 encoded content. ```text |* Section 2.1 |>ExContent.bin |VGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50Lg== |AlicePrivDSSSign.pri |MIIBSwIBADCCASsGByqGSM44BAEwggEeAoGBAIGNze2D6gqeOT7CSCij5EeT3Q7XqA7sU8 |WrhAhP/5Thc0h+DNbzREjR/p+vpKGJL+HZMMg23j+bv7dM3F9piuR10DcMkQiVm96nXvn8 |9J8v3UOoi1TxP7AHCEdNXYjDw7Wz41UIddU5dhDEeL3/nbCElzfy5FEbteQJllzzflvbAh |UA4kemGkVmuBPG2o+4NyErYov3k80CgYAmONAUiTKqOfs+bdlLWWpMdiM5BAI1XPLLGjDD |HlBd3ZtZ4s2qBT1YwHuiNrhuB699ikIlp/R1z0oIXks+kPht6pzJIYo7dhTpzi5dowfNI4 |W4LzABfG1JiRGJNkS9+MiVSlNWteL5c+waYTYfEX/Cve3RUP+YdMLRgUpgObo2OQQXAhUA |u0RG0aXJRgcu0P561pIH8JqFiT8= |AlicePrivRSASign.pri |MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOCJczmN2PX16Id2OX9OsA |W7U4PeD7er3H3HdSkNBS5tEt+mhibU0m+qWCn8l+z6glEPMIC+sVCeRkTxLLvYMs/GaG8H |2bBgrL7uNAlqE/X3BQWT3166NVbZYf8Zf8mB5vhs6odAcO+sbSx0ny36VTq5mXcCpkhSjE |7zVzhXdFdfAgMBAAECgYAApAPDJ0d2NDRspoa1eUkBSy6K0shissfXSAlqi5H3NvJ11ujN |FZBgJzFHNWRNlc1nY860n1asLzduHO4Ovygt9DmQbzTYbghb1WVq2EHzE9ctOV7+M8v/Ke ``` -------------------------------- ### Example 4.9 .eml S/MIME Message Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt This snippet shows a sample S/MIME signed message in .eml format. It includes headers like To, From, Subject, Message-ID, Date, and Content-Type, along with the base64 encoded signed data. ```eml MIME-Version: 1.0 To: User2@examples.com From: aliceDsp@examples.com Subject: Example 4.9 Message-ID: <021031164540300.304@examples.com> Date: Thu, 31 Oct 2002 16:45:14 -0300 Content-Type: application/pkcs7-mime; smime-type=signed-data; name=smime.p7m Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=smime.p7m MIIIdjBJKoZIhvcNAQcCoIIIdjCCB+ACAIExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCAuAwggLcMIICm6ADAgECAgIAyDAJ BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMj MxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYwggErBgcqhkjOOAQBMIIBHgKB gQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2T DINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0 dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm +H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX ``` -------------------------------- ### Generate Dilithium Key Pair and Sign/Verify Message Source: https://context7.com/bcgit/bc-csharp/llms.txt Demonstrates generating a Dilithium key pair, signing a message with the private key, and verifying the signature with the public key. Requires Bouncy Castle PQC libraries. Available parameter sets include Dilithium2, Dilithium3, and Dilithium5. ```csharp using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium; using Org.BouncyCastle.Security; using System; using System.Text; // Create Dilithium key pair generator DilithiumKeyPairGenerator keyGen = new DilithiumKeyPairGenerator(); // Initialize with Dilithium3 parameters (security level 3) DilithiumKeyGenerationParameters keyGenParams = new DilithiumKeyGenerationParameters( new SecureRandom(), DilithiumParameters.Dilithium3 ); keyGen.Init(keyGenParams); // Generate key pair AsymmetricCipherKeyPair keyPair = keyGen.GenerateKeyPair(); DilithiumPublicKeyParameters publicKey = (DilithiumPublicKeyParameters)keyPair.Public; DilithiumPrivateKeyParameters privateKey = (DilithiumPrivateKeyParameters)keyPair.Private; Console.WriteLine($"Public key size: {publicKey.GetEncoded().Length} bytes"); Console.WriteLine($"Private key size: {privateKey.GetEncoded().Length} bytes"); // Create signer DilithiumSigner signer = new DilithiumSigner(); // Sign message byte[] message = Encoding.UTF8.GetBytes("Message to sign with post-quantum algorithm"); signer.Init(true, privateKey); byte[] signature = signer.GenerateSignature(message); Console.WriteLine($"Signature size: {signature.Length} bytes"); // Verify signature signer.Init(false, publicKey); bool isValid = signer.VerifySignature(message, signature); Console.WriteLine($"Signature valid: {isValid}"); // Available Dilithium parameter sets: // - DilithiumParameters.Dilithium2 (Security level 2) // - DilithiumParameters.Dilithium3 (Security level 3) // - DilithiumParameters.Dilithium5 (Security level 5) // Output: // Public key size: 1952 bytes // Private key size: 4000 bytes // Signature size: 3293 bytes // Signature valid: True ``` -------------------------------- ### Manage OpenPGP Public Key Rings Source: https://context7.com/bcgit/bc-csharp/llms.txt Shows how to load, inspect, and search for keys within an OpenPGP public key ring. ```csharp using Org.BouncyCastle.Bcpg.OpenPgp; using System; using System.IO; // Load public key ring from file or bytes byte[] publicKeyRingData = File.ReadAllBytes("public-keyring.gpg"); PgpPublicKeyRing keyRing = new PgpPublicKeyRing(publicKeyRingData); // Get the master (primary) public key PgpPublicKey masterKey = keyRing.GetPublicKey(); Console.WriteLine($"Master Key ID: {masterKey.KeyId:X16}"); Console.WriteLine($"Algorithm: {masterKey.Algorithm}"); Console.WriteLine($"Created: {masterKey.CreationTime}"); Console.WriteLine($"Is Master Key: {masterKey.IsMasterKey}"); Console.WriteLine($"Bit Strength: {masterKey.BitStrength}"); // Enumerate user IDs foreach (string userId in masterKey.GetUserIds()) { Console.WriteLine($"User ID: {userId}"); } // Get all public keys (master + subkeys) foreach (PgpPublicKey key in keyRing.GetPublicKeys()) { Console.WriteLine($"Key ID: {key.KeyId:X16}, Master: {key.IsMasterKey}"); } // Find key by key ID long targetKeyId = 0x1234567890ABCDEF; PgpPublicKey foundKey = keyRing.GetPublicKey(targetKeyId); if (foundKey != null) { Console.WriteLine($"Found key: {foundKey.KeyId:X16}"); } // Find key by fingerprint byte[] fingerprint = masterKey.GetFingerprint(); PgpPublicKey keyByFingerprint = keyRing.GetPublicKey(fingerprint); // Join two copies of the same certificate (e.g., local + key server) // PgpPublicKeyRing merged = PgpPublicKeyRing.Join(localKeyRing, serverKeyRing); // Export key ring byte[] exportedKeyRing = keyRing.GetEncoded(); ``` -------------------------------- ### Generate ML-KEM Key Pair and Encapsulate/Decapsulate Secret Source: https://context7.com/bcgit/bc-csharp/llms.txt Demonstrates generating an ML-KEM key pair, encapsulating a shared secret using the public key, and then decapsulating it using the private key. Requires Bouncy Castle PQC libraries. Available parameter sets include ML_KEM_512, ML_KEM_768, and ML_KEM_1024. ```csharp using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Kems.MLKem; using Org.BouncyCastle.Security; using System; // Create ML-KEM key pair generator MLKemKeyPairGenerator keyGen = new MLKemKeyPairGenerator(); // Initialize with ML-KEM-768 parameters (security level 3) MLKemKeyGenerationParameters keyGenParams = new MLKemKeyGenerationParameters( new SecureRandom(), MLKemParameters.ML_KEM_768 ); keyGen.Init(keyGenParams); // Generate key pair (recipient) AsymmetricCipherKeyPair keyPair = keyGen.GenerateKeyPair(); MLKemPublicKeyParameters publicKey = (MLKemPublicKeyParameters)keyPair.Public; MLKemPrivateKeyParameters privateKey = (MLKemPrivateKeyParameters)keyPair.Private; Console.WriteLine($"Public key size: {publicKey.GetEncoded().Length} bytes"); Console.WriteLine($"Private key size: {privateKey.GetEncoded().Length} bytes"); // Sender: Encapsulate shared secret using recipient's public key MLKemGenerator kemGenerator = new MLKemGenerator(new SecureRandom()); ISecretWithEncapsulation encapsulation = kemGenerator.GenerateEncapsulated(publicKey); byte[] ciphertext = encapsulation.GetEncapsulation(); byte[] senderSecret = encapsulation.GetSecret(); Console.WriteLine($"Ciphertext size: {ciphertext.Length} bytes"); Console.WriteLine($"Shared secret size: {senderSecret.Length} bytes"); // Recipient: Decapsulate shared secret using private key MLKemExtractor kemExtractor = new MLKemExtractor(privateKey); byte[] recipientSecret = kemExtractor.ExtractSecret(ciphertext); // Verify both parties have the same shared secret bool secretsMatch = CompareArrays(senderSecret, recipientSecret); Console.WriteLine($"Shared secrets match: {secretsMatch}"); // The shared secret can now be used as a symmetric key Console.WriteLine($"Shared secret: {BitConverter.ToString(senderSecret).Replace("-", "").Substring(0, 64)}..."); // Available ML-KEM parameter sets: // - MLKemParameters.ML_KEM_512 (Security level 1) // - MLKemParameters.ML_KEM_768 (Security level 3) // - MLKemParameters.ML_KEM_1024 (Security level 5) static bool CompareArrays(byte[] a, byte[] b) { if (a.Length != b.Length) return false; for (int i = 0; i < a.Length; i++) if (a[i] != b[i]) return false; return true; } // Output: // Public key size: 1184 bytes // Private key size: 2400 bytes // Ciphertext size: 1088 bytes // Shared secret size: 32 bytes // Shared secrets match: True ``` -------------------------------- ### ASN.1 Octet String Representation Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt Example of an ASN.1 OCTET STRING structure containing binary data. ```text 723 04 128: OCTET STRING : 2F 23 82 D2 F3 09 5F B8 0C 58 EB 4E : 9D BF 89 9A 81 E5 75 C4 91 3D D3 D0 : D5 7B B6 D5 FE 94 A1 8A AC E3 C4 84 : F5 CD 60 4E 27 95 F6 CF 00 86 76 75 : 3F 2B F0 E7 D4 02 67 A7 F5 C7 8D 16 : 04 A5 B3 B5 E7 D9 32 F0 24 EF E7 20 : 44 D5 9F 07 C5 53 24 FA CE 01 1D 0F : 17 13 A7 2A 95 9D 2B E4 03 95 14 0B : E9 39 0D BA CE 6E 9C 9E 0C E8 98 E6 : 55 13 D4 68 6F D0 07 D7 A2 B1 62 4C : E3 8F AF FD E0 D5 5D C7 : } ``` -------------------------------- ### Extract S/MIME Binaries with Perl Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt A Perl script that parses the document for lines starting with '|' to extract and decode Base64 binary data into files. ```perl #!/usr/bin/perl # CMS Samples extraction program. v 1.1 ``` -------------------------------- ### Perl Base64 File Extraction Script Source: https://github.com/bcgit/bc-csharp/blob/master/crypto/test/data/rfc4134/rfc4134.txt The main logic for reading input, managing file handles, and decoding Base64 content. It expects specific markers in the input stream to start and end file writing. ```perl # Get all the input as an array of lines @AllIn = (); while () { push(@AllIn, $_) } $Base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr' . 'stuvwxyz0123456789+/='; $LineCount = 0; $CurrFile = ''; foreach $Line (@AllIn) { $LineCount++; # Keep the line counter for error messages $Line =~ s/^\s*//; # Get rid of leading whitespace chomp($Line); # Get rid of CR or CRLF at the end of the line if(substr($Line, 0, 1) ne '|') { next } # Not a special line elsif(substr($Line, 1, 1) eq '*') { next } # It is a comment elsif(substr($Line, 1, 1) eq '>') { &StartNewFile(substr($Line, 2)) } # Start a new file elsif(substr($Line, 1, 1) eq '<') { &EndCurrFile(substr($Line, 2)) } # End the current file else { &DoBase64(substr($Line, 1)) } # It is a line of Base64 } sub StartNewFile { $TheNewFile = shift(@_); if($CurrFile ne '') { die "Was about to start a new file at " . "line $LineCount, but the old file, $CurrFile, was open\n" } open(OUT, ">$TheNewFile") or die "Could not open $TheNewFile for writing: $!\n"; binmode(OUT); # This is needed for Windows, is a noop on Unix $CurrFile = $TheNewFile; $LeftOver = 0; # Amount left from previous Base64 character $NextPos = 0; # Bit position to start the next Base64 character # (bits are numbered 01234567) $OutString = ''; # Holds the text going out to the file } sub EndCurrFile { $FileToEnd = shift(@_); if($CurrFile ne $FileToEnd) { die "Was about to close " . "$FileToEnd at line $LineCount, but that name didn't match " . "the name of the currently open file, $CurrFile\n" } print OUT $OutString; close(OUT); $CurrFile = ''; } sub DoBase64 { $TheIn = shift(@_); if($CurrFile eq '') { die "Got some Base64 at line $LineCount, " . "but appear to not be writing to any particular file.\n" } @Chars = split(//, $TheIn); # Make an array of the characters foreach $ThisChar (@Chars) { # $ThisVal is the position in the string and the Base64 value $ThisVal = index($Base64Chars, $ThisChar); if($ThisVal == -1) { die "At line $LineCount, found the " . "character $ThisChar, which is not a Base64 character\n" } if($ThisVal == 64) { last } # It is a "=", so we're done if ($NextPos == 0 ) { # Don't output anything, just fill the left of $LeftOver $LeftOver = $ThisVal * 4; $NextPos = 6; } elsif ($NextPos == 2) { # Add $ThisVal to $LeftOver, output, and reset $OutString .= chr($LeftOver + $ThisVal); $LeftOver = 0; $NextPos = 0; } elsif ($NextPos == 4) { # Add upper 4 bits of $ThisVal to $LeftOver and output $Upper4 = ($ThisVal & 60); $OutString .= chr($LeftOver + ($Upper4/4)); $LeftOver = (($ThisVal - $Upper4) * 64); $NextPos = 2; } elsif ($NextPos == 6) { # Add upper 2 bits of $ThisVal to $LeftOver and output $Upper2 = ($ThisVal & 48); $OutString .= chr($LeftOver + ($Upper2/16)); $LeftOver = (($ThisVal - $Upper2) * 16); $NextPos = 4; } else { die "\$NextPos has an illegal value: $NextPos." } } } ```