




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第c#實(shí)現(xiàn)RSA非對稱加密算法目錄公鑰與私鑰C#實(shí)現(xiàn)
公鑰與私鑰
公鑰與私鑰是成對的,一般的,我們認(rèn)為的是公鑰加密、私鑰解密、私鑰簽名、公鑰驗(yàn)證,有人說成私鑰加密,公鑰解密時不對的。
公鑰與私鑰的生成有多種方式,可以通過程序生成(下文具體實(shí)現(xiàn)),可以通過openssl工具:
#生成一個私鑰,推薦使用1024位的秘鑰,秘鑰以pem格式保存到-out參數(shù)指定的文件中,采用PKCS1格式
opensslgenrsa-outrsa.pem1024
#生成與私鑰對應(yīng)的公鑰,生成的是SubjectPublicKey,一般配合PKCS8格式私鑰使用
opensslrsa-inrsa.pem-pubout-outrsa.pub
RSA生成公鑰與私鑰一般有兩種格式:PKCS1和PKCS8,上面的命令生成的秘鑰是PKCS1格式的,而公鑰是SubjectPublicKey,一般配合PKCS8格式私鑰使用,所以就可能會涉及到PKCS1和PKCS8之間的轉(zhuǎn)換:
#PKCS1格式私鑰轉(zhuǎn)換為PKCS8格式私鑰,私鑰直接輸出到-out參數(shù)指定的文件中
opensslpkcs8-topk8-informPEM-inrsa.pem-outformpem-nocrypt-outrsa_pkcs8.pem
#PKCS8格式私鑰轉(zhuǎn)換為PKCS1格式私鑰,私鑰直接輸出到-out參數(shù)指定的文件中
opensslrsa-inrsa_pkcs8.pem-outrsa_pkcs1.pem
#PKCS1格式公鑰轉(zhuǎn)換為PKCS8格式公鑰,轉(zhuǎn)換后的內(nèi)容直接輸出
opensslrsa-pubin-inrsa.pub-RSAPublicKey_out
#PKCS8格式公鑰轉(zhuǎn)換為PKCS1格式公鑰,轉(zhuǎn)換后的內(nèi)容直接輸出
opensslrsa-RSAPublicKey_in-pubout-inrsa.pub
現(xiàn)實(shí)中,我們往往從pem、crt、pfx文件獲取公私和私鑰,crt、pfx的制作可以參考:簡單的制作ssl證書,并在nginx和IIS中使用,或者使用現(xiàn)成的:/s/1MJ5YmuZiLBnf-DfNR_6D7A(提取碼:c6tj),密碼都是:123456
C#實(shí)現(xiàn)
為了方便讀取pem、crt、pfx文件中的公私和私鑰,這里我使用了第三方的包:Portable.BouncyCastle,可以使用NuGet安裝:Install-PackagePortable.BouncyCastle
接著,這里我封裝了一個RsaHelper輔助類來實(shí)現(xiàn)各種RSA加密的過程:
usingOrg.BouncyCastle.Utilities.IO.Pem;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.IO;
usingSystem.Security.Cryptography;
usingSystem.Security.Cryptography.X509Certificates;
usingSystem.Text;
namespaceConsoleApp1
publicclassRsaHelper
#regionkey
///summary
///將秘鑰保存到Pem文件
////summary
///paramname="isPrivateKey"/param
///paramname="buffer"/param
///paramname="pemFileName"/param
///returns/returns
publicstaticvoidWriteToPem(byte[]buffer,boolisPrivateKey,stringpemFileName)
PemObjectpemObject=newPemObject(isPrivateKey"RSAPRIVATEKEY":"RSAPUBLICKEY",buffer);
if(File.Exists(pemFileName))
File.Delete(pemFileName);
using(varfileStream=newFileStream(pemFileName,FileMode.OpenOrCreate,FileAccess.Write))
using(varsw=newStreamWriter(fileStream))
varwriter=newPemWriter(sw);
writer.WriteObject(pemObject);
sw.Flush();
///summary
///從Pem文件中讀取秘鑰
////summary
///paramname="pemFileName"/param
///returns/returns
publicstaticbyte[]ReadFromPem(stringpemFileName)
using(varfileStream=newFileStream(pemFileName,FileMode.Open,FileAccess.Read))
using(varsw=newStreamReader(fileStream))
varwriter=newPemReader(sw);
returnwriter.ReadPemObject().Content;
///summary
///從xml中讀取秘鑰
////summary
///paramname="xml"/param
///paramname="isPrivateKey"/param
///paramname="usePkcs8"/param
///returns/returns
publicstaticbyte[]ReadFromXml(stringxml,boolisPrivateKey,boolusePkcs8)
using(varrsa=newRSACryptoServiceProvider())
rsa.FromXmlString(xml);
if(isPrivateKey)
returnusePkcs8rsa.ExportPkcs8PrivateKey():rsa.ExportRSAPrivateKey();
returnusePkcs8rsa.ExportSubjectPublicKeyInfo():rsa.ExportRSAPublicKey();
///summary
///將秘鑰保存到xml中
////summary
///paramname="buffer"/param
///paramname="isPrivateKey"/param
///paramname="usePkcs8"/param
///returns/returns
publicstaticstringWriteToXml(byte[]buffer,boolisPrivateKey,boolusePkcs8)
using(varrsa=CreateRSACryptoServiceProvider(buffer,isPrivateKey,usePkcs8))
returnrsa.ToXmlString(isPrivateKey);
///summary
///獲取RSA非對稱加密的Key
////summary
///paramname="publicKey"/param
///paramname="privateKey"/param
publicstaticvoidGenerateRsaKey(boolusePKCS8,outbyte[]publicKey,outbyte[]privateKey)
using(RSACryptoServiceProviderrsa=newRSACryptoServiceProvider())
rsa.KeySize=1024;//1024位
if(usePKCS8)
//使用pkcs8填充方式導(dǎo)出
publicKey=rsa.ExportSubjectPublicKeyInfo();//公鑰
privateKey=rsa.ExportPkcs8PrivateKey();//私鑰
else
//使用pkcs1填充方式導(dǎo)出
publicKey=rsa.ExportRSAPublicKey();//公鑰
privateKey=rsa.ExportRSAPrivateKey();//私鑰
///summary
///從Pfx文件獲取RSA非對稱加密的Key
////summary
///paramname="pfxFileName"/param
///paramname="publicKey"/param
///paramname="privateKey"/param
publicstaticvoidReadFromPfx(stringpfxFileName,stringpassword,outbyte[]publicKey,outbyte[]privateKey)
X509Certificate2x509Certificate2=newX509Certificate2(pfxFileName,password,X509KeyStorageFlags.Exportable);
publicKey=x509Certificate2.GetRSAPublicKey().ExportRSAPublicKey();
privateKey=x509Certificate2.GetRSAPrivateKey().ExportRSAPrivateKey();
///summary
///從Crt文件中讀取公鑰
////summary
///paramname="crtFileName"/param
///paramname="password"/param
///returns/returns
publicstaticbyte[]ReadPublicKeyFromCrt(stringcrtFileName,stringpassword)
X509Certificate2x509Certificate2=newX509Certificate2(crtFileName,password,X509KeyStorageFlags.Exportable);
varpublicKey=x509Certificate2.GetRSAPublicKey().ExportRSAPublicKey();
returnpublicKey;
#endregion
#regionPkcs1andPkcs8
///summary
///Pkcs1轉(zhuǎn)Pkcs8
////summary
///paramname="isPrivateKey"/param
///paramname="buffer"/param
///returns/returns
publicstaticbyte[]Pkcs1ToPkcs8(boolisPrivateKey,byte[]buffer)
using(varrsa=newRSACryptoServiceProvider())
if(isPrivateKey)
rsa.ImportRSAPrivateKey(buffer,out_);
returnrsa.ExportPkcs8PrivateKey();
else
rsa.ImportRSAPublicKey(buffer,out_);
returnrsa.ExportSubjectPublicKeyInfo();
///summary
///Pkcs8轉(zhuǎn)Pkcs1
////summary
///paramname="isPrivateKey"/param
///paramname="buffer"/param
///returns/returns
publicstaticbyte[]Pkcs8ToPkcs1(boolisPrivateKey,byte[]buffer)
using(varrsa=newRSACryptoServiceProvider())
if(isPrivateKey)
rsa.ImportPkcs8PrivateKey(buffer,out_);
returnrsa.ExportRSAPrivateKey();
else
rsa.ImportSubjectPublicKeyInfo(buffer,out_);
returnrsa.ExportRSAPublicKey();
#endregion
#regionRSA
///summary
///獲取一個RSACryptoServiceProvider
////summary
///paramname="isPrivateKey"/param
///paramname="buffer"/param
///paramname="usePkcs8"/param
///returns/returns
publicstaticRSACryptoServiceProviderCreateRSACryptoServiceProvider(byte[]buffer,boolisPrivateKey,boolusePkcs8=false)
RSACryptoServiceProviderrsa=newRSACryptoServiceProvider();
if(isPrivateKey)
if(usePkcs8)
rsa.ImportPkcs8PrivateKey(buffer,out_);
else
rsa.ImportRSAPrivateKey(buffer,out_);
else
if(usePkcs8)
rsa.ImportSubjectPublicKeyInfo(buffer,out_);
else
rsa.ImportRSAPublicKey(buffer,out_);
returnrsa;
///summary
///RSA公鑰加密
////summary
///paramname="value"待加密的明文/param
///paramname="publicKey"公鑰/param
///paramname="usePkcs8"是否使用pkcs8填充/param
///returns/returns
publicstaticstringRsaEncrypt(stringvalue,byte[]publicKey,boolusePkcs8=false)
if(string.IsNullOrEmpty(value))returnvalue;
using(RSACryptoServiceProviderrsa=CreateRSACryptoServiceProvider(publicKey,false,usePkcs8))
varbuffer=Encoding.UTF8.GetBytes(value);
buffer=rsa.Encrypt(buffer,false);
//使用hex格式輸出數(shù)據(jù)
StringBuilderresult=newStringBuilder();
foreach(bytebinbuffer)
result.AppendFormat("{0:x2}",b);
returnresult.ToString();
//或者使用下面的輸出
//returnBitConverter.ToString(buffer).Replace("-","").ToLower();
///summary
///RSA私鑰解密
////summary
///paramname="value"密文/param
///paramname="privateKey"私鑰/param
///paramname="usePkcs8"是否使用pkcs8填充/param
///returns/returns
publicstaticstringRsaDecrypt(stringvalue,byte[]privateKey,boolusePkcs8=false)
if(string.IsNullOrEmpty(value))returnvalue;
using(RSACryptoServiceProviderrsa=CreateRSACryptoServiceProvider(privateKey,true,usePkcs8))
//轉(zhuǎn)換hex格式數(shù)據(jù)為byte數(shù)組
varbuffer=newbyte[value.Length/2];
for(vari=0;ibuffer.Length;i++)
buffer[i]=(byte)Convert.ToInt32(value.Substring(i*2,2),16);
buffer=rsa.Decrypt(buffer,false);
returnEncoding.UTF8.GetString(buffer);
///summary
///RSA私鑰生成簽名
////summary
///paramname="value"原始值/param
///paramname="publicKey"公鑰/param
///paramname="halg"簽名hash算法:SHA,SHA1,MD5,SHA256,SHA384,SHA512/param
///paramname="usePkcs8"是否使用pkcs8填充/param
///returns/returns
publicstaticstringSign(stringvalue,byte[]privateKey,stringhalg="MD5",boolusePkcs8=false)
if(string.IsNullOrEmpty(value))returnvalue;
using(RSACryptoServiceProviderrsa=CreateRSACryptoServiceProvider(privateKey,true,usePkcs8))
byte[]buffer=Encoding.UTF8.GetBytes(value);
buffer=rsa.SignData(buffer,HashAlgorithm.Create(halg));
//使用hex格式輸出數(shù)據(jù)
StringBuilderresult=newStringBuilder();
foreach(bytebinbuffer)
result.AppendFormat("{0:x2}",b);
returnresult.ToString();
//或者使用下面的輸出
//returnBitConverter.ToString(buffer).Replace("-","").ToLower();
///summary
///RSA公鑰驗(yàn)證簽名
////summary
///paramname="value"原始值/param
///paramname="publicKey"公鑰/param
///paramname="signature"簽名/param
///paramname="halg"簽名hash算法:SHA,SHA1,MD5,SHA256,SHA384,SHA512/param
///paramname="usePkcs8"是否使用pkcs8填充/param
///returns/returns
publicstaticboolVerify(stringvalue,byte[]publicKey,stringsignature,stringhalg="MD5",boolusePkcs8=false)
if(string.IsNullOrEmpty(value))returnfalse;
using(RSACryptoServiceProviderrsa=CreateRSACryptoServiceProvider(publicKey,false,usePkcs8))
//轉(zhuǎn)換hex格式數(shù)據(jù)為byte數(shù)組
varbuffer=newbyte[signature.Length/2];
for(vari=0;ibuffer.Length;i++)
buffer[i]=(byte)Convert.ToInt32(signature.Substring(i*2,2),16);
returnrsa.VerifyData(Encoding.UTF8.GetBytes(value),HashAlgorithm.Create(halg),buffer);
#endregion
}
可以使用生成RSA的公私秘鑰:
//通過程序生成
RsaHelper.GenerateRsaKey(usePKCS8,outpublicKey,outprivateKey);
生成秘鑰后,需要保存,一般保存到pem文件中:
//保存到Pem文件,filePath是文件目錄
RsaHelper.WriteToPem(publicKey,false,Path.Combine(filePath,"rsa.pub"));
RsaHelper.WriteToPem(privateKey,true,Path.Combine(filePath,"rsa.pem"));
還以將公鑰和私鑰輸出為xml格式:
//保存到xml中
stringpublicKeyXml=RsaHelper.WriteToXml(publicKey,false,usePKCS8);
stringprivateKeyXml=RsaHelper.WriteToXml(privateKey,true,usePKCS8);
保存到pem文件和xml中后,也可以從中讀取:
//從Pem文件獲取,filePath是文件目錄
publicKey=RsaHelper.ReadFromPem(Path.Combine(filePath,"rsa.pub"));
privateKey=RsaHelper.ReadFromPem(Path.Combine(filePath,"rsa.pem"));
//從xml中讀取
publicKey=RsaHelper.ReadFromXml(publicKeyXml,false,usePKCS8);
privateKey=RsaHelper.ReadFromXml(privateKeyXml,true,usePKCS8);
還可以從crt證書中讀取公鑰,而crt文件不包含私鑰,因此需要單獨(dú)獲取私鑰:
//從crt文件讀取,filePath是文件目錄
publicKey=RsaHelper.ReadPublicKeyFromCrt(Path.Combine(filePath,"demo.crt"),"");
privateKey=RsaHelper.ReadFromPem(Path.Combine(filePath,"demo.key"));
pfx文件中包含了公鑰和私鑰,可以很方便就讀取到:
//從demo.pfx文件讀取(demo.pfx采用的是pkcs1),filePath是文件目錄
RsaHelper.ReadFromPfx(Path.Combine(filePath,"demo.pfx"),"123456",outpublicKey,outprivateKey);
有時候我們還可能需要進(jìn)行秘鑰的轉(zhuǎn)換:
//Pkcs8格式公鑰轉(zhuǎn)換為Pkcs1格式公鑰
publicKey=RsaHelper.Pkcs8ToPkcs1(false,publicKey);
//Pkcs8格式私鑰轉(zhuǎn)換為Pkcs1格式私鑰
privateKey=RsaHelper.Pkcs8ToPkcs1(true,privateKey);
//Pkcs1格式公鑰轉(zhuǎn)換為Pkcs8格式公鑰
publicKey=RsaHelper.Pkcs1ToPkcs8(false,publicKey);
//Pkcs1格式私鑰轉(zhuǎn)換為Pkcs8格式私鑰
privateKey=RsaHelper.Pkcs1ToPkcs8(true,privateKey);
有了公鑰和私鑰,接下就就能實(shí)現(xiàn)加密、解密、簽名、驗(yàn)證簽名等操作了:
stringencryptText=RsaHelper.RsaEncrypt(text,publicKey,usePKCS8);
Console.WriteLine($"【{text}】經(jīng)過【RSA】加密后:{encryptText}");
stringdecryptText=RsaHelper.RsaDecrypt(encryptText,privateKey,usePKCS8);
Console.WriteLine($"【{encryptText}】經(jīng)過【RSA】解密后:{decryptText}");
stringsignature=RsaHelper.Sign(text,privateKey,"MD5",usePKCS8);
Console.WriteLine($"【{text}】經(jīng)過【RSA】簽名后:{signature}");
boolresult=RsaHelper.Verify(text,publicKey,signature,"MD5",usePKCS8);
Console.WriteLine($"【{text}】的簽名【{signature}】經(jīng)過【RSA】驗(yàn)證后結(jié)果是:{result}");
完整的demo代碼:
usingSystem;
usingSystem.IO;
namespaceConsoleApp1
classProgram
staticvoidMain(string[]args)
stringtext="上山打老虎";
boolusePKCS8=true;//usePKCS8=true表示是否成PKCS8格式的公私秘鑰,否則乘車PKCS1格式的公私秘鑰
stringfilePath=Directory.GetCurrentDirectory();
Console.WriteLine($"文件路徑:{filePath}");//存放pem,crt,pfx等文件的目錄
byte[]publicKey,privateKey;//公鑰和私鑰
//通過程序生成
RsaHelper.GenerateRsaKey(usePKCS8,outpublicKey,outprivateKey);
//從Pem文件獲取,filePath是文件目錄
//publicKey=RsaHelper.ReadFromPem(Path.Combine(filePath,"rsa.pub"));
//privateKey=RsaHelper.ReadFromPem(Path.Combine(filePath,"rsa.pem"));
//從demo.pfx文件讀取(demo.pfx采用的是pkcs1),filePath是文件目錄
//RsaHelper.ReadFromPfx(Path.Combine(filePath,"demo.pfx"),"123456",outpublicKey,outprivateKey);
//從crt文件讀取,filePath是文件目錄
//publicKey=RsaHelper.ReadPublicKeyFromCrt(Path.Combine(filePath,"demo.crt"),"");
//privateKey=RsaHelper.ReadFromPem(Path.Combine(filePath,"demo.key
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 設(shè)計(jì)公司前臺管理制度
- 設(shè)計(jì)招標(biāo)文件管理制度
- 診所醫(yī)療感染管理制度
- 診所隱患臺賬管理制度
- 貨場租賃使用管理制度
- 2025年中國工業(yè)大語言模型行業(yè)市場全景分析及前景機(jī)遇研判報(bào)告
- 貨物抵協(xié)議書范本
- 個人分賬協(xié)議書范本大全
- 懲治老婆協(xié)議書范本
- 員工持干股協(xié)議書范本
- 經(jīng)空氣傳播疾病醫(yī)院感染預(yù)防與控制規(guī)范課件
- 冠心病合并糖尿病血脂管理
- GB/T 43492-2023預(yù)制保溫球墨鑄鐵管、管件和附件
- PDCA循環(huán)在我院靜脈用藥調(diào)配中心用藥錯誤管理中的應(yīng)用靜配中心質(zhì)量持續(xù)改進(jìn)案例
- 精神病患者攻擊行為預(yù)防
- 《議程設(shè)置理論》課件
- 二單元稅率利率復(fù)習(xí)課
- GB/Z 43281-2023即時檢驗(yàn)(POCT)設(shè)備監(jiān)督員和操作員指南
- 農(nóng)藥經(jīng)營56學(xué)時培訓(xùn)模擬試題
- 衣柜全屋定制家具施工方案
- 廣州市近5年中考語文作文真題及模擬題匯編(含參考例文)
評論
0/150
提交評論