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