-
Notifications
You must be signed in to change notification settings - Fork 0
/
aes_256_GCM.cpp
150 lines (125 loc) · 4.71 KB
/
aes_256_GCM.cpp
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
//
// Created by yourgod on 03/03/2023.
//
#include "aes_256_GCM.h"
using CryptoPP::byte;
std::string aes_256_GCM::encode(const std::string &adata,
const std::string &pdata,
byte key[],
size_t key_size,
byte iv[],
size_t iv_size,
int TAG_SIZE
) {
std::string encoded;
std::string cipher; // out
try {
GCM<AES>::Encryption e;
e.SetKeyWithIV(key, key_size, iv, iv_size);
// Filter wrapper for encrypting
AuthenticatedEncryptionFilter ef(e, new StringSink(cipher), false,
TAG_SIZE);
// AuthenticatedEncryptionFilter::ChannelPut
// defines two channels: "" (empty) and "AAD"
// channel "" is encrypted and authenticated
// channel "AAD" is authenticated
ef.ChannelPut("AAD", (const byte *)adata.data(), adata.size());
ef.ChannelMessageEnd("AAD");
// Authenticated data *must* be pushed before
// Confidential/Authenticated data. Otherwise
// we must catch the BadState exception
ef.ChannelPut("", (const byte *)pdata.data(),
pdata.size()); // user_defined
ef.ChannelMessageEnd("");
} catch (CryptoPP::BufferedTransformation::NoChannelSupport &e) {
// The tag must go in to the default channel:
// "unknown: this object doesn't support multiple channels"
cerr << "Caught NoChannelSupport..." << endl;
cerr << e.what() << endl;
cerr << endl;
} catch (CryptoPP::AuthenticatedSymmetricCipher::BadState &e) {
// Pushing PDATA before ADATA results in:
// "GMC/AES: Update was called before State_IVSet"
cerr << "Caught BadState..." << endl;
cerr << e.what() << endl;
cerr << endl;
} catch (CryptoPP::InvalidArgument &e) {
cerr << "Caught InvalidArgument..." << endl;
cerr << e.what() << endl;
cerr << endl;
}
return cipher;
}
string aes_256_GCM::decode(const string &cipher,
const string &adata,
byte *key,
size_t key_size,
byte *iv,
size_t iv_size,
int TAG_SIZE
) {
string radata, rpdata;
try {
GCM<AES>::Decryption d;
d.SetKeyWithIV(&key[0], key_size, iv, iv_size);
// Break the cipher text out into it's
// components: Encrypted Data and MAC Value
string enc = cipher.substr(0, cipher.length() - TAG_SIZE);
string mac = cipher.substr(cipher.length() - TAG_SIZE);
// Sanity checks
assert(cipher.size() == enc.size() + mac.size());
// assert(enc.size() == pdata.size());
assert(TAG_SIZE == mac.size());
// Not recovered - sent via clear channel
// radata = adata;
// Object will not throw an exception
// during decryption\verification _if_
// verification fails.
// AuthenticatedDecryptionFilter df( d, NULL,
// AuthenticatedDecryptionFilter::MAC_AT_BEGIN );
AuthenticatedDecryptionFilter df(
d, NULL,
AuthenticatedDecryptionFilter::MAC_AT_BEGIN |
AuthenticatedDecryptionFilter::THROW_EXCEPTION,
TAG_SIZE);
// The order of the following calls are important
df.ChannelPut("", (const byte *)mac.data(), mac.size());
df.ChannelPut("AAD", (const byte *)adata.data(), adata.size());
df.ChannelPut("", (const byte *)enc.data(), enc.size());
// If the object throws, it will most likely occur
// during ChannelMessageEnd()
df.ChannelMessageEnd("AAD");
df.ChannelMessageEnd("");
// If the object does not throw, here's the only
// opportunity to check the data's integrity
bool b = false;
b = df.GetLastResult();
assert(b);
// Remove data from channel
string retrieved;
size_t n = (size_t)-1;
// Plain text recovered from enc.data()
df.SetRetrievalChannel("");
n = (size_t)df.MaxRetrievable();
retrieved.resize(n);
if (n > 0) {
df.Get((byte *)retrieved.data(), n);
}
rpdata = retrieved;
} catch (CryptoPP::InvalidArgument &e) {
cerr << "Caught InvalidArgument..." << endl;
cerr << e.what() << endl;
cerr << endl;
} catch (CryptoPP::AuthenticatedSymmetricCipher::BadState &e) {
// Pushing PDATA before ADATA results in:
// "GMC/AES: Update was called before State_IVSet"
cerr << "Caught BadState..." << endl;
cerr << e.what() << endl;
cerr << endl;
} catch (CryptoPP::HashVerificationFilter::HashVerificationFailed &e) {
cerr << "Caught HashVerificationFailed..." << endl;
cerr << e.what() << endl;
cerr << endl;
}
return rpdata;
}