1 #Region "Microsoft.VisualBasic::a02842f1a9fece5b27e2130dfce93204, Microsoft.VisualBasic.Core\Extensions\Security\SHA.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 SHA256
35     
36     '         Properties: CertificateSigned, Passphrase
37     
38     '         Constructor: (+1 OverloadsSub New
39     '         Function: Decrypt, DecryptString, Deserialization, Encrypt, EncryptData
40     '                   (+2 OverloadsGetDynamicsCertification, Serialization, ToString
41     
42     
43     ' /********************************************************************************/
44
45 #End Region
46
47 Imports System.Security
48 Imports System.Security.Cryptography
49 Imports System.IO
50 Imports System.Runtime.InteropServices
51 Imports System.Text.RegularExpressions
52 Imports System.Text
53 Imports Microsoft.VisualBasic.Linq.Extensions
54
55 Namespace SecurityString
56
57     ''' <summary>
58     ''' Derives a SHA256 key from a password using an extension of the PBKDF1 algorithm.
59     ''' </summary>
60     ''' <remarks></remarks>
61     Public Class SHA256 : Inherits SecurityStringModel
62
63         Const hashAlgorithm As String = "SHA1"
64         Const keySize As Integer = 256
65         Const passwordIterations As Integer = 2
66
67         ' Convert strings defining encryption key characteristics into byte
68         ' arrays. Let us assume that strings only contain ASCII codes.
69         If strings include Unicode characters, use Unicode, UTF7, or UTF8
70         ' encoding.
71
72         Dim initVectorBytes As Byte()
73         Dim saltValueBytes As Byte()
74
75         ''' <summary>
76         ''' 
77         ''' </summary>
78         ''' <param name="password"></param>
79         ''' <param name="saltValue">8 Bytes</param>
80         Sub New(password As String, saltValue As String)
81             Const initVector = "@1B2c3D4e5F6g7H8"
82
83             Me.strPassphrase = password
84             Me.initVectorBytes = Encoding.ASCII.GetBytes(initVector)
85             Me.saltValueBytes = Encoding.ASCII.GetBytes(saltValue)
86         End Sub
87
88         Public Overrides Function ToString() As String
89             Return MyBase.ToString() & $"//  {NameOf(saltValueBytes)}:={String.Join("", saltValueBytes.Select(Of String)(Function(b) CStr(b)).ToArray)}"
90         End Function
91
92         Public ReadOnly Property Passphrase As String
93             Get
94                 Return Me.strPassphrase
95             End Get
96         End Property
97
98         Public Overloads Overrides Function Decrypt(cipherTextBytes As Byte()) As Byte()
99
100             ' First, we must create a password, from which the key will be
101             ' derived. This password will be generated from the specified
102             ' passphrase and salt value. The password will be created using
103             ' the specified hash algorithm. Password creation can be done in
104             ' several iterations.
105
106             Dim password As New PasswordDeriveBytes(strPassphrase, saltValueBytes, hashAlgorithm, passwordIterations)
107
108             ' Use the password to generate pseudo-random bytes for the encryption
109             ' key. Specify the size of the key in bytes (instead of bits).
110 #Disable Warning
111             Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
112 #Enable Warning
113             ' Create uninitialized Rijndael encryption object.
114
115             Dim symmetricKey As New RijndaelManaged()
116
117             ' It is reasonable to set encryption mode to Cipher Block Chaining
118             ' (CBC). Use default options for other symmetric key parameters.
119
120             symmetricKey.Mode = CipherMode.CBC
121
122             ' Generate decryptor from the existing key bytes and initialization
123             ' vector. Key size will be defined based on the number of the key
124             ' bytes.
125
126             Dim decryptor As ICryptoTransform = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)
127
128             ' Define memory stream which will be used to hold encrypted data.
129
130             Dim memoryStream As New MemoryStream(cipherTextBytes)
131
132             ' Define cryptographic stream (always use Read mode for encryption).
133
134             Dim cryptoStream As New CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)
135
136             ' Since at this point we don't know what the size of decrypted data
137             ' will be, allocate the buffer long enough to hold ciphertext;
138             ' plaintext is never longer than ciphertext.
139
140             Dim plainTextBytes As Byte() = New Byte(cipherTextBytes.Length - 1) {}
141
142             ' Start decrypting.
143
144             Dim decryptedByteCount As Integer = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
145
146             ' Close both streams.
147
148             memoryStream.Close()
149             cryptoStream.Close()
150
151             ' Convert decrypted data into a string.
152             Let us assume that the original plaintext string was UTF8-encoded.
153
154             Return plainTextBytes
155         End Function
156
157         ''' <summary>
158         ''' 字符串的解密方法
159         ''' </summary>
160         ''' <param name="cipherText"></param>
161         ''' <returns></returns>
162         ''' <remarks></remarks>
163         Public Overrides Function DecryptString(cipherText As StringAs String
164
165             ' Convert our ciphertext into a byte array.
166
167             Dim cipherTextBytes As Byte() = Convert.FromBase64String(cipherText)
168
169             ' First, we must create a password, from which the key will be
170             ' derived. This password will be generated from the specified
171             ' passphrase and salt value. The password will be created using
172             ' the specified hash algorithm. Password creation can be done in
173             ' several iterations.
174
175             Dim password As New PasswordDeriveBytes(strPassphrase, saltValueBytes, hashAlgorithm, passwordIterations)
176
177             ' Use the password to generate pseudo-random bytes for the encryption
178             ' key. Specify the size of the key in bytes (instead of bits).
179 #Disable Warning
180             Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
181 #Enable Warning
182             ' Create uninitialized Rijndael encryption object.
183
184             Dim symmetricKey As New RijndaelManaged()
185
186             ' It is reasonable to set encryption mode to Cipher Block Chaining
187             ' (CBC). Use default options for other symmetric key parameters.
188
189             symmetricKey.Mode = CipherMode.CBC
190
191             ' Generate decryptor from the existing key bytes and initialization
192             ' vector. Key size will be defined based on the number of the key
193             ' bytes.
194
195             Dim decryptor As ICryptoTransform = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)
196
197             ' Define memory stream which will be used to hold encrypted data.
198
199             Dim memoryStream As New MemoryStream(cipherTextBytes)
200
201             ' Define cryptographic stream (always use Read mode for encryption).
202
203             Dim cryptoStream As New CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)
204
205             ' Since at this point we don't know what the size of decrypted data
206             ' will be, allocate the buffer long enough to hold ciphertext;
207             ' plaintext is never longer than ciphertext.
208
209             Dim plainTextBytes As Byte() = New Byte(cipherTextBytes.Length - 1) {}
210
211             ' Start decrypting.
212
213             Dim decryptedByteCount As Integer = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
214
215             ' Close both streams.
216
217             memoryStream.Close()
218             cryptoStream.Close()
219
220             ' Convert decrypted data into a string.
221             Let us assume that the original plaintext string was UTF8-encoded.
222             Dim plainText As String = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount)
223             Return plainText
224         End Function
225
226         Public Overloads Overrides Function Encrypt(plainTextBytes() As ByteAs Byte()
227             Dim password As New PasswordDeriveBytes(strPassphrase, saltValueBytes, hashAlgorithm, passwordIterations)
228 #Disable Warning
229             Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
230 #Enable Warning
231             Dim symmetricKey As New RijndaelManaged()
232
233             symmetricKey.Mode = CipherMode.CBC
234
235             Dim encryptor As ICryptoTransform = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)
236             Dim memoryStream As New MemoryStream()
237             Dim cryptoStream As New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
238
239             cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
240             cryptoStream.FlushFinalBlock()
241
242             Dim cipherTextBytes As Byte() = memoryStream.ToArray()
243
244             memoryStream.Close()
245             cryptoStream.Close()
246
247             Return cipherTextBytes
248         End Function
249
250         Public Function Serialization(data As Byte()) As String
251             data = Encrypt(data)
252             Return System.Text.Encoding.Unicode.GetString(data)
253         End Function
254
255         Public Function Deserialization(data As StringAs Byte()
256             Dim Buffer As Byte() = System.Text.Encoding.Unicode.GetBytes(data)
257             Return Decrypt(Buffer)
258         End Function
259
260         ''' <summary>
261         ''' Encrypt the plain text string.
262         ''' </summary>
263         ''' <param name="plainText"></param>
264         ''' <returns></returns>
265         Public Overrides Function EncryptData(plainText As StringAs String
266
267             Dim plainTextBytes As Byte() = Encoding.UTF8.GetBytes(plainText)
268             Dim password As New PasswordDeriveBytes(strPassphrase, saltValueBytes, hashAlgorithm, passwordIterations)
269 #Disable Warning
270             Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
271 #Enable Warning
272             Dim symmetricKey As New RijndaelManaged()
273
274             symmetricKey.Mode = CipherMode.CBC
275
276             Dim encryptor As ICryptoTransform = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)
277             Dim memoryStream As New MemoryStream()
278             Dim cryptoStream As New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
279
280             cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
281             cryptoStream.FlushFinalBlock()
282
283             Dim cipherTextBytes As Byte() = memoryStream.ToArray()
284
285             memoryStream.Close()
286             cryptoStream.Close()
287
288             Dim cipherText As String = Convert.ToBase64String(cipherTextBytes)
289
290             Return cipherText
291         End Function
292
293         ''' <summary>
294         ''' The previous key of the sha256 encryption will be expired after the rebuild of this module,
295         ''' so that this method is not working on the statics data storage job.
296         ''' (在本模块进行重新编译之后,原有的密匙将会失效,故这个属性不适合于静态存储加密使用)
297         ''' </summary>
298         ''' <value></value>
299         ''' <returns></returns>
300         ''' <remarks></remarks>
301         Public Shared ReadOnly Property CertificateSigned As SHA256 =
302             New SHA256(password:=Microsoft.VisualBasic.SecurityString.GetFileHashString(GetType(SHA256).Assembly.Location), saltValue:="ATCGCGAT")
303
304         ''' <summary>
305         ''' 双重动态数据签名
306         ''' </summary>
307         ''' <typeparam name="T"></typeparam>
308         ''' <returns></returns>
309         ''' <remarks></remarks>
310         Public Shared Function GetDynamicsCertification(Of T)() As SHA256
311             Return GetDynamicsCertification(GetType(T))
312         End Function
313
314         ''' <summary>
315         ''' 双重动态数据签名
316         ''' </summary>
317         ''' <returns></returns>
318         ''' <remarks></remarks>
319         Public Shared Function GetDynamicsCertification(TypeInfo As Type) As SHA256
320             Dim Password As String = Microsoft.VisualBasic.SecurityString.GetFileHashString(TypeInfo.Assembly.Location)
321             Dim saltValue As String = Microsoft.VisualBasic.SecurityString.GetFileHashString(GetType(SHA256).Assembly.Location)
322             saltValue = Mid(saltValue, 3, 8)
323             Return New SHA256(Password, saltValue)
324         End Function
325     End Class
326 End Namespace