blob: 30bfd6c0513e6b78139560cb613101f689cf14b9 [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";
Yingdi Yu4467c112015-10-19 09:27:45 -0700169 GroupManager manager(Name("Alice"), Name("data_type"), dbDir, 2048, 1);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800170
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);
Yingdi Yu883f4202015-11-02 13:54:11 -0800189 BOOST_CHECK_EQUAL(encryptedNonce.getAlgorithmType(), tlv::AlgorithmRsaOaep);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800190
191 const Buffer& bufferNonce = encryptedNonce.getPayload();
Yingdi Yu883f4202015-11-02 13:54:11 -0800192 algo::EncryptParams decryptParams(tlv::AlgorithmRsaOaep);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800193 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
Yingdi Yu4467c112015-10-19 09:27:45 -0700223 GroupManager manager(Name("Alice"), Name("data_type"), dbDir, 1024, 1);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800224 setManager(manager);
225
226 Data data = manager.createEKeyData("20150825T090000", "20150825T110000", encryptKeyBuf);
Yingdi Yu4467c112015-10-19 09:27:45 -0700227 BOOST_CHECK_EQUAL(data.getName().toUri(),
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800228 "/Alice/READ/data_type/E-KEY/20150825T090000/20150825T110000");
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800229
230 Buffer contentBuf(data.getContent().value(), data.getContent().value_size());
231 BOOST_CHECK_EQUAL_COLLECTIONS(encryptKeyBuf.begin(), encryptKeyBuf.end(),
232 contentBuf.begin(), contentBuf.end());
233
234}
235
236BOOST_AUTO_TEST_CASE(CalculateInterval)
237{
238 // create the group manager database
239 std::string dbDir = tmpPath.c_str();
240 dbDir += "/manager-interval-test.db";
241
242 // create group manager
Yingdi Yu4467c112015-10-19 09:27:45 -0700243 GroupManager manager(Name("Alice"), Name("data_type"), dbDir, 1024, 1);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800244 setManager(manager);
245
246 std::map<Name, Buffer> memberKeys;
247 Interval result;
248
249 TimeStamp tp1(from_iso_string("20150825T093000"));
250 result = manager.calculateInterval(tp1, memberKeys);
251 BOOST_CHECK_EQUAL(to_iso_string(result.getStartTime()), "20150825T090000");
252 BOOST_CHECK_EQUAL(to_iso_string(result.getEndTime()), "20150825T100000");
253
254 TimeStamp tp2(from_iso_string("20150827T073000"));
255 result = manager.calculateInterval(tp2, memberKeys);
256 BOOST_CHECK_EQUAL(to_iso_string(result.getStartTime()), "20150827T070000");
257 BOOST_CHECK_EQUAL(to_iso_string(result.getEndTime()), "20150827T080000");
258
259 TimeStamp tp3(from_iso_string("20150827T043000"));
260 result = manager.calculateInterval(tp3, memberKeys);
261 BOOST_CHECK_EQUAL(result.isValid(), false);
262
263 TimeStamp tp4(from_iso_string("20150827T053000"));
264 result = manager.calculateInterval(tp4, memberKeys);
265 BOOST_CHECK_EQUAL(to_iso_string(result.getStartTime()), "20150827T050000");
266 BOOST_CHECK_EQUAL(to_iso_string(result.getEndTime()), "20150827T060000");
267}
268
269BOOST_AUTO_TEST_CASE(GetGroupKey)
270{
271 // create the group manager database
272 std::string dbDir = tmpPath.c_str();
273 dbDir += "/manager-group-key-test.db";
274
275 // create group manager
Yingdi Yu4467c112015-10-19 09:27:45 -0700276 GroupManager manager(Name("Alice"), Name("data_type"), dbDir, 1024, 1);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800277 setManager(manager);
278
279 // get data list from group manager
280 TimeStamp tp1(from_iso_string("20150825T093000"));
281 std::list<Data> result = manager.getGroupKey(tp1);
282
283 BOOST_CHECK_EQUAL(result.size(), 4);
284
285 // first data contain the group encrypt key(public key)
286 std::list<Data>::iterator dataIterator = result.begin();
287 BOOST_CHECK_EQUAL(dataIterator->getName().toUri(),
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800288 "/Alice/READ/data_type/E-KEY/20150825T090000/20150825T100000");
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800289 EncryptKey<algo::Rsa> groupEKey(Buffer(dataIterator->getContent().value(),
290 dataIterator->getContent().value_size()));
291
292 // second data and decrypt
293 dataIterator++;
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800294 BOOST_CHECK_EQUAL(dataIterator->getName().toUri(),
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800295 "/Alice/READ/data_type/D-KEY/20150825T090000/20150825T100000/FOR/ndn/memberA/ksk-123");
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800296
297 //////////////////////////////////////////////////////////////////////// start decryption
298 Block dataContent = dataIterator->getContent();
299
300 dataContent.parse();
301 BOOST_CHECK_EQUAL(dataContent.elements_size(), 2);
302
303 // get nonce key
304 Block::element_const_iterator contentIterator = dataContent.elements_begin();
305 Block nonceContent(*contentIterator);
306 BOOST_CHECK_EQUAL(nonceContent.type(), tlv::EncryptedContent);
307 EncryptedContent encryptedNonce(nonceContent);
308 BOOST_CHECK_EQUAL(encryptedNonce.getInitialVector().size(), 0);
Yingdi Yu883f4202015-11-02 13:54:11 -0800309 BOOST_CHECK_EQUAL(encryptedNonce.getAlgorithmType(), tlv::AlgorithmRsaOaep);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800310
Yingdi Yu883f4202015-11-02 13:54:11 -0800311 algo::EncryptParams decryptParams(tlv::AlgorithmRsaOaep);
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800312 const Buffer& bufferNonce = encryptedNonce.getPayload();
313 Buffer nonce = algo::Rsa::decrypt(decryptKeyBuf.buf(), decryptKeyBuf.size(),
314 bufferNonce.buf(), bufferNonce.size(), decryptParams);
315
316 // get buffer payload
317 contentIterator++;
318 Block payloadContent(*contentIterator);
319 BOOST_CHECK_EQUAL(payloadContent.type(), tlv::EncryptedContent);
320 EncryptedContent encryptedPayload(payloadContent);
321 BOOST_CHECK_EQUAL(encryptedPayload.getInitialVector().size(), 16);
322 BOOST_CHECK_EQUAL(encryptedPayload.getAlgorithmType(), tlv::AlgorithmAesCbc);
323
324 decryptParams.setAlgorithmType(tlv::AlgorithmAesCbc);
325 decryptParams.setIV(encryptedPayload.getInitialVector().buf(),
326 encryptedPayload.getInitialVector().size());
327 const Buffer& bufferPayload = encryptedPayload.getPayload();
328 Buffer largePayload = algo::Aes::decrypt(nonce.buf(), nonce.size(),
329 bufferPayload.buf(), bufferPayload.size(),
330 decryptParams);
331
332 // get group D-KEY
333 DecryptKey<algo::Rsa> groupDKey(Buffer(largePayload.buf(), largePayload.size()));
334
335 /////////////////////////////////////////////////////////////////////// end decryption
336
337 // check the D-KEY
338 EncryptKey<algo::Rsa> derivedGroupEKey = algo::Rsa::deriveEncryptKey(groupDKey.getKeyBits());
339 BOOST_CHECK_EQUAL_COLLECTIONS(groupEKey.getKeyBits().begin(), groupEKey.getKeyBits().end(),
340 derivedGroupEKey.getKeyBits().begin(),
341 derivedGroupEKey.getKeyBits().end());
342
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800343 // third data and decrypt
344 dataIterator++;
345 BOOST_CHECK_EQUAL(dataIterator->getName().toUri(),
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800346 "/Alice/READ/data_type/D-KEY/20150825T090000/20150825T100000/FOR/ndn/memberB/ksk-123");
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800347
348 // second data and decrypt
349 dataIterator++;
350 BOOST_CHECK_EQUAL(dataIterator->getName().toUri(),
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800351 "/Alice/READ/data_type/D-KEY/20150825T090000/20150825T100000/FOR/ndn/memberC/ksk-123");
Zhiyi Zhang3ac0d8d2015-10-28 14:07:09 +0800352
Zhiyi Zhang84986cc2015-09-21 00:26:07 +0800353 // invalid time stamp to get group key
354 TimeStamp tp2(from_iso_string("20150826T083000"));
355 BOOST_CHECK_EQUAL(manager.getGroupKey(tp2).size(), 0);
356
357 TimeStamp tp3(from_iso_string("20150827T023000"));
358 BOOST_CHECK_EQUAL(manager.getGroupKey(tp3).size(), 0);
359}
360
361BOOST_AUTO_TEST_SUITE_END()
362
363} // namespace test
364} // namespace gep
365} // namespace ndn