-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAES-CTR.cs
106 lines (87 loc) · 2.92 KB
/
AES-CTR.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
using System.Collections.Generic;
using System.Security.Cryptography;
public class Aes128CounterMode : SymmetricAlgorithm {
private readonly byte[] Counter;
private readonly AesManaged AESCtr; public Aes128CounterMode(byte[] CTR) {
AESCtr = new AesManaged {
Mode = CipherMode.ECB,
Padding = PaddingMode.None
};
Counter = CTR;
}
public override ICryptoTransform CreateEncryptor(byte[] Key, byte[] Input) {
return new CryptoTransform(AESCtr, Key, Counter);
}
public override ICryptoTransform CreateDecryptor(byte[] Key, byte[] Input) {
return new CryptoTransform(AESCtr, Key, Counter);
}
public override void GenerateKey() {
AESCtr.GenerateKey();
}
public override void GenerateIV() {
}
}
public class CryptoTransform : ICryptoTransform {
private readonly byte[] Counter;
private readonly ICryptoTransform Transform;
private readonly Queue<byte> QueuedBytes = new Queue<byte>();
private readonly SymmetricAlgorithm Algorithm;
public CryptoTransform(SymmetricAlgorithm Alg, byte[] Key, byte[] Counter) {
Algorithm = Alg;
this.Counter = Counter;
var Block = new byte[Algorithm.BlockSize / 8];
Transform = Alg.CreateEncryptor(Key, Block);
}
public byte[] TransformFinalBlock(byte[] InputData, int StartOffset, int Length) {
var EncryptedData = new byte[Length];
TransformBlock(InputData, StartOffset, Length, EncryptedData, 0);
return EncryptedData;
}
public int TransformBlock(byte[] InputData, int StartOffset, int Length, byte[] Output, int OutOffset)
{
for (var i = 0; i < Length; i++)
{
if (Null()) CounterTransform(); var TransformBytes = QueuedBytes.Dequeue();
Output[OutOffset + i] = (byte)(InputData[StartOffset + i] ^ TransformBytes);
}
return Length;
}
private bool Null() {
return QueuedBytes.Count == 0;
}
private void CounterTransform() {
var Output = new byte[Algorithm.BlockSize / 8];
Transform.TransformBlock(Counter, 0, Counter.Length, Output, 0);
Countup();
foreach (var Byte in Output) {
QueuedBytes.Enqueue(Byte);
}
}
private void Countup() {
for (var i = Counter.Length - 1; i >= 0; i--) {
if (++Counter[i] != 0) break;
}
}
public int InputBlockSize {
get {
return Algorithm.BlockSize / 8;
}
}
public int OutputBlockSize {
get {
return Algorithm.BlockSize / 8;
}
}
public bool CanTransformMultipleBlocks{
get {
return true;
}
}
public bool CanReuseTransform {
get {
return false;
}
}
public void Dispose() {
}
}