forked from vinicius-stutz/csharp-encryption-lib
/
CryptService.cs
215 lines (174 loc) · 8.57 KB
/
CryptService.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
// TODO: Namespaces, classes and methods are in Portuguese. Feel free to refactor and translate ;).
namespace Criptografia
{
/// <summary>
/// <para>@project csharp.encryption (on GitHub Repositories).</para>
/// <para>@author Vinicius Stutz <http://www.vinicius-stutz.com/>.</para>
/// <para>@version 1.0 of 19 de Mar 2015.</para>
/// <para>@license Under the MIT license <http://opensource.org/licenses/MIT>.</para>
/// <para></para>
/// <para>Description: DLL/Classe de criptgrafia.</para>
/// <para></para>
/// <para>Exemplo de como usar para criptografar:</para>
/// <para>CryptService crip = new CryptService(CryptProvider.DES);</para>
/// <para>crip.Key = "MINHA_CHAVE"; // Esta chave você mesmo é quem escolhe</para>
/// <para>return crip.Criptografar(texto);</para>
/// <para></para>
/// <para>Exemplo de como usar para descriptografar:</para>
/// <para>CryptService crip = new CryptService(CryptProvider.DES);</para>
/// <para>crip.Key = "MINHA_CHAVE"; // Esta chave tem que ser a mesma do texto criptografado</para>
/// <para>return crip.Descriptografar(texto);</para>
/// </summary>
public class CryptService
{
#region Variáveis e Métodos Privados
private string chave = string.Empty;
private CryptProvider provider;
private SymmetricAlgorithm algoritmo;
/// <summary>Inicialização do vetor do algoritmo simétrico</summary>
private void SetIV()
{
switch (provider)
{
case CryptProvider.Rijndael:
algoritmo.IV = new byte[] { 0xf, 0x6f, 0x13, 0x2e, 0x35, 0xc2, 0xcd, 0xf9, 0x5, 0x46, 0x9c, 0xea, 0xa8, 0x4b, 0x73, 0xcc };
break;
default:
algoritmo.IV = new byte[] { 0xf, 0x6f, 0x13, 0x2e, 0x35, 0xc2, 0xcd, 0xf9 };
break;
}
}
#endregion
// ----------------------------------------------------------------------------------------------------
#region Properties
/// <summary>Chave secreta para o algoritmo simétrico de criptografia.</summary>
public string Key
{
get { return chave; }
set { chave = value; }
}
#endregion
// ----------------------------------------------------------------------------------------------------
#region Constructors
/// <summary>Contrutor padrão da classe, é setado um tipo de criptografia padrão (Rijndael).</summary>
public CryptService()
{
algoritmo = new RijndaelManaged();
algoritmo.Mode = CipherMode.CBC;
provider = CryptProvider.Rijndael;
}
/// <summary>
/// Construtor com o tipo de criptografia a ser usada Você pode escolher o tipo pelo Enum chamado CryptProvider.
/// </summary>
/// <param name="cryptProvider">Tipo de criptografia.</param>
public CryptService(CryptProvider cryptProvider)
{
// Seleciona algoritmo simétrico
switch (cryptProvider)
{
case CryptProvider.Rijndael:
algoritmo = new RijndaelManaged();
provider = CryptProvider.Rijndael;
break;
case CryptProvider.RC2:
algoritmo = new RC2CryptoServiceProvider();
provider = CryptProvider.RC2;
break;
case CryptProvider.DES:
algoritmo = new DESCryptoServiceProvider();
provider = CryptProvider.DES;
break;
case CryptProvider.TripleDES:
algoritmo = new TripleDESCryptoServiceProvider();
provider = CryptProvider.TripleDES;
break;
}
algoritmo.Mode = CipherMode.CBC;
}
#endregion
// ----------------------------------------------------------------------------------------------------
#region Public methods
/// <summary>Gera a chave de criptografia válida dentro do array.</summary>
/// <returns>Chave com array de bytes.</returns>
public virtual byte[] GetChave()
{
string salt = string.Empty;
// Ajusta o tamanho da chave se necessário e retorna uma chave válida
if (algoritmo.LegalKeySizes.Length > 0)
{
// Tamanho das chaves em bits
int keySize = chave.Length * 8;
int minSize = algoritmo.LegalKeySizes[0].MinSize;
int maxSize = algoritmo.LegalKeySizes[0].MaxSize;
int skipSize = algoritmo.LegalKeySizes[0].SkipSize;
// Busca o valor máximo da chave
if (keySize > maxSize) { chave = chave.Substring(0, maxSize / 8); }
else if (keySize < maxSize)
{
// Seta um tamanho válido
int validSize = (keySize <= minSize) ? minSize : (keySize - keySize % skipSize) + skipSize;
validSize = validSize / 8;
// Preenche a chave com arterisco para corrigir o tamanho
if (keySize < validSize) { chave = chave.PadRight(validSize, Convert.ToChar("*")); } // validSize / 8, "*".ToString()
}
}
PasswordDeriveBytes key = new PasswordDeriveBytes(chave, ASCIIEncoding.ASCII.GetBytes(salt));
return key.GetBytes(chave.Length);
}
/// <summary>Encripta o dado solicitado.</summary>
/// <param name="texto">Texto a ser criptografado.</param>
/// <returns>Texto criptografado.</returns>
public virtual string Criptografar(string texto)
{
byte[] plainByte = Encoding.UTF8.GetBytes(texto);
byte[] keyByte = GetChave();
// Seta a chave privada
algoritmo.Key = keyByte;
SetIV();
// Interface de criptografia / Cria objeto de criptografia
ICryptoTransform cryptoTransform = algoritmo.CreateEncryptor();
MemoryStream _memoryStream = new MemoryStream();
CryptoStream _cryptoStream = new CryptoStream(_memoryStream, cryptoTransform, CryptoStreamMode.Write);
// Grava os dados criptografados no MemoryStream
_cryptoStream.Write(plainByte, 0, plainByte.Length);
_cryptoStream.FlushFinalBlock();
// Busca o tamanho dos bytes encriptados
byte[] cryptoByte = _memoryStream.ToArray();
// Converte para a base 64 string para uso posterior em um xml
return Convert.ToBase64String(cryptoByte, 0, cryptoByte.GetLength(0));
}
/// <summary>Desencripta o dado solicitado.</summary>
/// <param name="textoCriptografado">Texto a ser descriptografado.</param>
/// <returns>Texto descriptografado.</returns>
public virtual string Descriptografar(string textoCriptografado)
{
// Em caso de "Invalid length for a Base-64 char array"
textoCriptografado = textoCriptografado.Replace(" ", "+");
int mod4 = textoCriptografado.Length % 4;
if (mod4 > 0) textoCriptografado += new string('=', 4 - mod4);
// Converte a base 64 string em num array de bytes
byte[] cryptoByte = Convert.FromBase64String(textoCriptografado);
byte[] keyByte = GetChave();
// Seta a chave privada
algoritmo.Key = keyByte;
SetIV();
// Interface de criptografia / Cria objeto de descriptografia
ICryptoTransform cryptoTransform = algoritmo.CreateDecryptor();
try
{
MemoryStream _memoryStream = new MemoryStream(cryptoByte, 0, cryptoByte.Length);
CryptoStream _cryptoStream = new CryptoStream(_memoryStream, cryptoTransform, CryptoStreamMode.Read);
// Busca resultado do CryptoStream
StreamReader _streamReader = new StreamReader(_cryptoStream);
return _streamReader.ReadToEnd();
}
catch { return null; }
}
#endregion
// ----------------------------------------------------------------------------------------------------
}
}