日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.NET Core加解密实战系列之——消息摘要与数字签名算法

發布時間:2023/12/4 asp.net 78 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET Core加解密实战系列之——消息摘要与数字签名算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介

加解密現狀,編寫此系列文章的背景:

  • 需要考慮系統環境兼容性問題(Linux、Windows)

  • 語言互通問題(如C#、Java等)(加解密本質上沒有語言之分,所以原則上不存在互通性問題)

  • 網上資料版本不一、或不全面

  • .NET官方庫密碼算法提供不全面,很難針對其他語言(Java)進行適配

本系列文章主要介紹如何在 .NET Core 中使用非對稱加密算法、編碼算法、消息摘要算法、簽名算法、對稱加密算法、國密算法等一系列算法,如有錯誤之處,還請大家批評指正。

本系列文章旨在引導大家能快速、輕松的了解接入加解密,乃至自主組合搭配使用BouncyCastle密碼術包中提供的算法。

本文中代碼示例僅列舉了比較常見的使用方式(BouncyCastle中提供的算法遠不止這些),另外算法DSA和ECDSA我們未在項目中使用過,代碼組合性非常多,因此文中部分代碼僅供參考。

本系列代碼項目地址:https://github.com/fuluteam/ICH.BouncyCastle.git

上一篇文章《.NET Core加解密實戰系列之——RSA非對稱加密算法》:https://www.cnblogs.com/fulu/p/13100471.html

功能依賴

BouncyCastle(https://www.bouncycastle.org/csharp) 是一個開放源碼的輕量級密碼術包;它支持大量的密碼術算法,它提供了很多 .NET Core標準庫沒有的算法。

支持 .NET 4,.NET Standard 1.0-2.0,WP,Silverlight,MonoAndroid,Xamarin.iOS,.NET Core

功能依賴
Portable.BouncyCastlePortable.BouncyCastle ? 1.8.5

消息摘要算法

消息摘要算法分為三類:

  • MD 2/4/5(Message Digest Algorithm 2/4/5):消息摘要算法 MD2、MD4、MD5

  • SHA(Secure Hash Algorithm):安全散列算法

  • MAC(Message Authentication Code):消息認證碼

MD算法

MD消息摘要算法,一種被廣泛使用的密碼散列函數,可以產生出一個128位(16字節)的散列值(hash value),用于確保信息傳輸完整一致。

家族發展史

  • MD2算法:

    1989年,著名的非對稱算法RSA發明人之一麻省理工學院教授羅納德·李維斯特開發了MD2算法。這個算法首先對信息進行數據補位,使信息的字節長度是16的倍數。再以一個16位的檢驗和做為補充信息追加到原信息的末尾。最后根據這個新產生的信息計算出一個128位的散列值,MD2算法由此誕生。

  • MD4算法:

    1990年,羅納德·李維斯特教授開發出較之MD2算法有著更高安全性的MD4算法。MD4算法對后續消息摘要算法起到了推動作用,許多比較有名的消息摘要算法都是在MD4算法的基礎上發展而來的,如MD5、SHA-1、RIPE-MD和HAVAL算法等。

  • MD5算法:

    1991年,繼MD4算法后,羅納德·李維斯特教授開發了MD5算法,用以取代MD4算法。這套算法的程序在 RFC 1321 標準中被加以規范。MD5算法經MD2、MD3和MD4算法發展而來,算法復雜程度和安全強度大大提高,MD算法的最終結果都是產生一個128位的信息摘要。這也是MD系列算法的特點。

    1996年,該算法被證實存在弱點,可以被加以破解,對于需要高度安全性的數據,專家一般建議改用其他算法,如SHA-2。

    2004年,證實MD5算法無法防止碰撞(collision),因此不適用于安全性認證,如SSL公開密鑰認證或是數字簽名等用途。

應用場景

消息摘要算法是不可逆的,所以信息摘要場景主要被用來驗證信息的完整性,防止信息被篡改,主要場景如下:

  • 驗簽:對要發送的數據做MD5(一般加slat)MD5值和數據一同發送,接收方接受數據做同樣的MD5計算,比較MD5值是否一致

  • 密碼保護:比如用戶密碼存儲上,一般都是存儲MD5值,更高一級的涉及是針對每個用戶生成一個隨機的slat,然后進MD5(passport + slat)計算,將這個值存儲到DB中

代碼實現

MD5
public static class MD5{/// <summary>/// 哈希計算(使用BouncyCastle)/// </summary>/// <param name="s"></param>/// <returns></returns>public static byte[] Compute(string s){if (string.IsNullOrEmpty(s)){throw new ArgumentNullException(nameof(s));}var digest = new MD5Digest();var resBuf = new byte[digest.GetDigestSize()];var input = Encoding.UTF8.GetBytes(s);digest.BlockUpdate(input, 0, input.Length);digest.DoFinal(resBuf, 0);return resBuf;}/// <summary>/// 哈希計算(不使用BouncyCastle)/// </summary>/// <param name="s"></param>/// <returns></returns>public static byte[] Compute2(string s){if (string.IsNullOrEmpty(s)){throw new ArgumentNullException(nameof(s));}using (var md5 = System.Security.Cryptography.MD5.Create()){return md5.ComputeHash(Encoding.UTF8.GetBytes(s));}}}

示例代碼

private static void MD5Sample(){var s = "hello md5";Console.WriteLine(s);var resBytes1 = MD5.Compute("hello md5");var resBytes2 = MD5.Compute2("hello md5");var a1 = BitConverter.ToString(resBytes1).Replace("-", "");Console.WriteLine($"通過BitConverter.ToString轉換得到結果:{a1}");var a2 = Hex.ToHexString(resBytes1).ToUpper();Console.WriteLine($"通過Hex.ToHexString轉換得到結果:{a2}");var a3 = Hex.ToHexString(resBytes2).ToUpper();Console.WriteLine($"不使用BouncyCastle得到結果:{a3}");Console.WriteLine();}

SHA算法

安全散列算法(英文:Secure Hash Algorithm,縮寫為SHA)是一個密碼散列函數家族,是FIPS所認證的安全散列算法。

SHA家族的五個算法,分別是SHA-1、SHA-224、SHA-256、SHA-384,和SHA-512,由美國國家安全局(NSA)所設計,并由美國國家標準與技術研究院(NIST)發布;是美國的政府標準。后四者有時并稱為SHA-2。SHA-1在許多安全協定中廣為使用,包括TLS和SSL、PGP、SSH、S/MIME和IPsec,曾被視為是MD5(更早之前被廣為使用的雜湊函數)的后繼者。但SHA-1的安全性如今被密碼學家嚴重質疑;雖然至今尚未出現對SHA-2有效的攻擊,它的算法跟SHA-1基本上仍然相似;因此有些人開始發展其他替代的雜湊算法。

2017年2月23日,Google公司公告宣稱他們與CWI Amsterdam合作共同創建了兩個有著相同的SHA-1值但內容不同的PDF文件,這代表SHA-1算法已被正式攻破

應用場景

目前SHA1的應用較為廣泛,主要應用于CA和數字證書中,另外在目前互聯網中流行的BT軟件中,也是使用SHA1來進行文件校驗的。

代碼實現

SHA1
public class SHA1{/// <summary>/// 哈希計算(使用BouncyCastle)/// </summary>public static byte[] Compute(string s){if (string.IsNullOrEmpty(s)){throw new ArgumentNullException(nameof(s));}var digest = new Sha1Digest();var resBuf = new byte[digest.GetDigestSize()];var input = Encoding.UTF8.GetBytes(s);digest.BlockUpdate(input, 0, input.Length);digest.DoFinal(resBuf, 0);return resBuf;}/// <summary>/// 哈希計算(不使用BouncyCastle)/// </summary>public static byte[] Compute2(string s){if (string.IsNullOrEmpty(s)){throw new ArgumentNullException(nameof(s));}using (var sha1 = System.Security.Cryptography.SHA1.Create()){return sha1.ComputeHash(Encoding.UTF8.GetBytes(s));}}}
SHA256
public class SHA256{/// <summary>/// 哈希計算(使用BouncyCastle)/// </summary>public static byte[] Compute1(string s){if (string.IsNullOrEmpty(s)){throw new ArgumentNullException(nameof(s));}var digest = new Sha256Digest();var resBuf = new byte[digest.GetDigestSize()];var input = Encoding.UTF8.GetBytes(s);digest.BlockUpdate(input, 0, input.Length);digest.DoFinal(resBuf, 0);return resBuf;}/// <summary>/// 哈希計算(不使用BouncyCastle)/// </summary>public static byte[] Compute2(string s){if (string.IsNullOrEmpty(s)){throw new ArgumentNullException(nameof(s));}using (var sha256 = System.Security.Cryptography.SHA256.Create()){return sha256.ComputeHash(Encoding.UTF8.GetBytes(s));}}}

示例代碼

private static void SHA256Sample(){var s = "hello sha-256";Console.WriteLine(s);Console.WriteLine($"使用BouncyCastle計算結果(轉Base64字符串):{Base64.ToBase64String(SHA256.Compute1(s))}");Console.WriteLine($"不使用BouncyCastle計算結果(轉Base64字符串):{Base64.ToBase64String(SHA256.Compute2(s))}");}

MAC算法

消息認證碼算法(英文:Message Authentication Codes,縮寫為MAC) 含有密鑰的散列函數算法,兼容了MD和SHA算法的特性,并在此基礎上加上了密鑰。因此MAC算法也經常被稱作HMAC算法。消息的散列值由只有通信雙方知道的密鑰來控制。此時Hash值稱作MAC。

HMAC是密鑰相關的散列運算消息認證碼(Hash-based Message Authentication Code)的縮寫,由H.Krawezyk,M.Bellare,R.Canetti于1996年提出的一種基于Hash函數和密鑰進行消息認證的方法,并于1997年作為RFC2104被公布,并在IPSec和其他網絡協議(如SSL)中得以廣泛應用,現在已經成為事實上的Internet安全標準。它可以與任何迭代散列函數捆綁使用。

HMAC算法的典型應用

HMAC算法的一個典型應用是用在“挑戰/響應”(Challenge/Response)身份認證中,認證流程如下:

(1) 先由客戶端向服務器發出一個驗證請求。(2) 服務器接到此請求后生成一個隨機數并通過網絡傳輸給客戶端(此為挑戰)。(3) 客戶端將收到的隨機數與自己的密鑰進行HMAC-SHA1運算并得到一個結果作為認證證據傳給服務器(此為響應)。(4) 與此同時,服務器也使用該隨機數與存儲在服務器數據庫中的該客戶密鑰進行HMAC-SHA1運算,如果服務器的運算結果與客戶端傳回的響應結果相同,則認為客戶端是一個合法用戶 。

HMAC算法的安全性

HMAC算法引入了密鑰,其安全性已經不完全依賴于所使用的HASH算法,安全性主要有以下幾點保證:

(1) 使用的密鑰是雙方事先約定的,第三方不可能知道。由上面介紹應用流程可以看出,作為非法截獲信息的第三方,能夠得到的信息只有作為“挑戰”的隨機數和作為“響應”的HMAC結果,無法根據這兩個數據推算出密鑰。由于不知道密鑰,所以無法仿造出一致的響應。(2)在HMAC算法的應用中,第三方不可能事先知道輸出(如果知道,不用構造輸入,直接將輸出送給服務器即可)。(3) HMAC算法與一般的加密重要的區別在于它具有“瞬時”性,即認證只在當時有效,而加密算法被破解后,以前的加密結果就可能被解密。

HMAC組合散列函數

與HMAC組合使用的算法有HMac-MD5、HMac-SHA1、HMac-SHA256等等:

public class Algorithms{public const string HMacSHA1="HMAC-SHA1";public const string HMacMD5="HMAC-MD5";public const string HMacMD4="HMAC-MD4";public const string HMacMD2="HMAC-MD2";public const string HMacSHA224="HMAC-SHA224";public const string HMacSHA256="HMAC-SHA256";public const string HMacSHA384="HMAC-SHA384";public const string HMacSHA512_224 = "HMAC-SHA512/224";public const string HMacSHA512_256="HMAC-SHA512/256";public const string HMacRIPEMD128="HMAC-RIPEMD128";public const string HMacRIPEMD160="HMAC-RIPEMD160";public const string HMacTIGER="HMAC-TIGER";public const string HMacKECCAK224="HMAC-KECCAK224";public const string HMacKECCAK256="HMAC-KECCAK256";public const string HMacKECCAK288="HMAC-KECCAK288";public const string HMacKECCAK384="HMAC-KECCAK384";public const string HMacSHA3512="HMAC-SHA3-512";public const string HMacGOST3411_2012256="HMAC-GOST3411-2012-256";public const string HMacGOST3411_2012_512="HMAC-GOST3411-2012-512";......}

代碼實現

public class HMAC{/// <summary>/// 生成密鑰KEY/// </summary>/// <param name="algorithm">密文算法,參考Algorithms.cs中提供的HMac algorithm</param>/// <returns>密鑰KEY</returns>public static byte[] GeneratorKey(string algorithm){var kGen = GeneratorUtilities.GetKeyGenerator(algorithm);return kGen.GenerateKey();}/// <summary>/// 哈希計算/// </summary>/// <param name="data">輸入字符串</param>/// <param name="key">密鑰KEY</param>/// <param name="algorithm">密文算法,參考Algorithms.cs中提供的HMac algorithm</param>/// <returns>哈希值</returns>public static byte[] Compute(string data, byte[] key, string algorithm){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}var keyParameter = new Org.BouncyCastle.Crypto.Parameters.KeyParameter(key);var input = Encoding.UTF8.GetBytes(data);var mac = MacUtilities.GetMac(algorithm);mac.Init(keyParameter);mac.BlockUpdate(input, 0, input.Length);return MacUtilities.DoFinal(mac);}/// <summary>/// 哈希計算/// </summary>/// <param name="data">輸入字符串</param>/// <param name="key">密鑰KEY</param>/// <param name="digest"></param>/// <returns>哈希值</returns>public static byte[] Compute(string data, byte[] key, IDigest digest){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}var keyParameter = new Org.BouncyCastle.Crypto.Parameters.KeyParameter(key);var input = Encoding.UTF8.GetBytes(data);IMac mac = new Org.BouncyCastle.Crypto.Macs.HMac(digest);mac.Init(keyParameter);mac.BlockUpdate(input, 0, input.Length);return MacUtilities.DoFinal(mac);}}
HMAC-MD5
public class HMACMD5{/// <summary>/// 生成密鑰KEY/// </summary>public static byte[] GeneratorKey(){return HMAC.GeneratorKey(Algorithms.HMacMD5);}/// <summary>/// 哈希計算(使用BouncyCastle)/// </summary>public static byte[] Compute(string data, byte[] key){return HMAC.Compute(data, key, Algorithms.HMacMD5);//or//return HMAC.Compute(data, key, new MD5Digest());}/// <summary>/// 哈希計算(不使用BouncyCastle)/// </summary>public static byte[] Compute2(string data, string key){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (string.IsNullOrEmpty(key)){throw new ArgumentNullException(nameof(key));}using (var hmacMd5 = new System.Security.Cryptography.HMACMD5(Encoding.UTF8.GetBytes(key))){return hmacMd5.ComputeHash(Encoding.UTF8.GetBytes(data));}}}
HMAC-SHA1
public class HMACSHA1{/// <summary>/// 生成密鑰KEY/// </summary>/// <returns></returns>public static byte[] GeneratorKey(){return HMAC.GeneratorKey(Algorithms.HMacSHA1);}/// <summary>/// 哈希計算(使用BouncyCastle)/// </summary>public static byte[] Compute(string data, byte[] key){return HMAC.Compute(data, key, Algorithms.HMacSHA1);//or//return HMAC.Compute(data, key, new Sha1Digest());}/// <summary>/// 哈希計算(不使用BouncyCastle)/// </summary>public static byte[] Compute2(string data, byte[] key){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}using (var hmacSha1 = new System.Security.Cryptography.HMACSHA1(key)){return hmacSha1.ComputeHash(Encoding.UTF8.GetBytes(data));}}}
HMAC-SHA256
public class HMACSHA256{/// <summary>/// 生成簽名/// </summary>public static byte[] GeneratorKey(){return HMAC.GeneratorKey(Algorithms.HMacSHA256);}/// <summary>/// 哈希計算(使用BouncyCastle)/// </summary>public static byte[] Compute(string data, byte[] key){return HMAC.Compute(data, key, Algorithms.HMacSHA256);//or//return HMAC.Compute(data, key, new Sha256Digest());}/// <summary>/// 哈希計算(不使用BouncyCastle)/// </summary>public static byte[] Compute2(string data, byte[] key){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}using (var hmacSha256 = new System.Security.Cryptography.HMACSHA256(key)){return hmacSha256.ComputeHash(Encoding.UTF8.GetBytes(data));}}}

示例代碼

private static void HMacSha256Sample(){var s = "hello hmac sha256";Console.WriteLine(s);var k = HMACSHA256.GeneratorKey();Console.WriteLine($"密鑰(十六進制字符串):{Hex.ToHexString(k)}");Console.WriteLine($"密鑰(Base64字符串):{Base64.ToBase64String(k)}");var b1 = HMACSHA256.Compute(s, k);Console.WriteLine($"使用BouncyCastle計算結果(轉Base64字符串):{Base64.ToBase64String(b1)}");Console.WriteLine($"使用BouncyCastle計算結果(轉十六進制字符串):{Hex.ToHexString(b1)}");var b2 = HMACSHA256.Compute2(s, k);Console.WriteLine($"不使用BouncyCastle計算結果(轉Base64字符串):{Base64.ToBase64String(b2)}");Console.WriteLine($"不使用BouncyCastle計算結果(轉十六進制字符串):{Hex.ToHexString(b2)}");}

數字簽名算法

數字簽名是一個帶有密鑰的消息摘要算法,這個密鑰包括了公鑰和私鑰,用于驗證數據完整性、認證數據來源和抗否認,遵循OSI參考模型、私鑰簽名和公鑰驗證。也是非對稱加密算法和消息摘要算法的結合體

FIPS 186-4規定了三種可用于數據保護的數字簽名生成和驗證技術:數字簽名算法(DSA),橢圓曲線數字簽名算法(ECDSA)和Rivest-Shamir Adelman算法( RSA)。

Rivest-Shamir Adelman算法( RSA)

RSA算法是1977年由羅納德·里維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當時他們三人都在麻省理工學院工作。RSA就是他們三人姓氏開頭字母拼在一起組成的。

RSA是目前計算機密碼學中最經典算法,也是目前為止使用最廣泛的數字簽名算法,從提出到現在已近三十年,經歷了各種攻擊的考驗,逐漸為人們接受,普遍認為是目前最優秀的公鑰方案之一。

代碼實現

SHA1WithRSA
public class SHA1WithRSA{/// <summary>/// 生成簽名/// </summary>public static string GenerateSignature(string data, RSAParameters privateKey){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}using (var rsa = System.Security.Cryptography.RSA.Create()){rsa.ImportParameters(privateKey);return Base64.ToBase64String(rsa.SignData(Encoding.UTF8.GetBytes(data), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));}}/// <summary>/// 驗證簽名/// </summary>public static bool VerifySignature(string data, string sign, RSAParameters publicKey){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (string.IsNullOrEmpty(sign)){throw new ArgumentNullException(nameof(sign));}using (var rsa = System.Security.Cryptography.RSA.Create()){rsa.ImportParameters(publicKey);return rsa.VerifyData(Encoding.UTF8.GetBytes(data), Base64.Decode(sign), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);}}/// <summary>/// 生成簽名/// </summary>public static string GenerateSignature(string data, AsymmetricKeyParameter privateKey){var byteData = Encoding.UTF8.GetBytes(data);var normalSig = SignerUtilities.GetSigner("SHA1WithRSA");normalSig.Init(true, privateKey);normalSig.BlockUpdate(byteData, 0, data.Length);var normalResult = normalSig.GenerateSignature();return Base64.ToBase64String(normalResult);}/// <summary>/// 驗證簽名/// </summary>public static bool VerifySignature(string data, string sign, AsymmetricKeyParameter publicKey){var signBytes = Base64.Decode(sign);var plainBytes = Encoding.UTF8.GetBytes(data);var verifier = SignerUtilities.GetSigner("SHA1WithRSA");verifier.Init(false, publicKey);verifier.BlockUpdate(plainBytes, 0, plainBytes.Length);return verifier.VerifySignature(signBytes);}}
SHA256WithRSA
public class SHA256WithRSA{/// <summary>/// 生成簽名/// </summary>public static string GenerateSignature(string data, RSAParameters privateKey){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}using (var rsa = System.Security.Cryptography.RSA.Create()){rsa.ImportParameters(privateKey);return Base64.ToBase64String(rsa.SignData(Encoding.UTF8.GetBytes(data), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));}}/// <summary>/// 驗證簽名/// </summary>public static bool VerifySignature(string data, string sign, RSAParameters publicKey){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (string.IsNullOrEmpty(sign)){throw new ArgumentNullException(nameof(sign));}using (var rsa = System.Security.Cryptography.RSA.Create()){rsa.ImportParameters(publicKey);return rsa.VerifyData(Encoding.UTF8.GetBytes(data), Base64.Decode(sign), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);}}/// <summary>/// 生成簽名/// </summary>public static string GenerateSignature(string data, AsymmetricKeyParameter parameter){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (parameter == null){throw new ArgumentNullException(nameof(parameter));}var signer = SignerUtilities.GetSigner("SHA256WithRSA");signer.Init(true, parameter);var bytes = Encoding.UTF8.GetBytes(data);signer.BlockUpdate(bytes, 0, bytes.Length);return Base64.ToBase64String(signer.GenerateSignature());}/// <summary>/// 驗證簽名/// </summary>public static bool VerifySignature(string data, string sign, AsymmetricKeyParameter parameter){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (string.IsNullOrEmpty(sign)){throw new ArgumentNullException(nameof(sign));}if (parameter == null){throw new ArgumentNullException(nameof(parameter));}var verifier = SignerUtilities.GetSigner("SHA256WithRSA");verifier.Init(false, parameter);var bytes = Encoding.UTF8.GetBytes(data);verifier.BlockUpdate(bytes, 0, bytes.Length);return verifier.VerifySignature(Base64.Decode(sign));}}

示例代碼

private static void SHA256WithRSA_Sample(){var s = "hello sha256 with rsa";Console.WriteLine(s);var keyParameter = RSAKeyGenerator.Pkcs8(2048);Console.WriteLine("私鑰:");Console.WriteLine(keyParameter.PrivateKey);Console.WriteLine("公鑰:");Console.WriteLine(keyParameter.PublicKey);Console.WriteLine();Console.WriteLine("使用BouncyCastle:");var sign1 = SHA256WithRSA.GenerateSignature(s,RSAUtilities.GetAsymmetricKeyParameterFormAsn1PrivateKey(keyParameter.PrivateKey));Console.WriteLine("sign1:");Console.WriteLine(sign1);var verified1 = SHA256WithRSA.VerifySignature(s, sign1,RSAUtilities.GetAsymmetricKeyParameterFormPublicKey(keyParameter.PublicKey));Console.WriteLine("驗證結果:");Console.WriteLine(verified1 ? "signature verified" : "signature not verified");Console.WriteLine();Console.WriteLine("不使用BouncyCastle:");var sign2 = SHA256WithRSA.GenerateSignature(s,RSAUtilities.GetRsaParametersFormAsn1PrivateKey(keyParameter.PrivateKey));Console.WriteLine("sign2:");Console.WriteLine(sign2);var verified2 = SHA256WithRSA.VerifySignature(s, sign1,RSAUtilities.GetAsymmetricKeyParameterFormPublicKey(keyParameter.PublicKey));Console.WriteLine("驗證結果:");Console.WriteLine(verified2 ? "signature verified" : "signature not verified");Console.WriteLine();}

數字簽名算法(DSA)

Digital Signature Algorithm (DSA)是Schnorr和ElGamal簽名算法的變種,被美國NIST作為DSS(DigitalSignature Standard)。DSA是基于整數有限域離散對數難題的,其安全性與RSA相比差不多。

DSA(用于數字簽名算法)的簽名生成速度很快,驗證速度很慢,加密時更慢,但解密時速度很快

目前,最好使用RSA 2048位密鑰(也可以用4096位的RSA密鑰),商業RSA證書比DSA證書被更廣泛地部署。

OpenSSH 7.0及以上版本默認禁用了ssh-dss(DSA)公鑰算法。官方沒有給出具體的解釋,但其中可能有OpenSSH,DSA密鑰位數生成的原因,同時生成簽名時隨機性差,可能會泄漏私鑰,且以現在機算機的算力,DSA 1024-bit已經實際上可破解,建議不使用。

一般來說,還是推薦大家使用RSA算法。

代碼實現

SHA1/DSA
/// <summary>/// 生成簽名/// </summary>public static string GenerateSignature(string data, AsymmetricKeyParameter privateKey){var byteData = Encoding.UTF8.GetBytes(data);var normalSig = SignerUtilities.GetSigner("SHA1/DSA");normalSig.Init(true, privateKey);normalSig.BlockUpdate(byteData, 0, data.Length);var normalResult = normalSig.GenerateSignature();return Base64.ToBase64String(normalResult);}/// <summary>/// 簽名驗證/// </summary>public static bool VerifySignature(string data, string sign, AsymmetricKeyParameter publicKey){var signBytes = Base64.Decode(sign);var plainBytes = Encoding.UTF8.GetBytes(data);var verifier = SignerUtilities.GetSigner("SHA1/DSA");verifier.Init(false, publicKey);verifier.BlockUpdate(plainBytes, 0, plainBytes.Length);return verifier.VerifySignature(signBytes);}
SHA256/DSA
/// <summary>/// 生成簽名/// </summary>public static string GenerateSignature(string data, AsymmetricKeyParameter parameter){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (parameter == null){throw new ArgumentNullException(nameof(parameter));}var signer = SignerUtilities.GetSigner("SHA256/DSA");signer.Init(true, parameter);var bytes = Encoding.UTF8.GetBytes(data);signer.BlockUpdate(bytes, 0, bytes.Length);return Base64.ToBase64String(signer.GenerateSignature());}/// <summary>/// 驗證簽名/// </summary>public static bool VerifySignature(string data, string sign, AsymmetricKeyParameter parameter){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (string.IsNullOrEmpty(sign)){throw new ArgumentNullException(nameof(sign));}if (parameter == null){throw new ArgumentNullException(nameof(parameter));}var verifier = SignerUtilities.GetSigner("SHA256/DSA");verifier.Init(false, parameter);var bytes = Encoding.UTF8.GetBytes(data);verifier.BlockUpdate(bytes, 0, bytes.Length);return verifier.VerifySignature(Base64.Decode(sign));}

示例代碼

private static void SHA256WithDSA_Sample(){var s = "hello dsa";Console.WriteLine(s);var keyParameter = DSAKeyGenerator.Generator();Console.WriteLine("私鑰:");Console.WriteLine(keyParameter.PrivateKey);Console.WriteLine("公鑰:");Console.WriteLine(keyParameter.PublicKey);Console.WriteLine();var sign = SHA256WithDSA.GenerateSignature(s,RSAUtilities.GetAsymmetricKeyParameterFormAsn1PrivateKey(keyParameter.PrivateKey));Console.WriteLine($"sign:{sign}");var verified = SHA256WithDSA.VerifySignature(s, sign,RSAUtilities.GetAsymmetricKeyParameterFormPublicKey(keyParameter.PublicKey));Console.WriteLine("驗證結果:");Console.WriteLine(verified ? "signature verified" : "signature not verified");}

橢圓曲線數字簽名算法(ECDSA)

橢圓曲線數字簽名算法(ECDSA)是使用橢圓曲線密碼(ECC)對數字簽名算法(DSA)的模擬。ECDSA于1999年成為ANSI標準,并于2000年成為IEEE和NIST標準。它在1998年既已為ISO所接受,并且包含它的其他一些標準亦在ISO的考慮之中。與普通的離散對數問題(discrete logarithm problem DLP)和大數分解問題(integer factorization problem IFP)不同,橢圓曲線離散對數問題(elliptic curve discrete logarithm problem ECDLP)沒有亞指數時間的解決方法。因此橢圓曲線密碼的單位比特強度要高于其他公鑰體制。

ECDSA是ECC與DSA的結合,整個簽名過程與DSA類似,所不一樣的是簽名中采取的算法為ECC

ECC與RSA 相比,有以下的優點:

  • 相同密鑰長度下,安全性能更高,如160位ECC已經與1024位RSA、DSA有相同的安全強度。

  • 計算量小,處理速度快,在私鑰的處理速度上(解密和簽名),ECC遠 比RSA、DSA快得多。

  • 存儲空間占用小 ECC的密鑰尺寸和系統參數與RSA、DSA相比要小得多, 所以占用的存儲空間小得多。

  • 帶寬要求低使得ECC具有廣泛得應用前景。

代碼實現

SHA1/ECDSA
/// <summary>/// 生成簽名/// </summary>public static string GenerateSignature(string data, AsymmetricKeyParameter parameter){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (parameter == null){throw new ArgumentNullException(nameof(parameter));}var signer = SignerUtilities.GetSigner("SHA1/ECDSA");signer.Init(true, parameter);var bytes = Encoding.UTF8.GetBytes(data);signer.BlockUpdate(bytes, 0, bytes.Length);return Base64.ToBase64String(signer.GenerateSignature());}/// <summary>/// 驗證簽名/// </summary>public static bool VerifySignature(string data, string sign, AsymmetricKeyParameter parameter){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (string.IsNullOrEmpty(sign)){throw new ArgumentNullException(nameof(sign));}if (parameter == null){throw new ArgumentNullException(nameof(parameter));}var verifier = SignerUtilities.GetSigner("SHA1/ECDSA");verifier.Init(false, parameter);var bytes = Encoding.UTF8.GetBytes(data);verifier.BlockUpdate(bytes, 0, bytes.Length);return verifier.VerifySignature(Base64.Decode(sign));}
SHA256/ECDSA
/// <summary>/// 生成簽名/// </summary>public static string GenerateSignature(string data, AsymmetricKeyParameter parameter){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (parameter == null){throw new ArgumentNullException(nameof(parameter));}var signer = SignerUtilities.GetSigner("SHA256/ECDSA");signer.Init(true, parameter);var bytes = Encoding.UTF8.GetBytes(data);signer.BlockUpdate(bytes, 0, bytes.Length);return Base64.ToBase64String(signer.GenerateSignature());}/// <summary>/// 驗證簽名/// </summary>public static bool VerifySignature(string data, string sign, AsymmetricKeyParameter parameter){if (string.IsNullOrEmpty(data)){throw new ArgumentNullException(nameof(data));}if (string.IsNullOrEmpty(sign)){throw new ArgumentNullException(nameof(sign));}if (parameter == null){throw new ArgumentNullException(nameof(parameter));}var verifier = SignerUtilities.GetSigner("SHA256/ECDSA");verifier.Init(false, parameter);var bytes = Encoding.UTF8.GetBytes(data);verifier.BlockUpdate(bytes, 0, bytes.Length);return verifier.VerifySignature(Base64.Decode(sign));}

示例代碼

private static void SHA256WithECDSA_Sample(){var s = "hello ec dsa";Console.WriteLine(s);var keyParameter = ECDSAKeyGenerator.Generator();Console.WriteLine("私鑰:");Console.WriteLine(keyParameter.PrivateKey);Console.WriteLine("公鑰:");Console.WriteLine(keyParameter.PublicKey);var sign = SHA256WithECDSA.GenerateSignature(s,RSAUtilities.GetAsymmetricKeyParameterFormAsn1PrivateKey(keyParameter.PrivateKey));Console.WriteLine($"sign:{sign}");var verified = SHA256WithECDSA.VerifySignature(s, sign,RSAUtilities.GetAsymmetricKeyParameterFormPublicKey(keyParameter.PublicKey));Console.WriteLine("驗證結果:");Console.WriteLine(verified ? "signature verified" : "signature not verified");}

下期預告

下一篇將介紹對稱加密算法,敬請期待。。。

總結

以上是生活随笔為你收集整理的.NET Core加解密实战系列之——消息摘要与数字签名算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。