c# 實(shí)現(xiàn)RSA非對稱加密算法_第1頁
c# 實(shí)現(xiàn)RSA非對稱加密算法_第2頁
c# 實(shí)現(xiàn)RSA非對稱加密算法_第3頁
c# 實(shí)現(xiàn)RSA非對稱加密算法_第4頁
c# 實(shí)現(xiàn)RSA非對稱加密算法_第5頁
已閱讀5頁,還剩11頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論