System.Security.Cryptography实战

Author:zfive5(zidong)

Email:zfive5@yahoo.com.cn

 

引子

 

一直以来认为网络是me的强项,自然书也买了和看了不少,日子久了,好书坏书靠经验去分辨, 但往往经验也同样会影响我对事物的正确判断。例如,很早看到过王达写的网络方面的书,第一印象觉得有凑数赚钱的嫌疑,连翻的机会都不给它,但上星期去海淀买来一本(感谢网上的评论),察觉到这系列简直就是网络基础的百科全书!虽然不是太深入,但讲什么是A之类的命题足以,我也对PPPoE协议格式理解比以前多些!

 

写标准加密散列算法,DES /MD5之类,都统统用c/c++,觉得只有在自己代码里包含最深层次的code才是正道,任何用其它库或控件是对这些算法无知的表露

这些天看.net比较多! 打开System.Security.Cryptography命名空间后才有了写它一点的冲动(感谢老天在我阅读msdn时,让鼠标偏了一下)!

 

正文

System.Security.Cryptography加密算法主要分为:

l        散列算法 (MD5/SHA1/ RIPEMD160/ SHA256 / SHA384 )

 

l        对称加密算法 (DES/TRI-DES)

l        非对称加密算法(RSA/DSA)

 

1.散列

散列,简单点就是一种变换,使变换后的数据在一定小概率情况下代表变换前数据的“标签”,这个标签就是散列,变换就是散列算法,往往这些算法是公开的、不可逆的!因为算法公开的,为了防止大家谁都可以对源数据进行散列,所以出现增加一个KEY的变形散列算法(HMAC算法)。

 

散列主要用在对数据有效性的验证方面。例如,BT就是用SHA1验证收到数据块是否有效的,Email服务器的登录就有一中名为HMACMD5的验证模式!

 

C#代码

    

//byte数据串进行散列

HashAlgorithm  oTransform = (HashAlgorithm)MD5.Create();

byte[] AInput={0x31,0x31,0x31,0x31};

byte[] AOutput = oTransform.ComputeHash(AInput);

 

//对文件流进行散列

FileStream oFile = new FileStream("c://10.vbs", FileMode.Open);

HashAlgorithm oTransform = (HashAlgorithm)MD5.Create();

byte[] AOutput = oTransform.ComputeHash(oFile);

oFile.Close();

 

//byte数据串进行HMACMD5

//KeyedHashAlgorithm oHash = (KeyedHashAlgorithm)HMACMD5.Create();

//HMACMD5.Create()其实为返回一个HMACSHA1,HMACMD5没有定义Create

KeyedHashAlgorithm oHash = (KeyedHashAlgorithm)new HMACMD5();

byte[] oKey={0x31};

oHash.Key = oKey;

byte[] AInput ={ 0x31, 0x31, 0x31, 0x31 };

byte[] AOutput = oHash.ComputeHash(AInput);

 

还有要说的MD5MD5CryptoServiceProvider 为什么有两个,它们之间的关系是怎样的?如果第一次用这个类库的话,真有点糊涂(此前我在糊涂ing“既生瑜,何生亮!”

 

源码之下无密码,开始反编译:

 

MD5.Create()   —>

CryptoConfig.CreateFromName(System.Security.Cryptography.MD5) —>

CryptoConfig.defaultNameHT[“System.Security.Cryptography.MD5] —>

Type type1 = (Type) typeof(MD5CryptoServiceProvider); —>

反射一个MD5CryptoServiceProvider实例

 

所以最终用户使用的还是MD5CryptoServiceProviderMD5主要起到作用就是简名的作用!

 

还有一点疑虑关于算列就剩下了“.net是否包含md2md4算法?”,其实也是以下代码给我的灵感的:

 

//MD5

Utils._CreateHash(Utils.Static ProvHandle, 0x8003, ref handle1);
 this._safeHashHandle = handle1;

 

//SHA1     

 Utils._CreateHash(Utils.StaticProvHandle, 0x8004, ref handle1);

 this._safeHashHandle = handle1;

 

是否0x8001<->MD2 , 0x8002<->MD4 ,这只是我的猜想,由于保护机制,无法在自己的类中使用SafeHashHandle 类(真不知道ms为什么不暴露出这个类呢?),但用户完全可以模仿SHA1Managed写一个MD4类!

 

2.对称加密

 

所谓对称就是指加密解密中使用的key值是一样的,这种加密算法也是我们大家日常用的最多的加密算法了,这类加密算法一般公开, 遭受考验的也主要是key的长度,当然了你也完全写一个不公开的算法,只要能在数学上证明有一个可逆过程与其一一对应就可以了!

 

想象A加完密的密文发送给B,如果B想知道原文,还要根据解密算法解开才可以 ! 因此key值的保密性在这类应用中的重中之重!

 

对称加密要注意的地方主要就是块加密模式(这个也不是对称独有的,在非对称中也存在模式概念)!CipherMode类型定义如下:

public enum CipherMode

{

     CBC = 1,

     ECB = 2,

     OFB = 3,

     CFB = 4,

     CTS = 5

}

关于CipherMode的解释见

ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref11/html/T_System_Security_Cryptography_CipherMode.htm

 

本来打算ctrl+c/ ctrl+v的,但看了半天都不知道在说什么,真不知道翻译的人是不懂呢?还是其它原因?现在只能自己写这部分了。

 

ECB 电子密码本

把加密串分成64bit一组,不足部分添齐(这里留到后面说),然后对每一个块单独加密,最终一块块的密文块组成密文,解密过程相反!如图:

 

 

 

CBC密码块链

CBC模式的出现 就是为了补救ECB模式的一些缺点(密文一样原文也一样),过程如图所示,这里就不画蛇了:

 

 

OFB 输出反溃模式

下图E’是加密函数E的一种变换,具体过程可以看书,这里主要展示的它的大至过程:

 

CFB 密码反馈模式

 

与上面的OFB类似,也是对OFB模式的一种加强,E’函数与OFB一样

 

CTR 记数模式

这种模式用IV加密,再与明文异或得到密文块,且下次加密块用到的IV是先前的IV1,过程如图:

 C#代码

//这样就可以实现文件或内存块的加密了,解密类似!

//这里需要注意的是:SymmetricAlgorithm默认的加密模式为CBC,见下代码:

//protected SymmetricAlgorithm ()

//{

//  this.ModeValue = CipherMode.CBC;

//  this.PaddingValue = PaddingMode.PKCS7;

//}

 

//这样当64位块一样时,出现同样的密文可能性很小!

//用户可以通过改变SymmetricAlgorithm成员ModeValue来改变加密模式来比较一下了!

//看上SymmetricAlgorithm构造函数发现pad也是可选的,后面可以看msdn,总算可以看明白了,感谢翻译!

SymmetricAlgorithm oSym = DES.Create();

MemoryStream oMem=new MemoryStream();

byte [] AKey={0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};

byte [] AIV= {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};

CryptoStream oStream = new CryptoStream(oMem, oSym.CreateEncryptor(AKey,AIV), CryptoStreamMode.Write);

byte[] AInput ={ 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,0x31,0x31,0x31 };

oStream.Write(AInput, 0, AInput.Length);

oStream.Close();

byte[] AOutput=oMem.ToArray();

 

这里还的引用一下msdn的关于pad的描述:

ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref11/html/T_System_Security_Cryptography_PaddingMode.htm

 

ANSIX923

 

ANSIX923 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节均填充数字零。

下面的示例演示此模式的工作原理。假定块长度为 8,数据长度为 9,则填充用八位字节数等于 7,数据等于 FF FF FF FF FF FF FF FF FF

 

数据: FF FF FF FF FF FF FF FF FF

 

X923 填充: FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 07

 

 

ISO10126

 

ISO10126 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节填充随机数据。

下面的示例演示此模式的工作原理。假定块长度为 8,数据长度为 9,则填充用八位字节数等于 7,数据等于 FF FF FF FF FF FF FF FF FF

 

数据: FF FF FF FF FF FF FF FF FF

 

ISO10126 填充: FF FF FF FF FF FF FF FF FF 7D 2A 75 EF F8 EF 07

 

 

None 不填充。

 

 

PKCS7

 

PKCS #7 填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。 

下面的示例演示这些模式的工作原理。假定块长度为 8,数据长度为 9,则填充用八位字节数等于 7,数据等于 FF FF FF FF FF FF FF FF FF

 

数据: FF FF FF FF FF FF FF FF FF

 

PKCS7 填充: FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07

 

Zeros

 

填充字符串由设置为零的字节组成。

 

 

以上红字部分出自《MSDN

 

3.非对称加密

 

意指加解密的密钥是不一样的,加密一个,解密一个!一个叫公钥,一个叫私钥!加密方式的安全性要比对称的安全些,但安全不是绝对的!这种算法最主要运用场景就是数字签名!像RSA/DSA

 

 C#代码

 

//加解密数据

//生成公私钥

RSACryptoServiceProvider oRSA = new RSACryptoServiceProvider();

string privatekey=oRSA.ToXmlString(true);

string publickey=oRSA.ToXmlString(false);

byte[] AOutput;

 

 

//公钥加密

RSACryptoServiceProvider oRSA1 = new RSACryptoServiceProvider();

oRSA1.FromXmlString(publickey);

byte[] AInput={0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};

AOutput = oRSA1.Encrypt(AInput,false);

 

//私钥解密

RSACryptoServiceProvider oRSA2 = new RSACryptoServiceProvider();

oRSA2.FromXmlString(privatekey);           

AInput = oRSA2.Decrypt(AOutput, false);

 

//私钥签名

RSACryptoServiceProvider oRSA3 = new RSACryptoServiceProvider();

oRSA3.FromXmlString(privatekey);

AOutput = oRSA3.SignData(AInput, "MD5");

 

 

//公钥验证

RSACryptoServiceProvider oRSA4 = new RSACryptoServiceProvider();

oRSA4.FromXmlString(publickey);

bool  bVerify= oRSA4.VerifyData(AInput, "MD5",AOutput);

 

 

这里需要提到的是DSA只能运用到数字签名和验证,加解密还的用RSA,关于最后一个参数“false:是什么意思,可以参考msdn,这里也不想添足了!

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值