开发者

C#使用应用RSA和ECC进行数字签名和签名验证的示例详解

目录
  • 基本概念
  • RSA 算法示例
    • 1. 密钥生成与保存
    • 2. 加密与解密
    • 3. 数字签名与验证
  • 椭圆曲线数字签名算法 (ECDSA) 示例
    • 1. 密钥生成与保存
    • 2. 数字签名与验证
  • 主程序示例 (Program.cs)
    • 运行环境要求
      • 关于数字证书

        基本概念

        1. RSA 通常用于加密少量数据(如对称密钥)和数字签名。直接使用RSA加密大量数据效率较低,更常见的是使用RSA加密一个随机生成的对称密钥,然后用对称密钥加密实际数据。
        2. 椭圆曲线算法 (ECC) 在相同的安全级别下,密钥长度比RSA短得多,因此在性能和存储方面有优势。它主要用于数字签名 (ECDSA)密钥协商 (ECDH),也可以进行加密(通过结合ECDH和对称加密)。
        3. 密钥保存:在实际应用中,私钥的保存至关重要。通常会使用更安全的方式,如Windows证书存储、硬件安全模块 (HSM) 或加密存储在文件中。这里提供的文件保存示例仅用于演示目的,不应直接用于生产环境。
        4. 异常处理:为了代码简洁,示例中的异常处理可能不够完善,实际应用中应加强。

        RSA 算法示例

        RSA算法在.NET中主要通过RSACryptoServiceProvider (旧版) 或 RSA (推荐,跨平台) 类实现。这里我们使用 RSA 类。

        1. 密钥生成与保存

        using System.Security.Cryptography;
        
        namespace RsaEcdsaCryption
        {
            public class RsaHelper
            {
                // 生成RSA密钥对并保存到文件
                public static void GenerateAndSave编程RsaKeys(string privateKeyPath, string publicKeyPath)
                {
                    using (RSA rsa = RSA.Create())
                    {
                        // 设置密钥长度 (例如,2048位)
                        rsa.KeySize = 2048;
        
                        // 导出私钥 (包含所有参数)
                        string privateKeyXML = rsa.ToXmlString(true);
                        File.WriteAllText(privateKeyPath, privateKeyXml);
                        
                        // 导出公钥 (只包含模数和指数)
                        string publicKeyXml = rsa.ToXmlString(false);
                        File.WriteAllText(publicKeyPath, publicKeyXml);
        
                        Console.WriteLine($"RSA 私钥已保存到: {privateKeyPath}");
                        Console.WriteLine($"RSA 公钥已保存到: {publicKeyPath}");
                    }
                }
        
                // 从文件加载RSA私钥
                public static RSA LoadRsaPrivateKey(string privateKeyPath)
                {
                    RSA rsa = RSA.Create();
                    string privateKeyXml = File.ReadAllText(privateKeyPath);
                    rsa.FromXmlString(privateKeyXml);            
                    return rsa;
                }
        
                // 从文件加载RSA公钥
                public static RSA LoadRsaPublicKey(string publicKeyPath)
                {
                    RSA rsa = RSA.Create();
                    string publicKeyXml = File.ReadAllText(publicKeyPath);
                    rsa.FromXmlString(publicKeyXml);
                    return rsa;
                }
            }
        }
        

        2. 加密与解密

        RSA加密通常是公钥加密,私钥解密。

        using System.Security.Cryptography;
        using System.Text;
        
        namespace RsaEcdsaCryption
        {
            public class RsaEncryptionDecryption
            {
                // 使用RSA公钥加密数据
                public static byte[] Encrypt(byte[] data, RSA publicKeyRsa)
                {
                    // OEAP填充模式推荐用于加密,提供更好的安全性
                    return publicKeyRsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
                }
        
                // 使用RSA私钥解密数据
                public static byte[] Decrypt(byte[] encryptedData, RSA privateKeyRsa)
                {
                    // OEAP填充模式推荐用于解密
                    return privateKeyRsa.Decrypt(encryptedData, RSAEncryptionPadding.OaepSHA256);
                }
        
                public static void RunEncryptionDecryptionExample(RSA publicKey, RSA privateKey)
                {
                    string originalText = "这是一段要使用RSA加密的秘密消息。";
                    byte[] originalBytes = Encoding.UTF8.GetBytes(originalText);
        
                    Console.WriteLine($"\n原始消息: {originalText}");
        
                    // 加密
                    byte[] encryptedBytes = Encrypt(originalBytes, publicKey);
                    Console.WriteLine($"加密后 (Base64): {Convert.ToBase64String(encryptedBytes)}");
        
                    // 解密
                    byte[] decryptedBytes = Decrypt(encryptedBytes, privateKey);
                    string decryptedText = Encoding.UTF8.GetString(decryptedBytes);
                    Console.WriteLine($"解密后: {decryptedText}");
        
                    Console.WriteLine($"加密/解密 {(originalText == decryptedText ? "成功" : "失败")}");
                }
            }
        }
        
        

        3. 数字签名与验证

        RSA签名通常使用私钥签名,公钥验证。

        using System.Security.Cryptography;
        using System.Text;
        
        public class RsaSignature
        {
            // 使用RSA私钥对数据进行签名
            public static byte[] SignData(byte[] data, RSA privateKeyRsa)
            {
                // 选择哈希算法 (例如,SHA256) 和填充模式 (PSS推荐用于签名)
                return privateKeyRsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
            }
        
            // 使用RSA公钥验证签名
            public static bool VerifySignature(byte[] data, byte[] signature, RSA publicKeyRsa)
            {
                // 选择哈希算法和填充模式与签名时一致
                return publicKeyRsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
            }
        
            public static void RunSignatureExample(RSA publicKey, RSA privateKey)
            {
                string messageToSign = "这是一段要进行数字签名的消息。";
                byte[] messageBytes = Encoding.UTF8.GetBytes(messageToSign);
        
                Console.WriteLine($"\n待签名消息: {messageToSign}");
        
                // 签名
                byte[] signature = SignData(messageBytes, privateKey);
                Console.WriteLine($"生成签名 (Base64): {Convert.ToBase64String(signature)}");
        
                // 验证签名
                bool isValid = VerifySignature(messageBytes, signature, publicKey);
                Console.WriteLine($"签名验证结果: {(isValid ? "有效" : "无效")}");
        
                // 尝试篡改数据后验证签名
                Console.WriteLine("\n尝试篡改数据后验证签名...");
                byte[] tamperedMessageBytes = Encoding.UTF8.GetBytes("这是一段被篡改的消息。");
                bool isTamperedValid = VerifySignature(tamperedMessageBytes, signature, publicKey);
                Console.WriteLine($"篡改后签名验证结果: {(isTamperedValid ? "有效" : "无效")}");
            }
        }
        

        椭圆曲线数字签名算法 (ECDSA) 示例

        ECDSA在.NET中主要通过 ECDsa 类实现。

        1. 密钥生成与保存

        ECDSA密钥通常是公私钥对,公钥可以从私钥派生。

        using System.Security.Cryptography;
        
        public class EcdsaHelper
        {
            // 生成ECDSA密钥对并保存到文件
            public static void GenerateAndSaveEcdsaKeys(string privateKeyPath, string publicKeyPath)
            {
                // 选择一个命名曲线,例如 P-256 (secp256r1)
                using (ECDsa ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256))
                {
                    // 导出私钥(PKCS#8格式,PEM编码)
                    string privateKeyPem = ecdsa.ExportPkcs8PrivateKeyPem();
                    File.WriteAllText(privateKeyPath, privateKeyPem);
        
                    // 导出公钥(SubjectPublicKeyInfo格式,PEM编码)
                    string publicKeyPem = ecdsa.ExportSubjectPublicKeyInfoPem();
                    File.WriteAllText(publicKeyPath, publicKeyPem);
        
                    Console.WriteLine($"ECDSA 私钥已保存到: {privateKeyPath}");
                    Console.WriteLine($"ECDSA 公钥已保存到: {publicKeyPath}");
                }
            }
        
            // 从文件加载ECDSA私钥
            public static ECDsa LoadEcdsaPrivateKey(string privateKeyPath)
            {
         android       ECDsa ecdsa = ECDsa.Create();
                string privateKeyPem = File.ReadAllText(privateKeyPath);
                ecdsa.ImportFromPem(privateKeyPem); // 或 ImportPkcs8PrivateKeyPem
                return ecdsa;
            }
        
            // 从文件加载ECDSA公钥
            public static ECDsa LoadEcdsaPublicKey(string publicKeyPath)
            {
                ECDsa ecdsa = ECDsa.Create();
                string publicKeyPem = File.ReadAllText(publicKeyPath);
                ecdsa.ImportFromPem(publicKeyPem); // 或 ImportSubjectPublicKeyInfoPem
                return ecdsa;
            }
        }
        

        2. 数字签名与验证

        ECDSA主要用于签名,不支持直接的加密/解密操作(需要结合ECDH和对称加密才能实现)。

        using System.Security.Cryptography;
        using System.Text;
        
        public class EcdsaSignature
        {
            // 使用ECDSA私钥对数据进行签名
            public static byte[] SignData(byte[] data, ECDsa privateKeyEcdsa)
            {
                // 选择哈希算法 (例如,SHA256)
                return privateKeyEcdsa.SignData(data, HashAlgorithmName.SHA256);
            }
        
            // 使用ECDSA公钥验证签名
            public static bool VerifySignature(byte[] data, byte[] signature, ECDsa publicKeyEcdsa)
            {
                // 选择哈希算法与签名时一致
                return publicKeyEcdsa.VerifyData(data, signature, HashAlgorithmName.SHA256);
            }
        
            public static void RunSignatureExample(ECDsa publicKey, ECDsa privateKey)
            {
                string messageToSign = "这是一段要使用ECDSA进行数字签名的消息。";
                byte[] messageBytes = Encoding.UTF8.GetBytes(messageToSign);
        
                Console.WriteLine($"\n待签名消息: {messageToSign}");
        
                // 签名
                byte[] signature = SignData(messageBytes, privateKey);
                Console.WriteLine($"生成签名 (Base64): {Convert.ToBase64String(signature)}");
        
                // 验证签名
                bool isValid = VerifySignature(messageBytes, signature, publicKey);
                Console.WriteLine($"签名验证结果: {(isValid ? "有效" : "无效")}");
        
                // 尝试篡改数据后验证签名
                Console.WriteLine("\n尝试篡改数据后验证签名...");
                byte[] tamperedMessageBytes = Encoding.UTF8.GetBytes("这是一段被篡改的消息。");
                bool isTamperedValid = VerifySignature(tamperedMessageBytes, signature, publicKey);
                Console.WriteLine($"篡改后签名验证结果: {(isTamperedValid ? "有效" : "无效")}");
            }
        }
        

        主程序示例 (Program.cs)

        将上述类集成到Program.cs中,演示如何使用它们。

        using System;
        using System.IO;
        using System.Security.Cryptography;
        
        public class Program
        {
            public static void Main(string[] args)
            {
                // 定义密钥文件路径
                string rsaPrivateKeyPath = "rsa_private_key.xml";
                string rsaPublicKeyPath = "rsa_public_key.xml";
                string ecdsaPrivateKeyPath = "ecdsa_private_key.pem";
                string ecdsaPublicKeyPath = "ecdsa_public_key.pem";
        
                Console.WriteLine("--- RSA 示例 ---");
        
                // RSA 密钥生成与保存
                RsaHelper.GenerateAndSaveRsaKeys(rsaPrivateKeyPath, rsaPublicKeyPath);
                RSA rsaPublicKey = RsaHelper.LoadRsaPublicKey(rsaPublicKeyPath);
                RSA rsaPrivateKey = RsaHelper.LoadRsaPrivateKey(rsaPrivateKeyPath);
        
                // RSA 加密与解密
                RsaEncryptionDecryption.RunEncryptionDecryptionExample(rsaPublicKey, rsaPrivateKey);
        
                // RSA 数字签名与验证
                RsaSignature.RunSignatureExample(rsaPublicKey, rsaPrivateKey);
        
                Console.WriteLine("\n--- ECDSA 示例 ---");
        
                // ECDSA 密钥生成与保存
                EcdsaHelper.GenerateAndSaveEcdsaKeys(ecdsaPrivateKeyPath, ecdsaPublicKeyPath);
                ECDsa ecdsaPublicKey = EcdsaHelper.LoadEcdsaPublicKey(ecdsaPublicKeyPath);
                ECDsa ecdsaPrivateKey = EcdsaHelper.LoadEcdsaPrivateKey(ecdsaPrivateKeyPath);
        
                // ECDSA 数字签名与验证
                EcdsaSignature.RunSignatureExample(ecdsaPublicKey, ecdsaPrivateKey);
        
                // 清理生成的密钥文件 (可选)
                // File.Delete(rsaPrivateKeyPath);
                // File.Delete(rsaPublicKeyPath);
                // File.Delete(ecdsaPrivateKeyPath);
                // File.Delete(ecdsaPublicKeyPath);
        
                Console.WriteLine("\n所有示例运行完毕。");
                Console.ReadKey();
            }
        }
        

        运行环境要求

        • .NET Core 3.1 或更高版本 / .NET 5.0 或更高版本RSA.Create(), ECDsa.Create(ECCurve.NamedCurves.nistP256), ExportPkcs8PrivateKeyPem(), ExportSubjectPublicKeyInfoPem(), ImportFromPem() 等方法需要较新的.NET版本支持。如果您使用的是较旧的.NET Framework,可能需要调整为 RSACryptoServiceProviderECDiffieHellmanCng/ECDsaCng,但它们的使用方式有所不同,且通常更推荐使用新的API。

        关于数字证书

        数字证书是编程公钥基础设施 (PKI) 的核心组成部分,它将公钥与实体的身份绑定在一起,并由可信的第三方(证书颁发机构 C A)进行签名。上述示例只是生成了原始的公钥和私钥文件,并没有涉及证书的生成和使用。

        如果需要处理数字证书,C# 提供了 X509Certificate2 类来加载、创建和管理证书。通常涉及:

        1. 加载证书:从文件 (.pfx, .cer) 或证书存储区加载。
        2. 提取公钥:从 X509Certificate2 对象中获取 RSAECDsa 公钥。
        3. 使用私钥:如果证书包含私钥,可以直接用它进行签名或解密。

        示例:

        // 假设你有一个带有私钥的PFX文件
        // string certPath = "myCert.pfx";
        // string certPassword = "myPassword";
        
        // using (X509Certificate2 cert = new X509Certificate2(certPath, certPassword))
        // {
        //     // 获取公钥用于验证
        //     RSA rsaPublicKeyFromCert = cert.GetRSAPublicKey(); // 或 GetECDsaPublicKey()
        //     // 获取私钥用于签名
        //     RSA rsaPrivateKeyFromCert = cert.GetRSAPrivateKey(); // 或 GetECDsaPandroidrivateKey()
        
        //     // 然后就可以用这些密钥进行签名/验证或加密/解密
        // }
        

        程序运行效果如下:

        C#使用应用RSA和ECC进行数字签名和签名验证的示例详解

        以上就是C#使用应用RSA和ECC进行数字签名和签名验证的示例详解的详细内容,更多关于C# RpythonSA和ECC数字签名和签名验证的资料请关注编程客栈(www.devze.com)其它相关文章!

        0

        上一篇:

        下一篇:

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        最新开发

        开发排行榜