一个实用的基于RSACryptoServiceProvider的Helper类

RSACryptoServiceProvider提供的加解密算法实在够难用的, 无奈自己的项目需要使用, 网上也没找到能做到自动分段加解密的封装, 无奈自己写一个吧. 在此提供源代码, 希望能对为此苦恼的朋友有所帮助.

/* Goal: 
 *     .NET内置的RSA算法太难用, 这里要实现一个自动分段加解密的封装.
 * 
 * Design describe: 
 *     本着实用的原则, 只提供产生密钥对的方法, 和加解密方法.
 * 
 * Write by:
 *     WangYiBo, 2008/5/20
 *     
 * Changing record:
 *     
 
*/


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Security.Cryptography;

namespace PublicClassLibrary.Definition
{
    
public class RSAKeyPair
    {
        
public readonly string PrivateKey;
        
public readonly string PublicKey;

        
private RSAKeyPair()
        { }

        
internal RSAKeyPair(string privateKey, string publicKey)
        {
            PrivateKey 
= privateKey;
            PublicKey 
= publicKey;
        }
    }

    
static public class RSAEncryption
    {
        
//微软的RSA算法需要填充随机数, 此数值受Encrypt方法中参数fOAEP的影响
        const int MinRandomCount_fOAEPIsTure = 11;
        
const int MinRandomCount_fOAEPIsFalse = 41;

        
static public RSAKeyPair CreatRSAKey(int dwKeySize)
        {
            RSACryptoServiceProvider rsa 
= new RSACryptoServiceProvider(dwKeySize);

            
return new RSAKeyPair(rsa.ToXmlString(true), rsa.ToXmlString(false));
        }


        
static public byte[] RSAEncrypt(this byte[] data, string publicKey, bool fOAEP)
        {
            
#region 因为不同的RSA加密位数会导致不同的buffer大小, 此步推算.
            
int bfSize = 1, length = publicKey.Length - 67;

            
int count = 0;
            
while (length > 1)
            {
                length 
>>= 1;
                count
++;
            }

            bfSize 
<<= count;
            
#endregion


            
#region 推算每次运算实际可以允许的最大有效数量
            
int eCount;
            
if (fOAEP)
            {
                eCount 
= bfSize - MinRandomCount_fOAEPIsFalse;
            }
            
else
            {
                eCount 
= bfSize - MinRandomCount_fOAEPIsTure;
            }
            
#endregion



            
#region 分段加密.
            
int resultBlockCount = (data.Length - 1/ eCount + 1;

            
byte[] bfBytes;
            
byte[] oBytes1 = new byte[eCount];
            
byte[] oBytes2 = new byte[data.Length % eCount];
            
byte[] result = new byte[resultBlockCount * bfSize];

            RSACryptoServiceProvider rsa 
= new RSACryptoServiceProvider();
            rsa.FromXmlString(publicKey);

            
for (int bc = 0; bc < resultBlockCount - 1; bc++)
            {
                
for (int i = 0; i < oBytes1.Length; i++)
                {
                    oBytes1[i] 
= data[bc * oBytes1.Length + i];
                }
                bfBytes 
= rsa.Encrypt(oBytes1, fOAEP);
                
for (int j = 0; j < bfBytes.Length; j++)
                {
                    result[bc 
* bfBytes.Length + j] = bfBytes[j];
                }
            }


            
for (int i = 0; i < oBytes2.Length; i++)
            {
                oBytes2[i] 
= data[(resultBlockCount - 1* oBytes1.Length + i];
            }
            bfBytes 
= rsa.Encrypt(oBytes2, fOAEP);
            
for (int j = 0; j < bfBytes.Length; j++)
            {
                result[(resultBlockCount 
- 1*bfBytes.Length + j] = bfBytes[j];
            }
            
#endregion

            
return result;
        }


        
static public byte[] RSADecrypt(this byte[] data, string privateKey, bool fOAEP)
        {
            
#region 推算bufferSize
            
int bfSize = 1, length = (privateKey.Length - 127/ 4;

            
int count = 0;
            
while (length > 1)
            {
                length 
>>= 1;
                count
++;
            }

            bfSize 
<<= count;
            
#endregion



            
#region 分段解密
            
int resultBlockCount = (data.Length - 1/ bfSize + 1;

            
byte[] bfBytes;
            
byte[] oBytes = new byte[bfSize];
            
byte[] result = new byte[data.Length];

            RSACryptoServiceProvider rsa 
= new RSACryptoServiceProvider();
            rsa.FromXmlString(privateKey);

            
int pbfBytesLength = 0;
            
for (int bc = 0; bc < resultBlockCount; bc++)
            {
                
for (int i = 0; i < oBytes.Length; i++)
                {
                    oBytes[i] 
= data[bc * oBytes.Length + i];
                }
                bfBytes 
= rsa.Decrypt(oBytes, fOAEP);

                
for (int j = 0; j < bfBytes.Length; j++)
                {
                    result[pbfBytesLength 
+ j] = bfBytes[j];
                }
                pbfBytesLength 
+= bfBytes.Length;
            }

            Array.Resize
<byte>(ref result, pbfBytesLength);
            
#endregion


            
return result;
        }
    }
}
posted @ 2008-06-19 11:43 王弈博 阅读(...) 评论(...) 编辑 收藏