blob: 1d256985c897f203085b586a8ec3a9a8a713169d [file] [log] [blame]
Zhiyi Zhang84986cc2015-09-21 00:26:07 +08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2015, Regents of the University of California
4 *
5 * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN).
6 * See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors.
7 *
8 * ndn-group-encrypt is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * ndn-group-encrypt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * ndn-group-encrypt, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author Zhiyi Zhang <dreamerbarrychang@gmail.com>
20 */
21
22#include "group-manager.hpp"
23#include "boost-test.hpp"
24#include "algo/rsa.hpp"
25#include "algo/aes.hpp"
26#include "encrypted-content.hpp"
27
28#include <boost/filesystem.hpp>
29#include <ndn-cxx/encoding/buffer-stream.hpp>
30#include <string>
31
32namespace ndn {
33namespace gep {
34namespace tests {
35
36using namespace boost::posix_time;
37
38const uint8_t SIG_INFO[] = {
39 0x16, 0x1b, // SignatureInfo
40 0x1b, 0x01, // SignatureType
41 0x01,
42 0x1c, 0x16, // KeyLocator
43 0x07, 0x14, // Name
44 0x08, 0x04,
45 0x74, 0x65, 0x73, 0x74,
46 0x08, 0x03,
47 0x6b, 0x65, 0x79,
48 0x08, 0x07,
49 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72
50};
51
52const uint8_t SIG_VALUE[] = {
53 0x17, 0x80, // SignatureValue
54 0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
55 0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
56 0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
57 0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
58 0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
59 0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
60 0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
61 0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
62 0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
63 0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
64};
65
66class GroupManagerFixture
67{
68public:
69 GroupManagerFixture()
70 : tmpPath(boost::filesystem::path(TMP_TESTS_PATH))
71 {
72 boost::filesystem::create_directories(tmpPath);
73
74 // generate the certificate public key
75 RandomNumberGenerator rng;
76 RsaKeyParams params;
77 DecryptKey<algo::Rsa> memberDecryptKey = algo::Rsa::generateKey(rng, params);
78 decryptKeyBuf = memberDecryptKey.getKeyBits();
79 EncryptKey<algo::Rsa> memberEncryptKey = algo::Rsa::deriveEncryptKey(decryptKeyBuf);
80 encryptKeyBuf = memberEncryptKey.getKeyBits();
81
82 // generate certificate
83 cert.setName(Name("/ndn/memberA/KEY/ksk-123/ID-CERT/123"));
84 PublicKey contentPubKey(encryptKeyBuf.buf(), encryptKeyBuf.size());
85 cert.setPublicKeyInfo(contentPubKey);
86 cert.encode();
87
88 Block sigInfoBlock(SIG_INFO, sizeof(SIG_INFO));
89 Block sigValueBlock(SIG_VALUE, sizeof(SIG_VALUE));
90
91 Signature sig(sigInfoBlock, sigValueBlock);
92 cert.setSignature(sig);
93
94 auto dataBlock = cert.wireEncode();
95 }
96
97 void
98 setManager(GroupManager& manager)
99 {
100 // set the first schedule
101 Schedule schedule1;
102 RepetitiveInterval interval11(from_iso_string("20150825T000000"),
103 from_iso_string("20150827T000000"),
104 5, 10, 2, RepetitiveInterval::RepeatUnit::DAY);
105 RepetitiveInterval interval12(from_iso_string("20150825T000000"),
106 from_iso_string("20150827T000000"),
107 6, 8, 1, RepetitiveInterval::RepeatUnit::DAY);
108 RepetitiveInterval interval13(from_iso_string("20150827T000000"),
109 from_iso_string("20150827T000000"),
110 7, 8);
111 schedule1.addWhiteInterval(interval11);
112 schedule1.addWhiteInterval(interval12);
113 schedule1.addBlackInterval(interval13);
114
115 // set the second schedule
116 Schedule schedule2;
117 RepetitiveInterval interval21(from_iso_string("20150825T000000"),
118 from_iso_string("20150827T000000"),
119 9, 12, 1, RepetitiveInterval::RepeatUnit::DAY);
120 RepetitiveInterval interval22(from_iso_string("20150827T000000"),
121 from_iso_string("20150827T000000"),
122 6, 8);
123 RepetitiveInterval interval23(from_iso_string("20150827T000000"),
124 from_iso_string("20150827T000000"),
125 2, 4);
126 schedule2.addWhiteInterval(interval21);
127 schedule2.addWhiteInterval(interval22);
128 schedule2.addBlackInterval(interval23);
129
130 // add to the group manager db
131 manager.addSchedule("schedule1", schedule1);
132 manager.addSchedule("schedule2", schedule2);
133
134 // do some adaptions to certificate
135 Block dataBlock = cert.wireEncode();
136
137 Data memberA(dataBlock);
138 memberA.setName(Name("/ndn/memberA/KEY/ksk-123/ID-CERT/123"));
139 Data memberB(dataBlock);
140 memberB.setName(Name("/ndn/memberB/KEY/ksk-123/ID-CERT/123"));
141 Data memberC(dataBlock);
142 memberC.setName(Name("/ndn/memberC/KEY/ksk-123/ID-CERT/123"));
143
144 // add members to the database
145 manager.addMember("schedule1", memberA);
146 manager.addMember("schedule1", memberB);
147 manager.addMember("schedule2", memberC);
148 }
149
150 ~GroupManagerFixture()
151 {
152 boost::filesystem::remove_all(tmpPath);
153 }
154
155public:
156 boost::filesystem::path tmpPath;
157 Buffer decryptKeyBuf;
158 Buffer encryptKeyBuf;
159 IdentityCertificate cert;
160};
161
162BOOST_FIXTURE_TEST_SUITE(TestGroupManager, GroupManagerFixture)
163
164BOOST_AUTO_TEST_CASE(CreateDKeyData)
165{
166 // create the group manager database
167 std::string dbDir = tmpPath.c_str();
168 dbDir += "/manager-d-key-test.db";
169 GroupManager manager(Name("Alice-read"), dbDir, 2048, 1);
170
171 Block newCertBlock = cert.wireEncode();
172 IdentityCertificate newCert(newCertBlock);
173
174 // encrypt D-KEY
175 Data data = manager.createDKeyData("20150825T000000", "20150827T000000", Name("/ndn/memberA/KEY"),
176 decryptKeyBuf, newCert.getPublicKeyInfo().get());
177
178 // verify encrypted D-KEY
179 Block dataContent = data.getContent();
180 dataContent.parse();
181 BOOST_CHECK_EQUAL(dataContent.elements_size(), 2);
182
183 // get nonce key
184 Block::element_const_iterator contentIterator = dataContent.elements_begin();
185 Block nonceContent(*contentIterator);
186 BOOST_CHECK_EQUAL(nonceContent.type(), tlv::EncryptedContent);
187 EncryptedContent encryptedNonce(nonceContent);
188 BOOST_CHECK_EQUAL(encryptedNonce.getInitialVector().size(), 0);
189 BOOST_CHECK_EQUAL(encryptedNonce.getAlgorithmType(), tlv::AlgorithmRsaPkcs);
190
191 const Buffer& bufferNonce = encryptedNonce.getPayload();
192 algo::EncryptParams decryptParams(tlv::AlgorithmRsaPkcs);
193 Buffer nonce = algo::Rsa::decrypt(decryptKeyBuf.buf(), decryptKeyBuf.size(),
194 bufferNonce.buf(), bufferNonce.size(), decryptParams);
195
196 // get D-KEY
197 contentIterator++;
198 Block payloadContent(*contentIterator);
199 BOOST_CHECK_EQUAL(payloadContent.type(), tlv::EncryptedContent);
200 EncryptedContent encryptedPayload(payloadContent);
201 BOOST_CHECK_EQUAL(encryptedPayload.getInitialVector().size(), 16);
202 BOOST_CHECK_EQUAL(encryptedPayload.getAlgorithmType(), tlv::AlgorithmAesCbc);
203
204 decryptParams.setAlgorithmType(tlv::AlgorithmAesCbc);
205 decryptParams.setIV(encryptedPayload.getInitialVector().buf(),
206 encryptedPayload.getInitialVector().size());
207 const Buffer& bufferPayload = encryptedPayload.getPayload();
208 Buffer largePayload = algo::Aes::decrypt(nonce.buf(), nonce.size(),
209 bufferPayload.buf(), bufferPayload.size(),
210 decryptParams);
211
212 BOOST_CHECK_EQUAL_COLLECTIONS(largePayload.begin(), largePayload.end(),
213 decryptKeyBuf.begin(), decryptKeyBuf.end());
214}
215
216BOOST_AUTO_TEST_CASE(CreateEKeyData)
217{
218 // create the group manager database
219 std::string dbDir = tmpPath.c_str();
220 dbDir += "/manager-e-key-test.db";
221
222 // create group manager
223 GroupManager manager(Name("Alice-read"), dbDir, 1024, 1);
224 setManager(manager);
225
226 Data data = manager.createEKeyData("20150825T090000", "20150825T110000", encryptKeyBuf);
227 BOOST_CHECK_EQUAL(data.getName().toUri(), "/Alice-read/E-KEY/20150825T090000/20150825T110000");
228
229 Buffer contentBuf(data.getContent().value(), data.getContent().value_size());
230 BOOST_CHECK_EQUAL_COLLECTIONS(encryptKeyBuf.begin(), encryptKeyBuf.end(),
231 contentBuf.begin(), contentBuf.end());
232
233}
234
235BOOST_AUTO_TEST_CASE(CalculateInterval)
236{
237 // create the group manager database
238 std::string dbDir = tmpPath.c_str();
239 dbDir += "/manager-interval-test.db";
240
241 // create group manager
242 GroupManager manager(Name("Alice-read"), dbDir, 1024, 1);
243 setManager(manager);
244
245 std::map<Name, Buffer> memberKeys;
246 Interval result;
247
248 TimeStamp tp1(from_iso_string("20150825T093000"));
249 result = manager.calculateInterval(tp1, memberKeys);
250 BOOST_CHECK_EQUAL(to_iso_string(result.getStartTime()), "20150825T090000");
251 BOOST_CHECK_EQUAL(to_iso_string(result.getEndTime()), "20150825T100000");
252
253 TimeStamp tp2(from_iso_string("20150827T073000"));
254 result = manager.calculateInterval(tp2, memberKeys);
255 BOOST_CHECK_EQUAL(to_iso_string(result.getStartTime()), "20150827T070000");
256 BOOST_CHECK_EQUAL(to_iso_string(result.getEndTime()), "20150827T080000");
257
258 TimeStamp tp3(from_iso_string("20150827T043000"));
259 result = manager.calculateInterval(tp3, memberKeys);
260 BOOST_CHECK_EQUAL(result.isValid(), false);
261
262 TimeStamp tp4(from_iso_string("20150827T053000"));
263 result = manager.calculateInterval(tp4, memberKeys);
264 BOOST_CHECK_EQUAL(to_iso_string(result.getStartTime()), "20150827T050000");
265 BOOST_CHECK_EQUAL(to_iso_string(result.getEndTime()), "20150827T060000");
266}
267
268BOOST_AUTO_TEST_CASE(GetGroupKey)
269{
270 // create the group manager database
271 std::string dbDir = tmpPath.c_str();
272 dbDir += "/manager-group-key-test.db";
273
274 // create group manager
275 GroupManager manager(Name("Alice-read"), dbDir, 1024, 1);
276 setManager(manager);
277
278 // get data list from group manager
279 TimeStamp tp1(from_iso_string("20150825T093000"));
280 std::list<Data> result = manager.getGroupKey(tp1);
281
282 BOOST_CHECK_EQUAL(result.size(), 4);
283
284 // first data contain the group encrypt key(public key)
285 std::list<Data>::iterator dataIterator = result.begin();
286 BOOST_CHECK_EQUAL(dataIterator->getName().toUri(),
287 "/Alice-read/E-KEY/20150825T090000/20150825T100000");
288 EncryptKey<algo::Rsa> groupEKey(Buffer(dataIterator->getContent().value(),
289 dataIterator->getContent().value_size()));
290
291 // second data and decrypt
292 dataIterator++;
293 BOOST_CHECK_EQUAL(dataIterator->getName().getPrefix(-2).toUri(),
294 "/Alice-read/D-KEY/20150825T090000/20150825T100000");
295
296 //////////////////////////////////////////////////////////////////////// start decryption
297 Block dataContent = dataIterator->getContent();
298
299 dataContent.parse();
300 BOOST_CHECK_EQUAL(dataContent.elements_size(), 2);
301
302 // get nonce key
303 Block::element_const_iterator contentIterator = dataContent.elements_begin();
304 Block nonceContent(*contentIterator);
305 BOOST_CHECK_EQUAL(nonceContent.type(), tlv::EncryptedContent);
306 EncryptedContent encryptedNonce(nonceContent);
307 BOOST_CHECK_EQUAL(encryptedNonce.getInitialVector().size(), 0);
308 BOOST_CHECK_EQUAL(encryptedNonce.getAlgorithmType(), tlv::AlgorithmRsaPkcs);
309
310 algo::EncryptParams decryptParams(tlv::AlgorithmRsaPkcs);
311 const Buffer& bufferNonce = encryptedNonce.getPayload();
312 Buffer nonce = algo::Rsa::decrypt(decryptKeyBuf.buf(), decryptKeyBuf.size(),
313 bufferNonce.buf(), bufferNonce.size(), decryptParams);
314
315 // get buffer payload
316 contentIterator++;
317 Block payloadContent(*contentIterator);
318 BOOST_CHECK_EQUAL(payloadContent.type(), tlv::EncryptedContent);
319 EncryptedContent encryptedPayload(payloadContent);
320 BOOST_CHECK_EQUAL(encryptedPayload.getInitialVector().size(), 16);
321 BOOST_CHECK_EQUAL(encryptedPayload.getAlgorithmType(), tlv::AlgorithmAesCbc);
322
323 decryptParams.setAlgorithmType(tlv::AlgorithmAesCbc);
324 decryptParams.setIV(encryptedPayload.getInitialVector().buf(),
325 encryptedPayload.getInitialVector().size());
326 const Buffer& bufferPayload = encryptedPayload.getPayload();
327 Buffer largePayload = algo::Aes::decrypt(nonce.buf(), nonce.size(),
328 bufferPayload.buf(), bufferPayload.size(),
329 decryptParams);
330
331 // get group D-KEY
332 DecryptKey<algo::Rsa> groupDKey(Buffer(largePayload.buf(), largePayload.size()));
333
334 /////////////////////////////////////////////////////////////////////// end decryption
335
336 // check the D-KEY
337 EncryptKey<algo::Rsa> derivedGroupEKey = algo::Rsa::deriveEncryptKey(groupDKey.getKeyBits());
338 BOOST_CHECK_EQUAL_COLLECTIONS(groupEKey.getKeyBits().begin(), groupEKey.getKeyBits().end(),
339 derivedGroupEKey.getKeyBits().begin(),
340 derivedGroupEKey.getKeyBits().end());
341
342 // invalid time stamp to get group key
343 TimeStamp tp2(from_iso_string("20150826T083000"));
344 BOOST_CHECK_EQUAL(manager.getGroupKey(tp2).size(), 0);
345
346 TimeStamp tp3(from_iso_string("20150827T023000"));
347 BOOST_CHECK_EQUAL(manager.getGroupKey(tp3).size(), 0);
348}
349
350BOOST_AUTO_TEST_SUITE_END()
351
352} // namespace test
353} // namespace gep
354} // namespace ndn