SecurityHelper是以前写了用于远程业务通讯安全的一个帮助类,功能也很简单,还有需要改进的地方,但当时觉得能用了就没再管它。大家如果有什么建议将不胜感激。
对了,请教一个问题,目前这些代码虽然都是我写的,但用在了公司的项目中。这会不会违背了职业道德?我的理解是这些代码都是比较通用的部分,凡是涉及具体业务的内容一律剔除,不涉及公司的商业秘密,也不可能因此对业务系统造成损害。另一方面,这类代码完全可以公开了接受公众检验,提高质量。当然这只是个人看法,如果大部分人认为这样做不合适那我会处理掉。
1
using
System;
2
using
System.IO;
3
using
System.Security.Cryptography;
4
using
System.Text;
5
using
System.Xml;
6![None.gif](/Images/OutliningIndicators/None.gif)
7
namespace
NHTSS.Framework.Common
8![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
9![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
10
/// 为系统提供加密、解密功能的帮助类。
11
/// </summary>
12
public sealed class SecurityHelper
13![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
14![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
15
/// 内部构造,不允许实例化该类。
16
/// </summary>
17
internal SecurityHelper()
18![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
19
}
20![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
21![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
22
/// 加密文本。
23
/// </summary>
24
/// <remarks>
25
/// 使用RSA算法。
26
/// </remarks>
27
/// <param name="xmlKeyPath">密钥文件(XML)路径。</param>
28
/// <param name="strMessage">待加密的文本。</param>
29
/// <returns>密文。</returns>
30
public static string RSAEncryptString(string xmlKeyPath, string strMessage)
31![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
32
if (!File.Exists(xmlKeyPath))
33![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
34
throw new System.IO.FileNotFoundException("加密密钥文件不存在。");
35
}
36
try
37![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
38
UnicodeEncoding myByteConverter = new UnicodeEncoding();
39![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
40
byte[] dataToEncrypt = myByteConverter.GetBytes(strMessage);
41
byte[] encryptedData;
42![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
43
using (RSACryptoServiceProvider myRSACSP = new RSACryptoServiceProvider())
44![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
45
XmlDocument myDoc = new XmlDocument();
46
myDoc.Load(xmlKeyPath);
47
myRSACSP.FromXmlString(myDoc.OuterXml);
48![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
49
encryptedData = myRSACSP.Encrypt(dataToEncrypt, false);
50
}
51
return Convert.ToBase64String(encryptedData);
52
}
53
catch (System.Exception ex)
54![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
55
throw new ApplicationException("加密失败!\r\n" + ex.Message, ex);
56
}
57
}
58![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
59![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
60
/// 解密文本。
61
/// </summary>
62
/// <remarks>
63
/// 使用RSA算法。
64
/// </remarks>
65
/// <param name="xmlKeyPath">密钥文件(XML)路径。</param>
66
/// <param name="strCryptograph">待解密的文本。</param>
67
/// <returns>明文。</returns>
68
public static string RSADecryptString(string xmlKeyPath, string strCryptograph)
69![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
70
if (!File.Exists(xmlKeyPath))
71![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
72
throw new System.IO.FileNotFoundException("解密密钥文件不存在。");
73
}
74![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
75
try
76![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
77
byte[] dataToDecrypt = Convert.FromBase64String(strCryptograph);
78
byte[] decryptedData;
79![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
80
using (RSACryptoServiceProvider myRSACSP = new RSACryptoServiceProvider())
81![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
82
XmlDocument myDoc = new XmlDocument();
83
myDoc.Load(xmlKeyPath);
84
myRSACSP.FromXmlString(myDoc.OuterXml);
85![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
86
decryptedData = myRSACSP.Decrypt(dataToDecrypt, false);
87
}
88
UnicodeEncoding myByteConverter = new UnicodeEncoding();
89
return myByteConverter.GetString(decryptedData);
90
}
91
catch (System.Exception ex)
92![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
93
throw new ApplicationException("解密失败!\r\n" + ex.Message, ex);
94
}
95
}
96![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
97![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
98![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
99
/// 对文本进行签名。
100
/// </summary>
101
/// <param name="xmlPrivateKeyPath">签名密钥(XML)的路径。</param>
102
/// <param name="strMessage">待签名的文本。</param>
103
/// <returns>签名。</returns>
104
public static string RSASignString(string xmlPrivateKeyPath, string strMessage)
105![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
106
if (!File.Exists(xmlPrivateKeyPath))
107![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
108
throw new System.IO.FileNotFoundException("签名密钥文件不存在。");
109
}
110![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
111
try
112![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
113
UnicodeEncoding myByteConverter = new UnicodeEncoding();
114![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
115
byte[] dataToSign = myByteConverter.GetBytes(strMessage);
116
byte[] signedData;
117![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
118
using (RSACryptoServiceProvider myRSACSP = new RSACryptoServiceProvider())
119![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
120
XmlDocument myDoc = new XmlDocument();
121
myDoc.Load(xmlPrivateKeyPath);
122
myRSACSP.FromXmlString(myDoc.OuterXml);
123![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
124
signedData = myRSACSP.SignData(dataToSign, new SHA1CryptoServiceProvider());
125
}
126
return myByteConverter.GetString(signedData);
127
}
128
catch (System.Exception ex)
129![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
130
throw new ApplicationException("签名失败!\r\n" + ex.Message, ex);
131
}
132
}
133![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
134![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
135
/// 验证签名。
136
/// </summary>
137
/// <param name="xmlPublicKeyPath">验证签名的公钥文件(XML)路径。</param>
138
/// <param name="strMessage">消息原文。</param>
139
/// <param name="strSignature">签名数据。</param>
140
/// <returns>验证结果。</returns>
141
public static bool RSAVerifySignString(string xmlPublicKeyPath, string strMessage, string strSignature)
142![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
143
if (!File.Exists(xmlPublicKeyPath))
144![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
145
throw new System.IO.FileNotFoundException("验证密钥文件不存在。");
146
}
147![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
148
try
149![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
150
UnicodeEncoding myByteConverter = new UnicodeEncoding();
151![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
152
byte[] dataToSign = myByteConverter.GetBytes(strMessage);
153
byte[] signedData = myByteConverter.GetBytes(strSignature);
154![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
155
bool bolResult = false;
156
using (RSACryptoServiceProvider myRSACSP = new RSACryptoServiceProvider())
157![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
158
XmlDocument myDoc = new XmlDocument();
159
myDoc.Load(xmlPublicKeyPath);
160
myRSACSP.FromXmlString(myDoc.OuterXml);
161![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
162
bolResult = myRSACSP.VerifyData(dataToSign, new SHA1CryptoServiceProvider(), signedData);
163
}
164
return bolResult;
165
}
166
catch (System.Exception ex)
167![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
168
throw new ApplicationException("验证签名失败!\r\n" + ex.Message, ex);
169
}
170
}
171
}
172![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
173![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
174
/// 用来生成密钥对。
175
/// </summary>
176
/// <remarks>
177
/// 采用RSA算法。XML文件表示。
178
/// </remarks>
179
public class KeyGenerator
180![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
181
private XmlDocument _privateKey;
182
private XmlDocument _publicKey;
183![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
184![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
185
/// 缺省构造,生成密钥对。
186
/// </summary>
187
public KeyGenerator()
188![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
189
//Use RSA Provider to generate public / private key pair
190
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
191![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
192
// create the xml-docs
193
_privateKey = new XmlDocument();
194
_publicKey = new XmlDocument();
195![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
196
// use RSA convenience methods to stuff public and private keys into dom's
197
_privateKey.LoadXml(RSA.ToXmlString(true));
198
_publicKey.LoadXml(RSA.ToXmlString(false));
199
}
200
}
201![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
202![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
203
/// 私钥。
204
/// </summary>
205
public XmlDocument PrivateKey
206![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
207![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _privateKey; }
208
}
209![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
210![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
211
/// 公钥。
212
/// </summary>
213
public XmlDocument PublicKey
214![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
215![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _publicKey; }
216
}
217![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
218![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
219
/// 生成加密型强随机非零值序列作为会话令牌。
220
/// </summary>
221
/// <remarks>
222
/// 使用弱加密,16位。
223
/// </remarks>
224
/// <returns>随机的令牌。</returns>
225
public static string GenToken()
226![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
227
byte[] random = new Byte[16];
228
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
229
rng.GetNonZeroBytes(random);
230
UnicodeEncoding myByteConverter = new UnicodeEncoding();
231
return myByteConverter.GetString(random);
232
}
233
}
234
}
![None.gif](/Images/OutliningIndicators/None.gif)
2
![None.gif](/Images/OutliningIndicators/None.gif)
3
![None.gif](/Images/OutliningIndicators/None.gif)
4
![None.gif](/Images/OutliningIndicators/None.gif)
5
![None.gif](/Images/OutliningIndicators/None.gif)
6
![None.gif](/Images/OutliningIndicators/None.gif)
7
![None.gif](/Images/OutliningIndicators/None.gif)
8
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
9
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
10
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
11
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
12
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
13
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
14
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
15
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
16
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
17
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
18
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
19
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
20
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
21
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
22
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
23
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
24
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
25
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
26
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
27
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
28
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
29
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
30
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
31
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
32
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
33
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
34
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
35
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
36
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
37
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
38
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
39
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
40
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
41
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
42
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
43
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
44
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
45
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
46
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
47
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
48
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
49
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
50
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
51
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
52
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
53
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
54
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
55
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
56
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
57
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
58
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
59
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
60
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
61
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
62
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
63
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
64
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
65
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
66
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
67
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
68
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
69
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
70
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
71
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
72
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
73
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
74
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
75
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
76
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
77
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
78
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
79
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
80
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
81
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
82
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
83
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
84
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
85
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
86
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
87
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
88
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
89
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
90
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
91
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
92
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
93
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
94
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
95
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
96
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
97
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
98
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
99
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
100
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
101
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
102
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
103
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
104
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
105
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
106
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
107
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
108
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
109
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
110
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
111
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
112
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
113
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
114
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
115
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
116
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
117
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
118
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
119
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
120
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
121
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
122
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
123
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
124
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
125
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
126
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
127
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
128
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
129
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
130
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
131
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
132
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
133
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
134
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
135
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
136
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
137
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
138
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
139
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
140
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
141
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
142
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
143
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
144
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
145
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
146
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
147
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
148
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
149
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
150
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
151
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
152
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
153
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
154
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
155
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
156
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
157
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
158
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
159
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
160
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
161
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
162
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
163
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
164
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
165
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
166
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
167
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
168
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
169
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
170
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
171
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
172
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
173
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
174
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
175
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
176
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
177
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
178
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
179
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
180
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
181
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
182
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
183
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
184
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
185
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
186
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
187
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
188
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
189
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
190
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
191
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
192
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
193
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
194
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
195
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
196
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
197
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
198
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
199
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
200
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
201
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
202
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
203
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
204
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
205
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
206
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
207
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
208
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
209
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
210
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
211
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
212
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
213
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
214
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
215
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
216
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
217
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
218
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
219
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
220
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
221
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
222
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
223
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
224
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
225
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
226
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
227
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
228
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
229
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
230
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
231
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
232
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
233
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
234
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)