forked from sshnet/SSH.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAesCipher.BclImpl.cs
More file actions
108 lines (94 loc) · 4.11 KB
/
AesCipher.BclImpl.cs
File metadata and controls
108 lines (94 loc) · 4.11 KB
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
using System;
using System.Security.Cryptography;
using Renci.SshNet.Common;
namespace Renci.SshNet.Security.Cryptography.Ciphers
{
public partial class AesCipher
{
private sealed class BclImpl : BlockCipher, IDisposable
{
private readonly Aes _aes;
private readonly ICryptoTransform _encryptor;
private readonly ICryptoTransform _decryptor;
public BclImpl(
byte[] key,
byte[] iv,
System.Security.Cryptography.CipherMode cipherMode,
PaddingMode paddingMode)
: base(key, 16, mode: null, padding: null)
{
var aes = Aes.Create();
aes.Key = key;
if (cipherMode != System.Security.Cryptography.CipherMode.ECB)
{
if (iv is null)
{
throw new ArgumentNullException(nameof(iv));
}
aes.IV = iv.Take(16);
}
aes.Mode = cipherMode;
aes.Padding = paddingMode;
aes.FeedbackSize = 128; // We use CFB128
_aes = aes;
_encryptor = aes.CreateEncryptor();
_decryptor = aes.CreateDecryptor();
}
public override byte[] Encrypt(byte[] input, int offset, int length)
{
if (_aes.Padding != PaddingMode.None)
{
// If padding has been specified, call TransformFinalBlock to apply
// the padding and reset the state.
return _encryptor.TransformFinalBlock(input, offset, length);
}
// Otherwise, (the most important case) assume this instance is
// used for one direction of an SSH connection, whereby the
// encrypted data in all packets are considered a single data
// stream i.e. we do not want to reset the state between calls to Encrypt.
var output = new byte[length];
_ = _encryptor.TransformBlock(input, offset, length, output, 0);
return output;
}
public override byte[] Decrypt(byte[] input, int offset, int length)
{
if (_aes.Padding != PaddingMode.None)
{
// If padding has been specified, call TransformFinalBlock to apply
// the padding and reset the state.
return _decryptor.TransformFinalBlock(input, offset, length);
}
// Otherwise, (the most important case) assume this instance is
// used for one direction of an SSH connection, whereby the
// encrypted data in all packets are considered a single data
// stream i.e. we do not want to reset the state between calls to Decrypt.
var output = new byte[length];
_ = _decryptor.TransformBlock(input, offset, length, output, 0);
return output;
}
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
throw new NotImplementedException($"Invalid usage of {nameof(EncryptBlock)}.");
}
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
throw new NotImplementedException($"Invalid usage of {nameof(DecryptBlock)}.");
}
private void Dispose(bool disposing)
{
if (disposing)
{
_aes.Dispose();
_encryptor.Dispose();
_decryptor.Dispose();
}
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
}