-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCTR.cc
96 lines (70 loc) · 2.56 KB
/
CTR.cc
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
#include "ciphermodes/CTR.h"
#include "cipher/BlockCipher.h"
#include "exceptions/BadParameterException.h"
#include "coder/Unsigned64.h"
#include <cmath>
namespace CK {
CTR::CTR(BlockCipher *c)
: cipher(c) {
}
CTR::~CTR() {
delete cipher;
}
coder::ByteArray CTR::decrypt(const coder::ByteArray& ciphertext, const coder::ByteArray& key) {
coder::ByteArray P;
double cs = ciphertext.getLength();
uint32_t blockSize = cipher->blockSize();
uint32_t blockCount = ceil(cs / blockSize);
for (unsigned i = 0; i < blockCount; ++i) {
uint32_t index = i * blockSize;
incrementCounter();
coder::ByteArray pBlock(cipher->encrypt(counter, key));
if (index + blockSize < ciphertext.getLength()) { // Whole block
P.append(pBlock ^ ciphertext.range(index, blockSize));
}
else { // Partial block, xor with encrypted counter LSB
coder::ByteArray partial(ciphertext.range(index, ciphertext.getLength() - index));
coder::ByteArray pctr(pBlock.range(0, partial.getLength()));
P.append(partial ^ pctr);
}
}
return P;
}
coder::ByteArray CTR::encrypt(const coder::ByteArray& plaintext, const coder::ByteArray& key) {
coder::ByteArray C;
double ps = plaintext.getLength();
uint32_t blockSize = cipher->blockSize();
uint32_t blockCount = ceil(ps / blockSize);
for (unsigned i = 0; i < blockCount; ++i) {
uint32_t index = i * blockSize;
incrementCounter();
coder::ByteArray cBlock(cipher->encrypt(counter, key));
if (index + blockSize < plaintext.getLength()) { // Whole block
C.append(cBlock ^ plaintext.range(index, blockSize));
}
else { // Partial block, xor with encrypted counter LSB
coder::ByteArray partial(plaintext.range(index, plaintext.getLength() - index));
coder::ByteArray pctr(cBlock.range(0, partial.getLength()));
C.append(partial ^ pctr);
}
}
return C;
}
void CTR::incrementCounter() {
coder::ByteArray nonce(counter.range(0, counter.getLength() - 4));
coder::Unsigned64 ctr(counter.range(nonce.getLength(), 4));
counter.clear();
ctr.setValue(ctr.getValue() + 1);
counter.append(nonce);
counter.append(ctr.getEncoded(coder::bigendian));
}
void CTR::setIV(const coder::ByteArray& iv) {
if (iv.getLength() != cipher->blockSize() - 8) {
throw BadParameterException("Invalid nonce size");
}
counter = iv;
coder::ByteArray ctr(8,0);
ctr[7] = 1;
counter.append(ctr);
}
}