security: Add interface to request different key id generation
The option for key id include timestamp, random, and user-specified
value.
This commit only adds the interface, the support to honor the interface
will be implemented later.
Change-Id: I476381ff0fc56cd7906392cb7482b7458e386781
Refs: #2948
diff --git a/src/security/key-params.cpp b/src/security/key-params.cpp
index 7ee2e1e..792efe1 100644
--- a/src/security/key-params.cpp
+++ b/src/security/key-params.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2013-2014 Regents of the University of California.
+ * Copyright (c) 2013-2016 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -23,37 +23,50 @@
namespace ndn {
-static const uint32_t RSA_KEY_SIZES[] = {2048, 1024};
+static const uint32_t MIN_RSA_KEY_SIZE = 1024;
+static const uint32_t DEFAULT_RSA_KEY_SIZE = 2048;
static const uint32_t ECDSA_KEY_SIZES[] = {256, 384};
-static const uint32_t AES_KEY_SIZES[] = {64, 128, 256};
+static const uint32_t AES_KEY_SIZES[] = {128, 192, 256};
+
+KeyParams::~KeyParams() = default;
+
+KeyParams::KeyParams(KeyType keyType, KeyIdType keyIdType)
+ : m_keyType(keyType)
+ , m_keyIdType(keyIdType)
+{
+ BOOST_ASSERT(keyIdType != KeyIdType::USER_SPECIFIED);
+}
+
+KeyParams::KeyParams(KeyType keyType, const name::Component& keyId)
+ : m_keyType(keyType)
+ , m_keyIdType(KeyIdType::USER_SPECIFIED)
+ , m_keyId(keyId)
+{
+ BOOST_ASSERT(!keyId.empty());
+}
uint32_t
RsaKeyParamsInfo::checkKeySize(uint32_t size)
{
- for (size_t i = 0; i < (sizeof(RSA_KEY_SIZES) / sizeof(uint32_t)); i++)
- {
- if (RSA_KEY_SIZES[i] == size)
- return size;
- }
- return getDefaultSize();
+ if (size < MIN_RSA_KEY_SIZE)
+ BOOST_THROW_EXCEPTION(KeyParams::Error("Unsupported key size"));
+ return size;
}
uint32_t
RsaKeyParamsInfo::getDefaultSize()
{
- return RSA_KEY_SIZES[0];
+ return DEFAULT_RSA_KEY_SIZE;
}
uint32_t
EcdsaKeyParamsInfo::checkKeySize(uint32_t size)
{
-
- for (size_t i = 0; i < (sizeof(ECDSA_KEY_SIZES) / sizeof(uint32_t)); i++)
- {
- if (ECDSA_KEY_SIZES[i] == size)
- return size;
- }
- return getDefaultSize();
+ for (size_t i = 0; i < (sizeof(ECDSA_KEY_SIZES) / sizeof(ECDSA_KEY_SIZES[0])); i++) {
+ if (ECDSA_KEY_SIZES[i] == size)
+ return size;
+ }
+ BOOST_THROW_EXCEPTION(KeyParams::Error("Unsupported key size"));
}
uint32_t
@@ -66,12 +79,11 @@
uint32_t
AesKeyParamsInfo::checkKeySize(uint32_t size)
{
- for (size_t i = 0; i < (sizeof(AES_KEY_SIZES) / sizeof(uint32_t)); i++)
- {
- if (AES_KEY_SIZES[i] == size)
- return size;
- }
- return getDefaultSize();
+ for (size_t i = 0; i < (sizeof(AES_KEY_SIZES) / sizeof(AES_KEY_SIZES[0])); i++) {
+ if (AES_KEY_SIZES[i] == size)
+ return size;
+ }
+ BOOST_THROW_EXCEPTION(KeyParams::Error("Unsupported key size"));
}
uint32_t
diff --git a/src/security/key-params.hpp b/src/security/key-params.hpp
index 9769270..8f28a3e 100644
--- a/src/security/key-params.hpp
+++ b/src/security/key-params.hpp
@@ -23,6 +23,7 @@
#define NDN_SECURITY_KEY_PARAMS_HPP
#include "../common.hpp"
+#include "../name-component.hpp"
#include "security-common.hpp"
namespace ndn {
@@ -46,9 +47,7 @@
};
virtual
- ~KeyParams()
- {
- }
+ ~KeyParams();
KeyType
getKeyType() const
@@ -56,15 +55,48 @@
return m_keyType;
}
-protected:
- explicit
- KeyParams(KeyType keyType)
- : m_keyType(keyType)
+ KeyIdType
+ getKeyIdType() const
{
+ return m_keyIdType;
}
+ void
+ setKeyId(const name::Component& keyId)
+ {
+ m_keyId = keyId;
+ }
+
+ const name::Component&
+ getKeyId() const
+ {
+ return m_keyId;
+ }
+
+protected:
+ /**
+ * @brief Create a key generation parameter
+ *
+ * @param keyType Type of the created key
+ * @param keyIdType The method how the key id should be generated; must not be
+ KeyIdType::USER_SPECIFIED
+ */
+ KeyParams(KeyType keyType, KeyIdType keyIdType);
+
+ /**
+ * @brief Create a key generation parameter
+ *
+ * @param keyType Type of the created key
+ * @param keyId The user-specified key id. The keyIdType will be set to KeyIdType::USER_SPECIFIED.
+ * keyId MUST NOT be the empty component.
+ * @post getKeyIdType() == KeyIdType::USER_SPECIFIED
+ */
+ KeyParams(KeyType keyType, const name::Component& keyId);
+
private:
KeyType m_keyType;
+ KeyIdType m_keyIdType;
+ name::Component m_keyId;
};
@@ -78,7 +110,11 @@
return KeyType::RSA;
}
- /// @brief check if size is qualified, otherwise return the default key size.
+ /**
+ * @brief check if @p size is qualified.
+ *
+ * @throw KeyParams::Error if the key size is not supported.
+ */
static uint32_t
checkKeySize(uint32_t size);
@@ -96,7 +132,11 @@
return KeyType::EC;
}
- /// @brief check if size is qualified, otherwise return the default key size.
+ /**
+ * @brief check if @p size is qualified.
+ *
+ * @throw KeyParams::Error if the key size is not supported.
+ */
static uint32_t
checkKeySize(uint32_t size);
@@ -110,25 +150,27 @@
class SimplePublicKeyParams : public KeyParams
{
public:
+ /// @brief Create key parameter with user specified @p keyId.
explicit
- SimplePublicKeyParams(uint32_t size = KeyParamsInfo::getDefaultSize())
- : KeyParams(KeyParamsInfo::getType())
+ SimplePublicKeyParams(const name::Component& keyId,
+ uint32_t size = KeyParamsInfo::getDefaultSize())
+ : KeyParams(KeyParamsInfo::getType(), keyId)
{
setKeySize(size);
}
+ /**
+ * @brief Create key parameter with auto-created keyId.
+ *
+ * This method is used only if user does not want to maintain the uniqueness of key name.
+ * By default, an 8-byte random number will be used as the key Id.
+ */
explicit
- SimplePublicKeyParams(const SimplePublicKeyParams& params)
- : KeyParams(params)
- , m_size(params.m_size)
+ SimplePublicKeyParams(uint32_t size = KeyParamsInfo::getDefaultSize(),
+ KeyIdType keyIdType = KeyIdType::RANDOM)
+ : KeyParams(KeyParamsInfo::getType(), keyIdType)
{
- }
-
- explicit
- SimplePublicKeyParams(const KeyParams& params)
- : KeyParams(params.getKeyType())
- {
- BOOST_THROW_EXCEPTION(KeyParams::Error("Incorrect key parameters (incompatible key type)"));
+ setKeySize(size);
}
uint32_t
@@ -171,7 +213,11 @@
return KeyType::AES;
}
- /// @brief check if size is qualified, otherwise return the default key size.
+ /**
+ * @brief check if @p size is qualified.
+ *
+ * @return KeyParams::Error if the key size is not supported.
+ */
static uint32_t
checkKeySize(uint32_t size);
@@ -185,26 +231,15 @@
class SimpleSymmetricKeyParams : public KeyParams
{
public:
+ /// @brief Create key parameter with user specified @p keyId.
explicit
- SimpleSymmetricKeyParams(uint32_t size = KeyParamsInfo::getDefaultSize())
- : KeyParams(KeyParamsInfo::getType())
+ SimpleSymmetricKeyParams(const name::Component& keyId,
+ uint32_t size = KeyParamsInfo::getDefaultSize())
+ : KeyParams(KeyParamsInfo::getType(), keyId)
{
setKeySize(size);
}
- explicit
- SimpleSymmetricKeyParams(const SimpleSymmetricKeyParams& params)
- : KeyParams(params)
- , m_size(params.m_size)
- {
- }
-
- explicit
- SimpleSymmetricKeyParams(const KeyParams& params)
- {
- BOOST_THROW_EXCEPTION(KeyParams::Error("Incorrect key parameters (incompatible key type)"));
- }
-
uint32_t
getKeySize() const
{
@@ -226,7 +261,6 @@
private:
uint32_t m_size;
-
};
typedef SimpleSymmetricKeyParams<AesKeyParamsInfo> AesKeyParams;
diff --git a/src/security/security-common.cpp b/src/security/security-common.cpp
index 0ea60cb..cda5fc5 100644
--- a/src/security/security-common.cpp
+++ b/src/security/security-common.cpp
@@ -25,120 +25,99 @@
namespace ndn {
std::ostream&
+operator<<(std::ostream& os, KeyIdType keyIdType)
+{
+ switch (keyIdType) {
+ case KeyIdType::USER_SPECIFIED:
+ return os << "USER_SPECIFIED";
+ case KeyIdType::SHA256:
+ return os << "SHA256";
+ case KeyIdType::RANDOM:
+ return os << "RANDOM";
+ }
+ return os << static_cast<int>(keyIdType);
+}
+
+std::ostream&
operator<<(std::ostream& os, KeyType keyType)
{
switch (keyType) {
- case KeyType::NONE:
- os << "NONE";
- break;
- case KeyType::RSA:
- os << "RSA";
- break;
- case KeyType::EC:
- os << "EC";
- break;
- case KeyType::AES:
- os << "AES";
- break;
- default:
- os << static_cast<int>(keyType);
- break;
+ case KeyType::NONE:
+ return os << "NONE";
+ case KeyType::RSA:
+ return os << "RSA";
+ case KeyType::EC:
+ return os << "EC";
+ case KeyType::AES:
+ return os << "AES";
};
- return os;
+ return os << static_cast<int>(keyType);
}
std::ostream&
operator<<(std::ostream& os, KeyClass keyClass)
{
switch (keyClass) {
- case KeyClass::NONE:
- os << "NONE";
- break;
- case KeyClass::PUBLIC:
- os << "PUBLIC";
- break;
- case KeyClass::PRIVATE:
- os << "PRIVATE";
- break;
- case KeyClass::SYMMETRIC:
- os << "SYMMETRIC";
- break;
- default:
- os << static_cast<int>(keyClass);
- break;
+ case KeyClass::NONE:
+ return os << "NONE";
+ case KeyClass::PUBLIC:
+ return os << "PUBLIC";
+ case KeyClass::PRIVATE:
+ return os << "PRIVATE";
+ case KeyClass::SYMMETRIC:
+ return os << "SYMMETRIC";
};
- return os;
+ return os << static_cast<int>(keyClass);
}
std::ostream&
operator<<(std::ostream& os, DigestAlgorithm algorithm)
{
switch (algorithm) {
- case DigestAlgorithm::NONE:
- os << "NONE";
- break;
- case DigestAlgorithm::SHA256:
- os << "SHA256";
- break;
- default:
- os << static_cast<int>(algorithm);
- break;
+ case DigestAlgorithm::NONE:
+ return os << "NONE";
+ case DigestAlgorithm::SHA256:
+ return os << "SHA256";
};
- return os;
+ return os << static_cast<int>(algorithm);
}
std::ostream&
operator<<(std::ostream& os, BlockCipherAlgorithm algorithm)
{
switch (algorithm) {
- case BlockCipherAlgorithm::NONE:
- os << "NONE";
- break;
- case BlockCipherAlgorithm::AES_CBC:
- os << "AES_CBC";
- break;
- default:
- os << static_cast<int>(algorithm);
- break;
+ case BlockCipherAlgorithm::NONE:
+ return os << "NONE";
+ case BlockCipherAlgorithm::AES_CBC:
+ return os << "AES_CBC";
};
- return os;
+ return os << static_cast<int>(algorithm);
}
std::ostream&
operator<<(std::ostream& os, CipherOperator op)
{
switch (op) {
- case CipherOperator::DECRYPT:
- os << "DECRYPT";
- break;
- case CipherOperator::ENCRYPT:
- os << "ENCRYPT";
- break;
- default:
- os << static_cast<int>(op);
- break;
+ case CipherOperator::DECRYPT:
+ return os << "DECRYPT";
+ case CipherOperator::ENCRYPT:
+ return os << "ENCRYPT";
};
- return os;
+ return os << static_cast<int>(op);
}
std::ostream&
operator<<(std::ostream& os, AclType aclType)
{
switch (aclType) {
- case AclType::NONE:
- os << "NONE";
- break;
- case AclType::PUBLIC:
- os << "PUBLIC";
- break;
- case AclType::PRIVATE:
- os << "PRIVATE";
- break;
- default:
- os << static_cast<int>(aclType);
- break;
+ case AclType::NONE:
+ return os << "NONE";
+ case AclType::PUBLIC:
+ return os << "PUBLIC";
+ case AclType::PRIVATE:
+ return os << "PRIVATE";
};
- return os;
+ return os << static_cast<int>(aclType);
}
} // namespace ndn
diff --git a/src/security/security-common.hpp b/src/security/security-common.hpp
index bd709f5..ef9a42b 100644
--- a/src/security/security-common.hpp
+++ b/src/security/security-common.hpp
@@ -47,6 +47,33 @@
} // namespace signed_interest
+/**
+ * @brief The type of KeyId component in a key name
+ */
+enum class KeyIdType {
+ /**
+ * @brief User-specified key ID
+ *
+ * It is user's responsibility to assure the uniqueness of the key names.
+ */
+ USER_SPECIFIED = 0,
+ /**
+ * @brief Use the SHA256 hash of the public key as the key id
+ *
+ * This KeyId type guarantees the uniqueness of the key names.
+ */
+ SHA256 = 1,
+ /**
+ * @brief Use a 64-bit random number as the key id
+ *
+ * This KeyId provides roughly uniqueness of the key names.
+ */
+ RANDOM = 2
+};
+
+std::ostream&
+operator<<(std::ostream& os, KeyIdType keyIdType);
+
enum class KeyType {
NONE = 0,
RSA = 1,
diff --git a/tests/unit-tests/security/key-params.t.cpp b/tests/unit-tests/security/key-params.t.cpp
index a1fefa4..f8efed1 100644
--- a/tests/unit-tests/security/key-params.t.cpp
+++ b/tests/unit-tests/security/key-params.t.cpp
@@ -23,6 +23,8 @@
#include "boost-test.hpp"
+#include <boost/lexical_cast.hpp>
+
namespace ndn {
namespace tests {
@@ -34,14 +36,21 @@
RsaKeyParams params;
BOOST_CHECK_EQUAL(params.getKeyType(), KeyType::RSA);
BOOST_CHECK_EQUAL(params.getKeySize(), 2048);
+ BOOST_CHECK(params.getKeyIdType() == KeyIdType::RANDOM);
- RsaKeyParams params2(1024);
+ RsaKeyParams params2(1024, KeyIdType::SHA256);
BOOST_CHECK_EQUAL(params2.getKeyType(), KeyType::RSA);
BOOST_CHECK_EQUAL(params2.getKeySize(), 1024);
+ BOOST_CHECK(params2.getKeyIdType() == KeyIdType::SHA256);
- RsaKeyParams params3(3);
- BOOST_CHECK_EQUAL(params3.getKeyType(), KeyType::RSA);
- BOOST_CHECK_EQUAL(params3.getKeySize(), 2048);
+ BOOST_CHECK_THROW(RsaKeyParams(3), KeyParams::Error);
+
+ name::Component keyId("keyId");
+ RsaKeyParams params4(keyId);
+ BOOST_CHECK(params4.getKeyType() == KeyType::RSA);
+ BOOST_CHECK_EQUAL(params4.getKeySize(), 2048);
+ BOOST_CHECK(params4.getKeyIdType() == KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params4.getKeyId(), keyId);
}
BOOST_AUTO_TEST_CASE(Ecdsa)
@@ -49,44 +58,59 @@
EcdsaKeyParams params;
BOOST_CHECK_EQUAL(params.getKeyType(), KeyType::EC);
BOOST_CHECK_EQUAL(params.getKeySize(), 256);
+ BOOST_CHECK(params.getKeyIdType() == KeyIdType::RANDOM);
- EcdsaKeyParams params2(384);
+ EcdsaKeyParams params2(384, KeyIdType::SHA256);
BOOST_CHECK_EQUAL(params2.getKeyType(), KeyType::EC);
BOOST_CHECK_EQUAL(params2.getKeySize(), 384);
+ BOOST_CHECK(params2.getKeyIdType() == KeyIdType::SHA256);
- EcdsaKeyParams params3(3);
- BOOST_CHECK_EQUAL(params3.getKeyType(), KeyType::EC);
- BOOST_CHECK_EQUAL(params3.getKeySize(), 256);
+ BOOST_CHECK_THROW(EcdsaKeyParams(3), KeyParams::Error);
+
+ name::Component keyId("keyId");
+ EcdsaKeyParams params4(keyId);
+ BOOST_CHECK(params4.getKeyType() == KeyType::EC);
+ BOOST_CHECK_EQUAL(params4.getKeySize(), 256);
+ BOOST_CHECK(params4.getKeyIdType() == KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params4.getKeyId(), keyId);
}
BOOST_AUTO_TEST_CASE(Aes)
{
- AesKeyParams params;
+ name::Component keyId("keyId");
+ AesKeyParams params(keyId);
BOOST_CHECK_EQUAL(params.getKeyType(), KeyType::AES);
- BOOST_CHECK_EQUAL(params.getKeySize(), 64);
+ BOOST_CHECK_EQUAL(params.getKeySize(), 128);
+ BOOST_CHECK_EQUAL(params.getKeyIdType(), KeyIdType::USER_SPECIFIED);
- AesKeyParams params2(128);
- BOOST_CHECK_EQUAL(params2.getKeyType(), KeyType::AES);
- BOOST_CHECK_EQUAL(params2.getKeySize(), 128);
+ AesKeyParams params2(keyId, 192);
+ BOOST_CHECK(params2.getKeyType() == KeyType::AES);
+ BOOST_CHECK_EQUAL(params2.getKeySize(), 192);
+ BOOST_CHECK(params.getKeyIdType() == KeyIdType::USER_SPECIFIED);
- AesKeyParams params3(256);
+ AesKeyParams params3(keyId, 256);
BOOST_CHECK_EQUAL(params3.getKeyType(), KeyType::AES);
BOOST_CHECK_EQUAL(params3.getKeySize(), 256);
+ BOOST_CHECK(params.getKeyIdType() == KeyIdType::USER_SPECIFIED);
- AesKeyParams params4(4);
- BOOST_CHECK_EQUAL(params4.getKeyType(), KeyType::AES);
- BOOST_CHECK_EQUAL(params4.getKeySize(), 64);
+ BOOST_CHECK_THROW(AesKeyParams(keyId, 4), KeyParams::Error);
+
+ AesKeyParams params5(keyId);
+ BOOST_CHECK_EQUAL(params5.getKeyType(), KeyType::AES);
+ BOOST_CHECK_EQUAL(params5.getKeySize(), 128);
+ BOOST_CHECK_EQUAL(params5.getKeyIdType(), KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params5.getKeyId(), keyId);
}
-BOOST_AUTO_TEST_CASE(Error)
+BOOST_AUTO_TEST_CASE(KeyIdTypeInfo)
{
- EcdsaKeyParams params;
- BOOST_REQUIRE_THROW((RsaKeyParams(params)), KeyParams::Error);
-
- AesKeyParams params2;
- BOOST_REQUIRE_THROW((RsaKeyParams(params2)), KeyParams::Error);
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyIdType::USER_SPECIFIED), "USER_SPECIFIED");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyIdType::SHA256), "SHA256");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyIdType::RANDOM), "RANDOM");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(static_cast<KeyIdType>(12345)), "12345");
}
+
BOOST_AUTO_TEST_SUITE_END() // TestKeyParams
BOOST_AUTO_TEST_SUITE_END() // Security