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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

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

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

簡介

加解密現(xiàn)狀,編寫此系列文章的背景:

  • 需要考慮系統(tǒng)環(huán)境兼容性問題(Linux、Windows)

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

  • 網(wǎng)上資料版本不一、或不全面

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

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

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

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

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

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

功能依賴

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

支持 .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):消息認(rèn)證碼

MD算法

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

家族發(fā)展史

  • MD2算法:

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

  • MD4算法:

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

  • MD5算法:

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

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

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

應(yīng)用場景

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

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

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

代碼實現(xiàn)

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轉(zhuǎn)換得到結(jié)果:{a1}");var a2 = Hex.ToHexString(resBytes1).ToUpper();Console.WriteLine($"通過Hex.ToHexString轉(zhuǎn)換得到結(jié)果:{a2}");var a3 = Hex.ToHexString(resBytes2).ToUpper();Console.WriteLine($"不使用BouncyCastle得到結(jié)果:{a3}");Console.WriteLine();}

SHA算法

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

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

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

應(yīng)用場景

目前SHA1的應(yīng)用較為廣泛,主要應(yīng)用于CA和數(shù)字證書中,另外在目前互聯(lián)網(wǎng)中流行的BT軟件中,也是使用SHA1來進行文件校驗的。

代碼實現(xiàn)

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計算結(jié)果(轉(zhuǎn)Base64字符串):{Base64.ToBase64String(SHA256.Compute1(s))}");Console.WriteLine($"不使用BouncyCastle計算結(jié)果(轉(zhuǎn)Base64字符串):{Base64.ToBase64String(SHA256.Compute2(s))}");}

MAC算法

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

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

HMAC算法的典型應(yīng)用

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

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

HMAC算法的安全性

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

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

HMAC組合散列函數(shù)

與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";......}

代碼實現(xiàn)

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計算結(jié)果(轉(zhuǎn)Base64字符串):{Base64.ToBase64String(b1)}");Console.WriteLine($"使用BouncyCastle計算結(jié)果(轉(zhuǎn)十六進制字符串):{Hex.ToHexString(b1)}");var b2 = HMACSHA256.Compute2(s, k);Console.WriteLine($"不使用BouncyCastle計算結(jié)果(轉(zhuǎn)Base64字符串):{Base64.ToBase64String(b2)}");Console.WriteLine($"不使用BouncyCastle計算結(jié)果(轉(zhuǎn)十六進制字符串):{Hex.ToHexString(b2)}");}

數(shù)字簽名算法

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

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

Rivest-Shamir Adelman算法( RSA)

RSA算法是1977年由羅納德·里維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當(dāng)時他們?nèi)硕荚诼槭±砉W(xué)院工作。RSA就是他們?nèi)诵帐祥_頭字母拼在一起組成的。

RSA是目前計算機密碼學(xué)中最經(jīng)典算法,也是目前為止使用最廣泛的數(shù)字簽名算法,從提出到現(xiàn)在已近三十年,經(jīng)歷了各種攻擊的考驗,逐漸為人們接受,普遍認(rèn)為是目前最優(yōu)秀的公鑰方案之一。

代碼實現(xiàn)

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("驗證結(jié)果:");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("驗證結(jié)果:");Console.WriteLine(verified2 ? "signature verified" : "signature not verified");Console.WriteLine();}

數(shù)字簽名算法(DSA)

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

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

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

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

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

代碼實現(xiàn)

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("驗證結(jié)果:");Console.WriteLine(verified ? "signature verified" : "signature not verified");}

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

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

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

ECC與RSA 相比,有以下的優(yōu)點:

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

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

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

  • 帶寬要求低使得ECC具有廣泛得應(yīng)用前景。

代碼實現(xiàn)

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("驗證結(jié)果:");Console.WriteLine(verified ? "signature verified" : "signature not verified");}

下期預(yù)告

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

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。