blob: deac7683719e6bdc26b2759cb70a50a42af11e68 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California
*
* This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN).
* See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors.
*
* ndn-group-encrypt is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* ndn-group-encrypt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* ndn-group-encrypt, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Zhiyi Zhang <dreamerbarrychang@gmail.com>
*/
#include "group-manager.hpp"
#include "encryptor.hpp"
#include "encrypted-content.hpp"
#include <map>
namespace ndn {
namespace gep {
static const name::Component E_KEY_COMPONENT("E-KEY");
static const name::Component D_KEY_COMPONENT("D-KEY");
static const name::Component READ_COMPONENT("read");
GroupManager::GroupManager(const Name& prefix, const Name& dataType, const std::string& dbDir,
const int paramLength, const int freshPeriod)
: m_namespace(prefix)
, m_db(dbDir)
, m_paramLength(paramLength)
, m_freshPeriod(freshPeriod)
{
m_namespace.append(READ_COMPONENT).append(dataType);
}
std::list<Data>
GroupManager::getGroupKey(const TimeStamp& timeslot)
{
std::map<Name, Buffer> memberKeys;
std::list<Data> result;
// get time interval
Interval finalInterval = calculateInterval(timeslot, memberKeys);
if (finalInterval.isValid() == false)
return result;
std::string startTs = boost::posix_time::to_iso_string(finalInterval.getStartTime());
std::string endTs = boost::posix_time::to_iso_string(finalInterval.getEndTime());
// generate the pri key and pub key
Buffer priKeyBuf, pubKeyBuf;
generateKeyPairs(priKeyBuf, pubKeyBuf);
// add the first element to the result
// E-KEY (public key) data packet name convention:
// /<data_type>/E-KEY/[start-ts]/[end-ts]
Data data = createEKeyData(startTs, endTs, pubKeyBuf);
result.push_back(data);
// encrypt pri key with pub key from certificate
for (const auto& entry : memberKeys) {
const Name& keyName = entry.first;
const Buffer& certKey = entry.second;
// generate the name of the packet
// D-KEY (private key) data packet name convention:
// /<data_type>/D-KEY/[start-ts]/[end-ts]/[member-name]
data = createDKeyData(startTs, endTs, keyName, priKeyBuf, certKey);
result.push_back(data);
}
return result;
}
void
GroupManager::addSchedule(const std::string& scheduleName, const Schedule& schedule)
{
m_db.addSchedule(scheduleName, schedule);
}
void
GroupManager::deleteSchedule(const std::string& scheduleName)
{
m_db.deleteSchedule(scheduleName);
}
void
GroupManager::updateSchedule(const std::string& scheduleName, const Schedule& schedule)
{
m_db.updateSchedule(scheduleName, schedule);
}
void
GroupManager::addMember(const std::string& scheduleName, const Data& memCert)
{
IdentityCertificate cert(memCert);
m_db.addMember(scheduleName, cert.getPublicKeyName(), cert.getPublicKeyInfo().get());
}
void
GroupManager::removeMember(const Name& identity)
{
m_db.deleteMember(identity);
}
void
GroupManager::updateMemberSchedule(const Name& identity, const std::string& scheduleName)
{
m_db.updateMemberSchedule(identity, scheduleName);
}
Interval
GroupManager::calculateInterval(const TimeStamp& timeslot, std::map<Name, Buffer>& memberKeys)
{
// prepare
Interval positiveResult;
Interval negativeResult;
Interval tempInterval;
Interval finalInterval;
bool isPositive;
memberKeys.clear();
// get the all intervals from schedules
for (const std::string& scheduleName : m_db.listAllScheduleNames()) {
const Schedule& schedule = m_db.getSchedule(scheduleName);
std::tie(isPositive, tempInterval) = schedule.getCoveringInterval(timeslot);
if (isPositive) {
if (!positiveResult.isValid())
positiveResult = tempInterval;
positiveResult && tempInterval;
std::map<Name, Buffer> m = m_db.getScheduleMembers(scheduleName);
memberKeys.insert(m.begin(), m.end());
}
else {
if (!negativeResult.isValid())
negativeResult = tempInterval;
negativeResult && tempInterval;
}
}
if (!positiveResult.isValid()) {
// return invalid interval when there is no member has interval covering the time slot
return Interval(false);
}
// get the final interval result
if (negativeResult.isValid())
finalInterval = positiveResult && negativeResult;
else
finalInterval = positiveResult;
return finalInterval;
}
void
GroupManager::generateKeyPairs(Buffer& priKeyBuf, Buffer& pubKeyBuf) const
{
RandomNumberGenerator rng;
RsaKeyParams params(m_paramLength);
algo::EncryptParams eparams(tlv::AlgorithmRsaPkcs);
DecryptKey<algo::Rsa> privateKey = algo::Rsa::generateKey(rng, params);
priKeyBuf = privateKey.getKeyBits();
EncryptKey<algo::Rsa> publicKey = algo::Rsa::deriveEncryptKey(priKeyBuf);
pubKeyBuf = publicKey.getKeyBits();
}
Data
GroupManager::createEKeyData(const std::string& startTs, const std::string& endTs,
const Buffer& pubKeyBuf)
{
Name dataName(m_namespace);
dataName.append(E_KEY_COMPONENT).append(startTs).append(endTs);
Data data(dataName);
data.setFreshnessPeriod(time::hours(m_freshPeriod));
data.setContent(pubKeyBuf.get(), pubKeyBuf.size());
m_keyChain.sign(data);
return data;
}
Data
GroupManager::createDKeyData(const std::string& startTs, const std::string& endTs,
const Name& keyName, const Buffer& priKeyBuf,
const Buffer& certKey)
{
Name dataName(m_namespace);
dataName.append(D_KEY_COMPONENT);
dataName.append(startTs).append(endTs).append(keyName.getPrefix(-1));
Data data = Data(dataName);
data.setFreshnessPeriod(time::hours(m_freshPeriod));
algo::EncryptParams eparams(tlv::AlgorithmRsaPkcs);
algo::encryptData(data, priKeyBuf.buf(), priKeyBuf.size(), keyName,
certKey.buf(), certKey.size(), eparams);
m_keyChain.sign(data);
return data;
}
} // namespace ndn
} // namespace ndn