本章讲述了如何利用哈希,配置等手段保护数据。为了更进一步保护数据,则需要直接通过密匙的方式进行加密。这种方式在安全性和强度上都比其他方法更加的稳固。
在.NET安全命名空间Crypttography下定义了3种类型的加密方法,它们是非对称算法、对称算法和哈希算法。所有的这些类(和.NET密码学类型)都是抽象类。
对称算法(Symmetric Algorithm),有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算,同时解密密钥也可以从加密密钥中推算。而在大多数的对称算法中,加密密钥和解密密钥是相同的。所以也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通信之前,商定一个密钥。
对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信性至关重要。
对称算法的加密强度也依赖于密钥。如果开发人员配置一个长的密钥,将是非常难破解的。如图4-6所示,加密和解密过程都需要使用同一密匙,利用加密解密的内存容器plaintext和ciphertext。
图4-6 对称加密算法机理
对称加密算法基于简单的数学操作,工作效率高。因此当要加密的数据量非常大时它是最好的选择。基于对称的加密可以被黑客暴力破解,但是长的密钥可以在黑客破解密码的时候保护数据更长的时间。
另外,在使用密钥或密码对称加密过程中初始化向量(Initial Vector,IV)也很重要。IV被使用在最初的编码中(加密或者解密)。在所有的对称算法类中都有Mode的属性,这是IV使用的。如果设置Mode属性为CipherMode.CBC(Cipher Block Chaining),则使用这个模式时,每个数据块使用来自前一个块的值来处理,也就是说,如果系统处理第三块数据,它就会从第二块中取一些信息。同样,它会取第一块数据中的信息用来处理第二块数据。但是在第一块数据之前没有可以用的块,因此它将使用IV来处理第一块。
这个技术确保没有两个相同的块产生相同的输出并且因此使得数据更安全。然而如果使Mode=CipherModer.ECB(Electronic codebook mode),则应用程序就不会使用上面的方法(使用前面的处理的块信息处理后面的块)。如果想用很少的资源和时间处理大量的消息,那么这个方法是不错的选择。
对称加密算法主要包括的算法如表4-4所示。
表4-4 对称加密算法
这里需要注意的是,所有的算法类都是继承于抽象类SymmetricAlgorithm,并且每个类都支持不同大小的密钥。相同的情况下,它们也支持不同大小的初始化向量。
抽象类不能直接创建任何实例。用SymmetricAlgorithm类中的共享Create方法可以创建加密实例,代码如下:
该方法为创建者返回一个TestC默认实现的实例,而不用去关心具体如何实现TestC类,代码将自动适应改变并正确的工作,或可能在将来类用托管代码写,原代码依然可以接受。
对称加密算法SymmetricAlgorithm类的方法和属性如表4-5所示。
表4-5 SymmetricAlgorithm类的方法和属性描述
在讲解具体加密算法代码前,需要解释几个概念:
(1)CreateEncryptor和CreateDecryptor方法。
SymmetricAlgorithm类的CreateEncryptor和CreateDecryptor方法返回ICryptoTransform对象。IcryptoTransform是一个数据块处理类来实现的接口。过程可以是加密、解密、哈希、基于64的编码和解码等,接口的目的是完成数据处理分块。读者可以直接使用它的实例,但是在大多数情况下,为了方便也通过CryptoStream完成。
下面的实例演示了如何使用CryptoStream:
CreateEncryptor和CreateDecryptor是两个重要的方法。如果没有任何参数传入其中,那么将使用默认的密钥和IV(使用SymmetricAlgoruthm类里面的GenerateKey和GenerateIV方法),也可以传入一个IV和密钥到CreateEncryptor和CreateDecryptor的对象中,使加密和解密使用自己定义的IV和密钥。
(2)CryptoStream类。
CryptoStream类通常用来读写数据的同时加密或解密数据,该类简单的包装了一下原始流类,下面的代码可以得到它的对象:
fileStream请求从硬盘或者内存中读取数据的原始文件的流(或是MemoryStream),通过使用mStream对象和StreamReader/StreamWriter对象读写数据,读写时加密解密信息将依赖IcryptoTransform对象。
了解基本概念后,下面通过实例说明利用DES对称算法实现加密和解密方法。
首先,打开IDE创建一个窗体,并且添加一个文本输入控件txtData和命令按钮控件的窗体,代码将要加密TextBox里面的文本并用MessageBox显示。
命令按钮的单击事件代码如下:
需要注意的是,代码在任何地方都没有使用IV和密钥,这些由.NET框架自动产生。代码将加密以后的数据使用MemoryStream写到内存中,开发人员从内存中得到数据。
当数据已经写入内存需要回显到TextBox和MessageBox中,需要代码读取和显示执行结果,代码如下:
从字节转换为字符串可以使用UTF8Encoding进行编码。最后,将解密后的数据再次显示在MessageBox和TextBox中,其代码如下:
与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密,所以这种算法叫作非对称加密算法。
以加解密双方甲乙为例,利用非对称加密算法实现机密信息交换的基本过程是:甲生成一对密钥并将其中的一把作为公用密钥向其他贸易方公开;得到该公用密钥的乙使用该密钥对机密信息进行加密后再发送给甲。甲再用自己保存的另一把专用密钥对加密后的信息进行解密。甲只能用其专用密钥解密由其公用密钥加密后的信息。
非对称加密算法的保密性较好,消除了最终用户交换密钥的需要,但加密和解密花费时间长、速度慢,不适合于对文件加密。
在微软公司的Window安全性体系结构中,公开密钥系统主要用于对私有密钥的加密过程。每个用户如果想要对数据进行加密,都需要生成一对自己的密钥对(keypair)。密钥对中的公开密钥和非对称加密解密算法是公开的,但私有密钥则应该由密钥的主人妥善保管。
使用公开密钥对文件进行加密传输的实际过程包括4步:
(1)发送方生成一个自己的私有密钥并用接收方的公开密钥对自己的私有密钥进行加密,然后通过网络传输到接收方。
(2)发送方对需要传输的文件用自己的私有密钥进行加密,然后通过网络把加密后的文件传输到接收方。
(3)接收方用自己的公开密钥进行解密后得到发送方的私有密钥。
(4)接受方用发送方的私有密钥对文件进行解密得到文件的明文形式。
因为只有接收方才拥有自己的公开密钥,所以即使其他人得到了加密后发送方的私有密钥,也无法进行解密,从而保证了私有密钥的安全性,也保证了传输文件的安全性。实际上,在文件传输过程中实现了两个加密解密过程。文件本身的加密和解密与私有密钥的加密解密,这分别通过私有密钥和公开密钥来实现。
整个加解密流程如图4-7所示。
图4-7 对称加密算法机理
非对称算法在Web系统验证模块上经常被使用,如高密级文件在线传输,聊天加密等。下面的实例使用.NET程序对非对称加密算法,以及如何在.NET里使用非对称(RSA)算法加密解密用户数据。RSA的加解密过程主要是创建两个RSA对象rsa1和rsa2,要rsa2发送一段信息给rsa1,则先由rsa1发送“公钥”给rsa2。rsa2 获取得公钥之后,加密要发送的数据内容。rsa1获取加密后的内容后,用自己的私钥解密,得出原始的数据内容。
实例代码如下:
无论是基于JSP或ASP.NET技术的系统中都会需要创建基于HTTPS的高安全信道,如电子商务系统、结算系统等。
该技术通常向用户传送公钥,使用的分发机制称为证书。通常证书颁发机构(CA)对证书进行签名,以便确认公钥来自声称发送公钥的主体。
证书存放在称为“证书存储”的安全位置中。“证书存储”包含证书、CRL和证书信任列表(CTL),每个用户都有存储证书的个人存储(称为“我的存储”)。
虽然可以将任何证书存储在“我的存储”中,但应该将此存储专用于存储用户的个人证书,即用于签名和解密该特定用户消息的证书。
除了“我的存储”外,Windows还维护以下证书存储:CA和根。此存储包含特定证书颁发机构(用户信任其向其他用户颁发证书)的证书。操作系统提供了一套受信任的CA证书,管理员还可以添加其他的证书,如包含用户与之交换签名消息其他用户的证书。
图4-8所示为证书认证的顺序。
图4-8 证书加密算法机理
(1)甲将一个签名的证书请求(包含他的名字、公钥、可能还有其他一些信息)发送到CA。
(2)CA使用甲的请求创建一个消息,CA使用其私钥对消息进行签名,将消息和签名返回给甲,消息和签名共同构成了甲的证书。
(3)甲将证书发送给乙,以便授权乙访问甲的公钥。
(4)乙使用CA的公钥对证书签名进行验证,如果证明签名是有效的,乙就承认证书中的公钥是甲的公钥。
与数字签名的情况相同,任何有权访问CA公钥的接收者都可以确定证书是否由特定CA签名,这个过程不要求访问任何机密信息。上面这个方案假定乙有权访问CA的公钥,如果乙拥有包含该公钥的CA证书的副本,则乙有权访问该密钥。
在了解了证书基本概念后,需要帮助读者进一步了解如何结合.NET技术实现基于证书的加密技术。
Internet上有很多提供验证服务的机构,比较流行的有VeriSign。在Intranet中使用Windows Server中的证书服务运行自己的CA服务。
X.509是一种较常用的证书标准,如Linux和Windows的Authenticode技术与SSL技术都是使用的X.509证书标准。.NET Framework SDK中提供了makecert这个生成证书的工具用于制作测试证书。
如下命令会产生一个名为test.cer的证书:
双击此证书可以看到证书详细内容,如图4-9所示。
图4-9 证书详细信息
在.NET 框架中System.Security.Cryptography.X509Certificates下提供了专门处理X.509证书的类。
下面的实例说明证书文件的读取,以及证书对象基本方法的使用。代码创建指定证书的对象,并且输出关于证书的安全加密信息。
代码中的主函数Main用于输出演示结果。方法FindKeyLocation用于定位密钥文件,其名称为test,存放路径是用户个人文件夹。方法GetKeyFileName用于输出该证书的相关描述参数。
程序代码如下:
在使用证书加密Web信息时,需要读者注意根证书。因为Windows系统维护了一个证书的列表,称为证书存储区(Certificate Store)。包含在该列表中的证书被称为根证书,它是由Windows系统默认提供的。如果CA的证书是一个根证书,Windows就不再需要通过网络访问CA以验证证书的有效性,因为本机上已存有这类CA证书。通过各CA的层级验证可以形成一个证书链,从而最大程度避免机器在安装期间与CA联系。