《信息安全工程实践.docx》由会员分享,可在线阅读,更多相关《信息安全工程实践.docx(102页珍藏版)》请在三一办公上搜索。
1、信息安全工程实践安全编程基于USBKey的软件授权编程实验【实验内容】了解USBKey的使用和工作原理掌握通过USBKey控制软件启动和加密的简单程序【实验原理】USBKey是一种插在计算机USB口上的软硬件结合的设备,USBKey内置单片机或智能卡芯片,具有一定的存储空间和运算处理能力,使得USBKey具有判断、分析的处理能力,增强了主动的反解密能力。USBKey的内置芯片里包含有专用的加密算法软件,USBKey厂家提供一套USBKey的读写接口(API)给开发商,开发商在开发中通过在软件执行过程中和USBKey交换数据来实现加解密。目前多在USBKey中存储用户的私钥以及数字证书,利用US
2、B Key内置的公钥算法实现对用户身份的认证,同时也可以通过USBKey防止未授权的用户对软件进行复制和破解。【实验环境】运行环境:Microsoft Visual Studio 2005编程语言:C#【实验步骤】一、 加密狗本实验使用的加密狗,是一种类似于U盘的小硬件,是一种防盗版的方式。加密狗就是一种插在计算机并行口上的软硬件结合的加密产品,为多数软件开发商所采用。加密狗一般都有几十或几百字节的非易失性存储空间可供读写,现在较新的加密狗内部还包含了单片机。软件开发者可以通过接口函数和加密狗进行数据交换(即对加密狗进行读写),来检查加密狗是否插在并行口上;或者直接用加密狗附带的工具加密自己E
3、XE文件(俗称包壳)。这样,软件开发者可以在软件中设置多处软件锁,利用加密狗做为钥匙来打开这些锁;如果没插加密狗或加密狗不对应,软件将不能正常执行。加密狗厂家都会提供一套加密狗的读写接口(API)给开发商,厂家卖给开发商的狗都有各自的区别,某个开发商只能操作自己买的加密狗。加密狗通过在软件执行过程中和加密狗交换数据来实现加密的,加密狗内置单片机电路(也称CPU),使得加密狗具有判断、分析的处理能力,增强了主动的反解密能力。这种加密产品称它为“智能型”加密狗。加密狗内置的单片机里包含有专用于加密的算法软件,该软件被写入单片机后,就不能再被读出。这样,就保证了加密狗硬件不能被复制。二、 加密狗使用
4、的简单实例此实例通过加密狗来控制软件的启动。(1) 运行页面如图5.1.11所示为主程序窗口的运行画面,要运行程序,必须先成功启动加密狗。图5.1.11(2) 主要代码:注:把加密狗所提供的DLL文件(本实验为Rockey2.dll)加载到程序的BinDebug目录下。using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using S
5、ystem.Runtime.InteropServices;namespace DogTestpublicpartialclassForm1 : Form public Form1() InitializeComponent(); #region引用加密狗所提供的接口 DllImport(Rockey2.dll)staticexternint RY2_Find(); DllImport(Rockey2.dll)staticexternint RY2_Open(int mode, Int32 uid, refInt32 hid); DllImport(Rockey2.dll)staticexte
6、rnvoid RY2_Close(int handle); DllImport(Rockey2.dll)staticexternint RY2_GenUID(int handle, refInt32 uid, String seed, int isProtect); DllImport(Rockey2.dll)staticexternint RY2_Read(int handle, int block_index, StringBuilder buffer512); DllImport(Rockey2.dll)staticexternint RY2_Write(int handle, int
7、block_index, String buffer512); #endregion/启动按钮的事件代码privatevoid Btn_start_Click(object sender, EventArgs e) String strinfo;int ret = 0;Int32 handle = 0;Int32 hid = 0;Int32 uid = 0;String seed, Writebuff;Char cRead = 0;string ReadBuff = newstring(cRead, 512);/查找 ret = RY2_Find();if (ret = 0) listBox1
8、.Items.Add(Not Find Rockey2!);return; listBox1.Items.Add(Find Rockey2 1!);/打开 ret = RY2_Open(0, 0, ref hid);if (ret != 0) strinfo = Err : + handle; listBox1.Items.Add(strinfo);return; handle = ret; strinfo = Rockey2 : + hid; listBox1.Items.Add(strinfo);/取得UID seed = Rockey2; ret = RY2_GenUID(handle,
9、 ref uid, seed, 0); strinfo = Gen Uid: + uid; listBox1.Items.Add(strinfo);/关闭 RY2_Close(handle); strinfo = Close Rockey2!; listBox1.Items.Add(strinfo);/查找,发现 ret = RY2_Find();/打开 ret = RY2_Open(1, uid, ref hid); handle = ret;/写入数据 Writebuff = Welcome to used Rockey2!; ret = RY2_Write(handle, 0, Writ
10、ebuff); strinfo = Write Data: + Welcome to used Rockey2!; listBox1.Items.Add(strinfo);/读取数据StringBuilder retbuff = newStringBuilder(0, 512); ret = RY2_Read(handle, 0, retbuff); strinfo = Read Data: + retbuff.ToString(); listBox1.Items.Add(strinfo);DialogResult dr = MessageBox.Show(加密狗已经成功启动!, xiaoxi
11、, MessageBoxButtons.OK);if (dr = DialogResult.OK) WorkMain work = newWorkMain(); work.Show(); privatevoid Btn_clear_Click(object sender, EventArgs e) /清空按钮的事件代码 listBox1.Items.Clear(); (3) 运行此实例的界面如果没有正确加载加密狗,程序会告诉我们没有发现加密狗,如图5.1.12所示。图5.1.12如果正确加载加密狗,程序会有相应提示,如图5.1.13所示。图5.1.13点击“确定”按钮后,进入工作页面,如图5.
12、1.14所示。图5.1.14【实验思考】根据自己的硬件不同,试编写程序通过加密狗来控制此程序的运行;通过加密狗来控制所编程序的使用人数。利用BouncyCastle API加密编程实验【实验内容】使用BouncyCastleAPI 接口进行编程【实验原理】BouncyCastle 是一种用于Java平台的开放源码的轻量级密码包。它支持大量的密码算法,并提供JCE 1.2.1的实现。因为Bouncy Castle被设计成轻量级的,所以从J2SE 1.4 到J2ME(包括 MIDP)平台,它都可以运行,是在MIDP上运行的唯一完整的密码包。后来也提供C#版本的API。Bouncy Castle A
13、PI功能很强大,对于初学者来说,辨认类之间的关系以及方法参数和返回值的正确类型有一定难度。通常,开发人员必须浏览源代码和测试用例来研究Bouncy Castle API的主要功能。可以从http:/www.bouncycastle.org/csharp/ 网站上可以下载最新的C#版本的DLL类库和源代码。【实验环境】运行环境:Microsoft Visual Studio 2005编程语言:C#【实验步骤】一、 利用Bouncy Castle API编码实现对数据的加解密将其DLL类库,添加到自己的项目中,示例的源代码展示如下:(1) 本例的主页面如图5.1.21所示。图5.1.21(2) 其
14、页面的主要代码为:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.IO;namespace BouncyCastleAPIpublicpartialclassTestCrypto : Form string strEn = , ;string strDe = , , ;public TestCrypto(
15、) InitializeComponent(); privatevoid Btn_Source_Click(object sender, EventArgs e) OpenFileDialog filedlg = newOpenFileDialog(); filedlg.Filter = 文本文件(*.txt)|*.txt;if (filedlg.ShowDialog() = DialogResult.OK) txt_Source.Text = filedlg.FileName; privatevoid Btn_target_Click(object sender, EventArgs e)
16、OpenFileDialog filedlg = newOpenFileDialog(); filedlg.Filter = 文本文件(*.txt)|*.txt;if (filedlg.ShowDialog() = DialogResult.OK) txt_target.Text = filedlg.FileName; /加密privatevoid Btn_Encrypt_Click(object sender, EventArgs e) if (txt_Source.Text = | txt_Source.Text = string.Empty) MessageBox.Show(请选择文件!
17、);return; if (txt_target.Text = | txt_target.Text = string.Empty) MessageBox.Show(请选择文件!);return; else strEn0 = txt_Source.Text; strEn1 = txt_target.Text;DESEncrypto.Inin(strEn); /调用 DESEncrypto 类 /解密privatevoid Btn_Decrypt_Click(object sender, EventArgs e) if (txt_Source.Text = | txt_Source.Text =
18、string.Empty) MessageBox.Show(请选择文件!); return; if (txt_target.Text = | txt_target.Text = string.Empty) MessageBox.Show(请选择文件!);return; else strDe0 = txt_Source.Text; strDe1 = txt_target.Text;/相对于当前工作目录string strPath = Directory.GetCurrentDirectory(); string strKey = strPath + + deskey.dat; /密钥文件路径 s
19、trDe2 = strKey;DESEncrypto.Inin(strDe); /调用 DESEncrypto 类 (3) DESEncrypto的具体代码using System;using System.Collections.Generic;using System.Text;using System.IO;using Org.BouncyCastle.Crypto; /请注意命名空间的引用using Org.BouncyCastle.Crypto.Engines;using Org.BouncyCastle.Crypto.Generators;using Org.BouncyCastl
20、e.Crypto.Modes;using Org.BouncyCastle.Crypto.Paddings;using Org.BouncyCastle.Crypto.Parameters;using Org.BouncyCastle.Security;using Org.BouncyCastle.Utilities.Encoders;namespace BouncyCastleAPI publicclassDESEncrypto / true:解密,false:解密privatebool encrypt = true;/句柄privatePaddedBufferedBlockCipher c
21、ipher = null;/输入流(源文件)privateStream inStr = null;/输出流(目标文件)privateStream outStr = null;/密钥privatebyte key = null;publicstaticvoid Inin(string args) bool encrypt = true;string infile = null;string outfile = null;string keyfile = null;if (args.Length 2) encrypt = false; keyfile = args2; DESEncrypto de
22、s = newDESEncrypto(infile, outfile, keyfile, encrypt); des.process(); public DESEncrypto(string infile,string outfile,string keyfile,bool encrypt)this.encrypt = encrypt;tryinStr = File.OpenRead(infile); /打开文件catch (FileNotFoundException)Console.Error.WriteLine(Input file not found +infile+);Environm
23、ent.Exit(1);tryoutStr = File.Create(outfile); /打开文件catch (IOException)Console.Error.WriteLine(Output file not created +outfile+);Environment.Exit(1);if (encrypt)try/创建密钥文件deskey.datSecureRandom sr = newSecureRandom();KeyGenerationParameters kgp = newKeyGenerationParameters(sr,DesEdeParameters.DesEde
24、KeyLength * 8);DesEdeKeyGenerator kg = newDesEdeKeyGenerator();kg.Init(kgp);key = kg.GenerateKey(); Stream keystream = File.Create(keyfile);byte keyhex = Hex.Encode(key);keystream.Write(keyhex, 0, keyhex.Length);keystream.Flush();keystream.Close();catch (IOException)Console.Error.WriteLine(Could not
25、 decryption create key file +keyfile+);Environment.Exit(1);elsetry/读密钥文件deskey.datStream keystream = File.OpenRead(keyfile);int len = (int) keystream.Length;byte keyhex = newbytelen;keystream.Read(keyhex, 0, len);key = Hex.Decode(keyhex);catch (IOException)Console.Error.WriteLine(Decryption key file
26、 not found, + or not valid +keyfile+);Environment.Exit(1);privatevoid process() /填充模式CBC;分组模式Pkcs7 cipher = newPaddedBufferedBlockCipher(newCbcBlockCipher(newDesEdeEngine(); if (encrypt) performEncrypt(key); else performDecrypt(key); try inStr.Close(); outStr.Flush(); outStr.Close(); catch (IOExcept
27、ion) /加密/privatevoid performEncrypt(byte key) cipher.Init(true, newKeyParameter(key); int inBlockSize = 47;int outBlockSize = cipher.GetOutputSize(inBlockSize);byte inblock = newbyteinBlockSize;byte outblock = newbyteoutBlockSize;try int inL;int outL;byte rv = null;while (inL = inStr.Read(inblock, 0
28、, inBlockSize) 0) outL = cipher.ProcessBytes(inblock, 0, inL, outblock, 0);if (outL 0) rv = Hex.Encode(outblock, 0, outL); outStr.Write(rv, 0, rv.Length); outStr.WriteByte(byte)n); try outL = cipher.DoFinal(outblock, 0);if (outL 0) rv = Hex.Encode(outblock, 0, outL); outStr.Write(rv, 0, rv.Length);
29、outStr.WriteByte(byte)n); catch (CryptoException) catch (IOException ioeread) Console.Error.WriteLine(ioeread.StackTrace); /解密/privatevoid performDecrypt(byte key) cipher.Init(false, newKeyParameter(key); StreamReader br = newStreamReader(inStr); try int outL;byte inblock = null;byte outblock = null
30、;string rv = null;while (rv = br.ReadLine() != null) inblock = Hex.Decode(rv); outblock = newbytecipher.GetOutputSize(inblock.Length); outL = cipher.ProcessBytes(inblock, 0, inblock.Length, outblock, 0);if (outL 0) outStr.Write(outblock, 0, outL); try outL = cipher.DoFinal(outblock, 0);if (outL 0) o
31、utStr.Write(outblock, 0, outL); catch (CryptoException) catch (IOException ioeread) Console.Error.WriteLine(ioeread.StackTrace); 二、 程序运行效果(1) “明文.txt”文件的内容为:12345678,如图5.1.22所示;“密文.txt”和“解密后的文件.txt“均为空。图5.1.22(2) 通过程序进行加密,如图5.1.23所示。图5.1.23(3) 加密后“密文.txt”内容如图5.1.24所示。图5.1.24(4) 通过程序对“密文.txt“进行解密,如图5
32、.1.25所示。图5.1.25(5) 解密后“解密后的文件.txt“文件的内容如图5.1.26所示。图5.1.26(6) 观察比较其加密前后相关文件的内容。【实验思考】了解Bouncy Castle API接口的使用,试用其接口实现相关的加密算法,如ASE,3DES等加密算法;了解并学习Bouncy Castle API接口中的其它模块的功能和应用。利用Crypte API加密编程实验【实验内容】使用CryptoAPI接口进行编程【实验原理】微软公司在NT4.0以上版本中提供了一套完整的CryptoAPI的函数,其功能是为应用程序开发者提供在Win32环境下使用加密、验证等安全服务时的标准加密
33、接口。用户在对软件进行保护的时候可以直接利用CryptoAPI来完成这些工作,比如计算注册码,检查程序的完整性等。用这些的API进行加密解密的时候,只需要知道如何去应用它们,而不必知道它们的底层实现。CryptoAPI处于应用程序和CSP(cryptographic service provider)之间,如图5.1.31所示:图5.1.31CryptoAPI共有五部分组成:简单消息函数(Simplified Message Functions)、低层消息函数(Low-level Message Functions)、基本加密函数(Base Cryptographic Functions)、证
34、书编解码函数(Certificate Encode/Decode Functions)和证书库管理函数(Certificate Store Functions)。其中前三者可用于对敏感信息进行加密或签名处理,可保证网络传输信息的私有性;后两者通过对证书的使用,可保证网络信息交流中的认证性。大家也许对CSP还比较迷惑。其实CSP是真正实行加密的独立模块,它既可以由软件实现也可以由硬件实现。但是它必须符合CryptoAPI接口的规范。每个CSP都有一个名字和一个类型。每个CSP的名字是唯一的,这样便于CryptoAPI找到对应的CSP。目前支持CryptoAPI的Windows系统有:Window
35、s 95 OSR2、Windows NT SP3及后续版本、Windows 98、Windows 2000等。CryptoAPI的配置信息存储在注册表中,包括如下密钥:HKEY_LOCAL_MACHINESOFTWAREMicrosoft Cryptography Defaults和HKEY_CURRENT_USER SoftwareMicrosoftCryptographyProviders。CryptoAPI使用两种密钥:会话密钥与公共/私人密钥对。会话密钥使用相同的加密和解密密钥,这种算法较快,但必须保证密钥的安全传递。公共/私人密钥对使用一个公共密钥和一个私人密钥,私人密钥只有专人才能
36、使用,公共密钥可以广泛传播。如果密钥对中的一个用于加密,另一个一定用于解密。公共/私人密钥对算法很慢,一般只用于加密小批数据,例如用于加密会话密钥。CryptoAPI支持两种基本的编码方法:流式编码和块编码。流式编码在明码文本的每一位上创建编码位,速度较快,但安全性较低。块编码在一个完整的块(一般为64位)上工作,需要使用填充的方法对要编码的数据进行舍入,以组成多个完整的块。这种算法速度较慢,但更安全。【实验环境】运行环境:Microsoft Visual Studio 2005编程语言:C+【实验步骤】一、 运用CryptoAPI编程的运行环境首先需要Crypt32.lib,将它加到project-setting-link下面,也可以在程序中用#pragmacomment(lib,crypt32.lib)加入。在程序开头,要加入两个头文件Windows.h和Wincrypt.h,和一个#defineMY_ENCODING_TYPE(PKCS_7_ASN_ENCODING|X509_ASN_ENCODING)。二、 利用CryptoAPI实现对数据的加解密(1) 先加入一个头文件targetver.h,文件内容如下:#pragmaonce/