Changing logic in GroupManger.getGroupKey() to avoid regenerate group key pairs every time.
Change-Id: I4c6eb5246bce04289d7ba097a66d0f11745ce44c
Refs: #3812
diff --git a/src/group-manager-db.cpp b/src/group-manager-db.cpp
index 5c9cd23..0f8640b 100644
--- a/src/group-manager-db.cpp
+++ b/src/group-manager-db.cpp
@@ -55,7 +55,17 @@
" ON UPDATE CASCADE \n"
" ); \n"
"CREATE UNIQUE INDEX IF NOT EXISTS \n"
- " memNameIndex ON members(member_name); \n";
+ " memNameIndex ON members(member_name); \n"
+ " \n"
+ "CREATE TABLE IF NOT EXISTS \n"
+ " ekeys( \n"
+ " ekey_id INTEGER PRIMARY KEY, \n"
+ " ekey_name BLOB NOT NULL, \n"
+ " pub_key BLOB NOT NULL, \n"
+ " pri_key BLOB NOT NULL \n"
+ " ); \n"
+ "CREATE UNIQUE INDEX IF NOT EXISTS \n"
+ " ekeyNameIndex ON ekeys(ekey_name); \n";
class GroupManagerDB::Impl
{
@@ -319,5 +329,60 @@
statement.step();
}
+bool
+GroupManagerDB::hasEKey(const Name& eKeyName)
+{
+ Sqlite3Statement statement(m_impl->m_database,
+ "SELECT ekey_id FROM ekeys where ekey_name=?");
+ statement.bind(1, eKeyName.wireEncode(), SQLITE_TRANSIENT);
+ return (statement.step() == SQLITE_ROW);
+}
+
+void
+GroupManagerDB::addEKey(const Name& eKeyName, const Buffer& pubKey, const Buffer& priKey)
+{
+ Sqlite3Statement statement(m_impl->m_database,
+ "INSERT INTO ekeys(ekey_name, pub_key, pri_key) values (?, ?, ?)");
+ statement.bind(1, eKeyName.wireEncode(), SQLITE_TRANSIENT);
+ statement.bind(2, pubKey.buf(), pubKey.size(), SQLITE_TRANSIENT);
+ statement.bind(3, priKey.buf(), priKey.size(), SQLITE_TRANSIENT);
+ if (statement.step() != SQLITE_DONE)
+ BOOST_THROW_EXCEPTION(Error("Cannot add the EKey to database"));
+}
+
+std::tuple<Buffer, Buffer>
+GroupManagerDB::getEKey(const Name& eKeyName)
+{
+ Sqlite3Statement statement(m_impl->m_database,
+ "SELECT * FROM ekeys where ekey_name=?");
+ statement.bind(1, eKeyName.wireEncode(), SQLITE_TRANSIENT);
+
+ Buffer pubKey, priKey;
+ if (statement.step() == SQLITE_ROW) {
+ pubKey = Buffer(statement.getBlob(2), statement.getSize(2));
+ priKey = Buffer(statement.getBlob(3), statement.getSize(3));
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Cannot get the result from database"));
+ }
+ return std::make_tuple(pubKey, priKey);
+}
+
+void
+GroupManagerDB::cleanEKeys()
+{
+ Sqlite3Statement statement(m_impl->m_database, "DELETE FROM ekeys");
+ statement.step();
+}
+
+void
+GroupManagerDB::deleteEKey(const Name& eKeyName)
+{
+ Sqlite3Statement statement(m_impl->m_database,
+ "DELETE FROM ekeys WHERE ekey_name=?");
+ statement.bind(1, eKeyName.wireEncode(), SQLITE_TRANSIENT);
+ statement.step();
+}
+
} // namespace gep
} // namespace ndn
diff --git a/src/group-manager-db.hpp b/src/group-manager-db.hpp
index 9f737ae..cbf4ecd 100644
--- a/src/group-manager-db.hpp
+++ b/src/group-manager-db.hpp
@@ -164,6 +164,42 @@
void
deleteMember(const Name& identity);
+ /**
+ * @brief Check if there is a EKey with name @p eKeyName in database
+ */
+ bool
+ hasEKey(const Name& eKeyName);
+
+ /**
+ * @brief Add a EKey with name @p eKeyName to database
+ *
+ * @p pubKey The public Key of the group key pair
+ * @p priKey The private Key of the group key pair
+ */
+ void
+ addEKey(const Name& eKeyName, const Buffer& pubKey, const Buffer& priKey);
+
+ /**
+ * @brief Get the group key pair from database
+ */
+ std::tuple<Buffer, Buffer>
+ getEKey(const Name& eKeyName);
+
+ /**
+ * @brief Delete all the EKeys in the database
+ *
+ * The database will keep growing because EKeys will keep being added. The method
+ * should be called periodically
+ */
+ void
+ cleanEKeys();
+
+ /**
+ * @brief Delete a EKey with name @p eKeyName from database
+ */
+ void
+ deleteEKey(const Name& eKeyName);
+
private:
class Impl;
unique_ptr<Impl> m_impl;
diff --git a/src/group-manager.cpp b/src/group-manager.cpp
index 4bbf19e..bd5feb0 100644
--- a/src/group-manager.cpp
+++ b/src/group-manager.cpp
@@ -39,7 +39,7 @@
}
std::list<Data>
-GroupManager::getGroupKey(const TimeStamp& timeslot)
+GroupManager::getGroupKey(const TimeStamp& timeslot, bool needRegenerate)
{
std::map<Name, Buffer> memberKeys;
std::list<Data> result;
@@ -54,7 +54,19 @@
// generate the pri key and pub key
Buffer priKeyBuf, pubKeyBuf;
- generateKeyPairs(priKeyBuf, pubKeyBuf);
+ Name eKeyName(m_namespace);
+ eKeyName.append(NAME_COMPONENT_E_KEY).append(startTs).append(endTs);
+
+ if (!needRegenerate && m_db.hasEKey(eKeyName)) {
+ std::tie(pubKeyBuf, priKeyBuf) = getEKey(eKeyName);
+ }
+ else {
+ generateKeyPairs(priKeyBuf, pubKeyBuf);
+ if (m_db.hasEKey(eKeyName)) {
+ deleteEKey(eKeyName);
+ }
+ addEKey(eKeyName, pubKeyBuf, priKeyBuf);
+ }
// add the first element to the result
// E-KEY (public key) data packet name convention:
@@ -200,5 +212,29 @@
return data;
}
+void
+GroupManager::addEKey(const Name& eKeyName, const Buffer& pubKey, const Buffer& priKey)
+{
+ m_db.addEKey(eKeyName, pubKey, priKey);
+}
+
+std::tuple<Buffer, Buffer>
+GroupManager::getEKey(const Name& eKeyName)
+{
+ return m_db.getEKey(eKeyName);
+}
+
+void
+GroupManager::deleteEKey(const Name& eKeyName)
+{
+ m_db.deleteEKey(eKeyName);
+}
+
+void
+GroupManager::cleanEKeys()
+{
+ m_db.cleanEKeys();
+}
+
} // namespace ndn
} // namespace ndn
diff --git a/src/group-manager.hpp b/src/group-manager.hpp
index e4674df..2e19ab1 100644
--- a/src/group-manager.hpp
+++ b/src/group-manager.hpp
@@ -62,14 +62,17 @@
*
* This method creates a group key if it does not
* exist, and encrypts the key using public key of
- * all eligible members
+ * all eligible members.
+ *
+ * @p needRegenerate should be true if 1.first time to call 2.a member was removed
+ * and it can be false if 1.not the first time to call 2.a member was added
*
* @returns The group key (the first one is the
* public key, and the rest are encrypted
* private key.
*/
std::list<Data>
- getGroupKey(const TimeStamp& timeslot);
+ getGroupKey(const TimeStamp& timeslot, bool needRegenerate = true);
/// @brief Add @p schedule with @p scheduleName
void
@@ -95,6 +98,7 @@
void
updateMemberSchedule(const Name& identity, const std::string& scheduleName);
+
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/**
* @brief Calculate interval that covers @p timeslot
@@ -121,6 +125,22 @@
createDKeyData(const std::string& startTs, const std::string& endTs, const Name& keyName,
const Buffer& priKeyBuf, const Buffer& certKey);
+ /// @brief Add a EKey to the database
+ void
+ addEKey(const Name& eKeyName, const Buffer& pubKey, const Buffer& priKey);
+
+ /// @brief Get the key pair from the database
+ std::tuple<Buffer, Buffer>
+ getEKey(const Name& eKeyName);
+
+ /// @brief Delete a EKey to the database
+ void
+ deleteEKey(const Name& eKeyName);
+
+ /// @brief The method should be called periodically because the table size will keep growing
+ void
+ cleanEKeys();
+
private:
Name m_namespace;
GroupManagerDB m_db;