RSA加解密使用總結,.net私鑰加密公鑰解密,WinCE平臺RSA加解密

BouncyCastle.Crypto.dll

該庫的源代碼下載地址:http://www.bouncycastle.org/csharp/download/bccrypto-net-1.7-src.zip

 

BigInteger類具有RSA加解密的功能,下載地址:

http://www.codeproject.com/KB/cs/biginteger.aspx

 

對pem密鑰文件的解析參考代碼:

http://www.codeproject.com/KB/security/CryptoInteropKeys.aspx 


 ————————————————————————————————————————————————

使用pem格式RSA密鑰文件加解密,大致從兩個方面介紹

一、對RSA文件格式的解析

a)        RSA文件的生成(openssl的使用方法)

b)       RSA文件在不同平臺中的解析方式(解析代碼)

二、對解析出來的公鑰,私鑰的使用方法

a)        Java平臺上的不同的加解密方式(公鑰加密,私鑰解密/私鑰加密,公鑰解密)

b)       .net平臺上的不同的加解密方式(私鑰加密,公鑰解密/公鑰加密,私鑰解密)

從根本上解決不同平臺RSA密鑰互通的問題。

 

.net平臺pem文件解析方式:NF上解析,CF平臺解析,(CF:compactframework)

 

u      使用BigInteger類進行公鑰解密

pem文件的解析

對pem密鑰文件的解析參考代碼:

http://www.codeproject.com/KB/security/CryptoInteropKeys.aspx

爲了使該代碼可以在CF平臺上也能使用,對其做了一些修改。

首先爲了方便解析pem文件,在AsnKeyParser類中添加了一個構造函數,和一個變量。(類本身提供了一個internal AsnKeyParser(Stringpathname)方法用來解析pem文件。)

internal AsnKeyParser(AsnParserparser)

{

this.parser = parser;

}

private AsnParserparser;

//(AsnParser是AsnKeyParser.cs文件中的一個類)。

 

然後是從公鑰字符串中獲取公鑰的代碼:

byte[] binKey = System.Convert.FromBase64String(pub_key); 

// Base64解碼,pub_key是公鑰字符串

AsnParser parser = newAsnParser(binKey);

AsnKeyParser keyParser = newAsnKeyParser(parser);

RSAParameters publicKey =keyParser.ParseRSAPublicKey();

//至此爲止獲得了公鑰

使用BigInteger類作公鑰解密

由於.net平臺上提供的RSACryptoServiceProvider只能用作公鑰加密,私鑰解密,(和其內部實現有關)。如果要使用私鑰加密,公鑰解密,可以依靠第三方,使用標準RSA算法實現的組件。

以上所提到的BigIngeter類提供了標準的RSA加解密算法,

BigInteger類具有解密的功能,下載地址:

http://www.codeproject.com/KB/cs/biginteger.aspx

 

使用公鑰解密的具體方法如下:

byte[] data = Convert.FromBase64String(enStr);//enStr爲密文

//byte[] data =HexStringToByteArray(enStr);

//如果密文是16進制字符串可以使用HexStringToByteArray方法轉換爲字節數組

 

BigInteger biN = newBigInteger(publicKey.Modulus);

BigInteger biE = newBigInteger(publicKey.Exponent);

BigInteger biText = newBigInteger(data);

BigInteger biEnText = biText.modPow(biE, biN);

string temp =byteToHexStr(biEnText.getBytes());

 

//十六進制字符串轉爲byte數組

private static byte[] HexStringToByteArray(stringsBytes)

{

int pos = 0;

int len = (sBytes.Length / 2);

byte[] b = newbyte[len];

int count = sBytes.Length;

 

for (int i= 0; i < count; i += 2)

{

b[pos] = Convert.ToByte(sBytes.Substring(i,2), 16);

pos++;

}

 

//string temp =Encoding.Default.GetString(b);

return b;

}

 

/// <summary>

/// 字節數組轉16進制字符串

/// </summary>

/// <param name="bytes"></param>

/// <returns></returns>

public static string byteToHexStr(byte[]bytes)

{

string returnStr = "";

if (bytes != null)

{

for (int i= 0; i < bytes.Length; i++)

{

returnStr += bytes[i].ToString("X2");

}

}

return returnStr;

}

 

由於我的原文是16進制的字符串,在解密的過程中發現如果原文的字節中有00的話解密會有異常,原文第一字節如果是00,解密出來會被拋棄,只要手工加上00,如果是第2,3,4字節是00的話,修改BigInteger中的getBytes方法便可解決,修改如下:

public byte[] getBytes()

{

int numBits = bitCount();

 

int numBytes = numBits >> 3;

if ((numBits & 0x7) != 0)

numBytes++;

 

byte[] result = newbyte[numBytes];

 

//Console.WriteLine(result.Length);

 

int pos = 0;

uint tempVal, val = data[dataLength - 1];

 

if ((tempVal = (val >> 24 &0xFF)) != 0)

{ result[pos++] = (byte)tempVal; }

 

if ((tempVal = (val >> 16 &0xFF)) != 0)

{ result[pos++] = (byte)tempVal; }

else if (pos> 0)

{ pos++; }

else

{ result[pos++] = (byte)tempVal; }

 

if ((tempVal = (val >> 8 &0xFF)) != 0)

{ result[pos++] = (byte)tempVal; }

else if (pos> 0)

{ pos++; }

else

{ result[pos++] = (byte)tempVal; }

 

if ((tempVal = (val & 0xFF)) != 0)

{ result[pos++] = (byte)tempVal; }

else

{ result[pos++] = (byte)tempVal; }

 

for (int i= dataLength - 2; i >= 0; i--, pos += 4)

{

val = data[i];

result[pos + 3] = (byte)(val & 0xFF);

val >>= 8;

result[pos + 2] = (byte)(val & 0xFF);

val >>= 8;

result[pos + 1] = (byte)(val & 0xFF);

val >>= 8;

result[pos] = (byte)(val& 0xFF);

}

 

return result;

}

 

u      使用開源的BouncyCastle.Crypto.dl組件庫來作加解密

該庫的源代碼下載地址:http://www.bouncycastle.org/csharp/download/bccrypto-net-1.7-src.zip

       使用時,先導入其中crypto\bzip2,csharp\crypto\src兩個文件夾所有的內容

然後刪除crypto\src\ AssemblyInfo.cs,crypto\src\asn1\util\ Dump.cs文件

 

crypto\src\util\Platform.cs類中編寫了平臺與編譯選擇代碼,如果要在WinCE平臺(CF)上使用,需要在條件預編譯中加上條件編譯,右鍵點擊項目》屬性

在條件編譯符號在加上:NETCF_2_0,

對平臺的支持情況,可以參看crypto\src\util\ Platform.cs類中的條件預編譯代碼

 

對於WinForm中可以直接使用BouncyCastle.Crypto.dl庫

下載地址:http://www.bouncycastle.org/csharp/download/bccrypto-net-1.7-bin.zip

 

調用的代碼如下:(還是使用公鑰解密密文)

using System.Security.Cryptography;

 

using Org.BouncyCastle.Crypto.Generators;

using Org.BouncyCastle.Crypto.Parameters;

using Org.BouncyCastle.Crypto;

using Org.BouncyCastle.Security;

using Org.BouncyCastle.Crypto.Engines;

 

using Org.BouncyCastle.OpenSsl;

 

TextReader xl = newStreamReader("c:/pub.key");

 

//pub.key文件格式如下:

-----BEGIN PUBLIC KEY-----

MEwwDQasdf…………………Y6oTv3w1hq+zSCzcw6Mv+a6Kx3

CMpgg9jDGmGwdp4mg5LopYag0ZYHq21AJwIDAQAB

-----END PUBLIC KEY-----

 

PemReader y1 = newPemReader(xl);

 

string sign = "mt25lD1UX9fnf+96v1Y8hlvIgW0Uou3H7LivTeiQaSoXFNzHaBntuFz2NDIe7XGF";

 

byte[] data = System.Convert.FromBase64String(sign);

 

AsymmetricKeyParameter pubkey = (AsymmetricKeyParameter)y1.ReadObject();

 

IAsymmetricBlockCipher engine = newRsaEngine();

engine.Init(false,pubkey);

 

byte[] testData = engine.ProcessBlock(data,0, data.Length);

 

string temp = byteToHexStr(testData); //字節數組轉換爲16進制字符串

 

在CE平臺調用上有些差異,調用方法如下:

string appPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName);

TextReader xl = newStreamReader(appPath+"\\pub.key");

PemReader y1 = newPemReader(xl);

 

string sign = "mt25lD1UX9fnf+96v1Y8hlvIgW0Uou3H7LivTeiQaSoXFNzHaBntuFz2NDIe7XGF";

 

byte[] data = System.Convert.FromBase64String(sign);

PemObject ss1=y1.ReadPemObject();

AsymmetricKeyParameter pubkey = PublicKeyFactory.CreateKey(ss1.Content);

IAsymmetricBlockCipher engine = newRsaEngine();

engine.Init(false,pubkey);

 

byte[] testData = engine.ProcessBlock(data,0, data.Length);

 

string temp = byteToHexStr(testData);

 

 

發佈了13 篇原創文章 · 獲贊 3 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章