1 #Region "Microsoft.VisualBasic::56424bbe3437e0f8e2bdd340bb3cb693, Microsoft.VisualBasic.Core\ApplicationServices\Tools\Network\SSL\Certificate.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Class Certificate
35     
36     '         Properties: AppDomain, hash, IsPublicToken, PrivateKey, uid
37     
38     '         Constructor: (+4 OverloadsSub New
39     '         Function: __decrypt, __load, (+2 Overloads) CopyFrom, (+2 Overloads) Decrypt, DecryptString
40     '                   (+2 Overloads) Encrypt, EncryptData, (+2 OverloadsInstall, InstallPublicToken, PublicEncrypt
41     '                   ToString
42     
43     
44     ' /********************************************************************************/
45
46 #End Region
47
48 Imports Microsoft.VisualBasic.Emit.CodeDOM_VBC
49 Imports Microsoft.VisualBasic.Net.Protocols
50 Imports Microsoft.VisualBasic.SecurityString
51
52 Namespace Net.SSL
53
54     ''' <summary>
55     ''' 应用程序的完整性验证和用户身份的验证
56     ''' </summary>
57     Public Class Certificate : Implements SecurityString.SecurityStringModel.ISecurityStringModel
58
59         Protected _SHA256 As SecurityString.SHA256
60
61         ''' <summary>
62         ''' 私有密匙
63         ''' </summary>
64         ''' <returns></returns>
65         Public Overridable ReadOnly Property PrivateKey As String
66             Get
67                 Return _SHA256.strPassphrase
68             End Get
69         End Property
70
71         ''' <summary>
72         ''' <see cref="Guid"/>计算出来的哈希值只能为负数,现在约定,当这个属性为0的时候就认为这个证书是公共密匙,
73         ''' 这个一般是使用用户的账号所计算出来的哈希值
74         ''' </summary>
75         ''' <returns></returns>
76         Public ReadOnly Property uid As Long
77             Get
78                 Return _uid
79             End Get
80         End Property
81
82         ''' <summary>
83         ''' 初始化继承类所需要的
84         ''' </summary>
85         Protected _uid As Long
86
87         Public ReadOnly Property IsPublicToken As Boolean
88             Get
89                 Return uid = 0L
90             End Get
91         End Property
92
93         ''' <summary>
94         ''' 与<see cref="uid"/>属性所不同的是,这个属性是<see cref="privatekey"/>的哈希值,
95         ''' 通常这个哈希值在请求resultful WebAPI的时候用来作为用户的唯一标识
96         ''' </summary>
97         ''' <returns></returns>
98         Public ReadOnly Property hash As Long
99
100         Public Overrides Function ToString() As String
101             Return $"[{NameOf(Certificate)}] {uid} {_SHA256.Passphrase}"
102         End Function
103
104         ''' <summary>
105         ''' 请注意这个构造方法会计算一遍密码的哈希值,假若需要直接进行初始化,请使用<see cref="Install"/>方法
106         ''' </summary>
107         ''' <param name="hash">用户的私有密匙</param>
108         ''' <param name="uid">大小写无关的</param>
109         Sub New(hash As String, uid As String)
110             hash = SecurityString.MD5Hash.GetMd5Hash(hash)
111             _SHA256 = New SecurityString.SHA256(hash, SALT)
112             Me._uid = SecurityString.MD5Hash.ToLong(SecurityString.MD5Hash.GetMd5Hash(uid.ToLower))
113             Me.hash = SecurityString.MD5Hash.ToLong(hash)
114         End Sub
115
116         ''' <summary>
117         ''' 
118         ''' </summary>
119         ''' <param name="hash">原始的密码,会在这个构造函数之中计算为哈希值产生新的密码。</param>
120         ''' <param name="uid">客户端所发送过来的使用哈希值计算出来的唯一标识符</param>
121         Sub New(hash As String, uid As Long)
122             hash = SecurityString.MD5Hash.GetMd5Hash(hash)
123             _SHA256 = New SecurityString.SHA256(hash, SALT)
124             Me._uid = uid
125             Me.hash = SecurityString.MD5Hash.ToLong(hash)
126         End Sub
127
128         ''' <summary>
129         ''' 从服务器上面所返回来的握手数据
130         ''' </summary>
131         ''' <param name="handshakeData"></param>
132         Sub New(handshakeData As RequestStream)
133             Dim hash As String = SecurityString.MD5Hash.GetMd5Hash(handshakeData.GetUTF8String)
134             _SHA256 = New SHA256(hash, SALT)
135             Me._uid = handshakeData.uid
136             Me.hash = SecurityString.MD5Hash.ToLong(hash)
137         End Sub
138
139         ''' <summary>
140         ''' 这个构造函数不再计算哈希值而是直接初始化
141         ''' </summary>
142         ''' <param name="hash">必须是md5哈希值</param>
143         Protected Sub New(hash As String)
144             _SHA256 = New SHA256(hash, SALT)
145             Me.hash = SecurityString.MD5Hash.ToLong(hash)
146         End Sub
147
148         Const SALT As String = "88888888"
149
150         Public Shared Function CopyFrom(CA As SSL.Certificate, uid As StringAs SSL.Certificate
151             Dim hashCode As String = SecurityString.MD5Hash.ToLong(SecurityString.MD5Hash.GetMd5Hash(uid.ToLower))
152             Return New SSL.Certificate(CA._SHA256.Passphrase) With {._uid = hashCode}
153         End Function
154
155         Public Shared Function CopyFrom(CA As SSL.Certificate, uid As LongAs SSL.Certificate
156             Return New SSL.Certificate(CA._SHA256.Passphrase) With {._uid = uid}
157         End Function
158
159         ''' <summary>
160         ''' 不计算密匙<paramref name="privateKey"/>哈希值而是直接安装
161         ''' </summary>
162         ''' <param name="privateKey"></param>
163         ''' <param name="uid"></param>
164         ''' <returns></returns>
165         Public Shared Function Install(privateKey As String, uid As LongAs SSL.Certificate
166             Return New SSL.Certificate(privateKey) With {._uid = uid}
167         End Function
168
169         Public Shared Function InstallPublicToken(publicKey As StringAs SSL.Certificate
170             Call $"Install public token ssl certificate.".__DEBUG_ECHO
171             Return New SSL.Certificate(publicKey)
172         End Function
173
174         ''' <summary>
175         ''' 函数会根据uid的值来设定协议为私有密匙还是公共密匙
176         ''' </summary>
177         ''' <param name="request"></param>
178         ''' <returns></returns>
179         Public Overridable Function Encrypt(request As RequestStream) As RequestStream
180             Dim byteData As Byte() = request.Serialize
181             Dim Protocol = If(IsPublicToken, RequestStream.Protocols.SSL_PublicToken, RequestStream.Protocols.SSL)
182             byteData = _SHA256.Encrypt(byteData)
183             request = New RequestStream(RequestStream.SYS_PROTOCOL, Protocol, byteData) With {.uid = uid}
184
185             Return request
186         End Function
187
188         ''' <summary>
189         ''' 强制将协议设定为公共密匙加密
190         ''' </summary>
191         ''' <param name="request"></param>
192         ''' <returns></returns>
193         Public Overridable Function PublicEncrypt(request As RequestStream) As RequestStream
194             Dim byteData As Byte() = request.Serialize
195             byteData = _SHA256.Encrypt(byteData)
196             request = New RequestStream(RequestStream.SYS_PROTOCOL, RequestStream.Protocols.SSL_PublicToken, byteData) With {.uid = uid}
197
198             Return request
199         End Function
200
201         ''' <summary>
202         ''' <see cref="Decrypt(Byte())"/> <see cref="RequestStream.ChunkBuffer"/>
203         ''' </summary>
204         ''' <param name="request"></param>
205         ''' <returns></returns>
206         Public Overridable Function Decrypt(request As RequestStream) As RequestStream
207             Return __decrypt(request, _SHA256)
208         End Function
209
210         Protected Shared Function __decrypt(request As RequestStream, sha256 As SecurityString.SHA256) As RequestStream
211             Dim byteData As Byte() = request.ChunkBuffer
212             byteData = sha256.Decrypt(byteData)
213             request = New RequestStream(byteData)
214             Return request
215         End Function
216
217         ''' <summary>
218         ''' 检查应用程序的完整性
219         ''' </summary>
220         ''' <returns></returns>
221         Public Shared ReadOnly Property AppDomain As Certificate = Install(App.ExecutablePath, publicToken:=True)
222
223         ''' <summary>
224         ''' 
225         ''' </summary>
226         ''' <param name="App">可执行程序的文件路径</param>
227         ''' <returns></returns>
228         Public Shared Function Install(App As StringOptional publicToken As Boolean = FalseAs Certificate
229             Call Console.WriteLine()
230             Call Console.WriteLine()
231             Call $"**************************************************[ INSTALL {NameOf(Certificate)}:  {App.ToFileURL}]****************************************************************".__DEBUG_ECHO
232
233             Dim Modules = (From [module] As String
234                            In __load(App).AsParallel
235                            Select [module], hash = SecurityString.MD5Hash.GetFileHashString([module])
236                            Order By hash Ascending).ToArray '????已经排过序了,为什么顺序还是不一样
237             For Each [module] In Modules
238                 Call $"   Installed Module ==> {[module].ToString}".__DEBUG_ECHO
239             Next
240             Dim caHashString As String = String.Join("+", (From [mod] In ModuleSelect [mod].hash).ToArray)
241             Dim CA As Certificate = If(publicToken, Certificate.InstallPublicToken(SecurityString.GetMd5Hash(caHashString)), New Certificate(caHashString, NameOf(App)))
242
243             Call Console.WriteLine()
244             Call Console.WriteLine()
245             Call $"**************************************************[ END OF INSTALL {NameOf(Certificate)} ==> {CA.ToString}]****************************************************************".__DEBUG_ECHO
246
247             Return CA
248         End Function
249
250         Private Shared Function __load(path As StringAs String()
251             Dim assembly As System.Reflection.Assembly
252             Try
253                 assembly = System.Reflection.Assembly.LoadFile(FileIO.FileSystem.GetFileInfo(path).FullName)
254             Catch ex As Exception
255                 Throw New Exception(path.ToFileURL, ex)
256             End Try
257             Dim refListBuffer = GetReferences(assembly:=assembly, removeSystem:=True)
258
259             Return refListBuffer
260         End Function
261
262         Public Overridable Function Decrypt(input() As ByteAs Byte() Implements SecurityStringModel.ISecurityStringModel.Decrypt
263             Return _SHA256.Decrypt(input)
264         End Function
265
266         Public Overridable Function DecryptString(text As StringAs String Implements SecurityStringModel.ISecurityStringModel.DecryptString
267             Return _SHA256.DecryptString(text)
268         End Function
269
270         Public Overridable Function Encrypt(input() As ByteAs Byte() Implements SecurityStringModel.ISecurityStringModel.Encrypt
271             Return _SHA256.Encrypt(input)
272         End Function
273
274         Public Overridable Function EncryptData(text As StringAs String Implements SecurityStringModel.ISecurityStringModel.EncryptData
275             Return _SHA256.EncryptData(text)
276         End Function
277     End Class
278 End Namespace