security: add HMAC support to SignerFilter and VerifierFilter
Introduce HmacKeyParams
Add HMAC support to transform::PrivateKey
Deprecate HmacFilter
Refs: #3075
Change-Id: I16e24c1c4f278b08c7f51c91e9317b7820943536
diff --git a/ndn-cxx/security/key-params.cpp b/ndn-cxx/security/key-params.cpp
index 9d12bc8..e1f38b8 100644
--- a/ndn-cxx/security/key-params.cpp
+++ b/ndn-cxx/security/key-params.cpp
@@ -23,13 +23,6 @@
namespace ndn {
-static const uint32_t MIN_RSA_KEY_SIZE = 2048;
-static const uint32_t DEFAULT_RSA_KEY_SIZE = 2048;
-static const uint32_t EC_KEY_SIZES[] = {224, 256, 384, 521};
-static const uint32_t DEFAULT_EC_KEY_SIZE = 256;
-static const uint32_t AES_KEY_SIZES[] = {128, 192, 256};
-static const uint32_t DEFAULT_AES_KEY_SIZE = 128;
-
KeyParams::KeyParams(KeyType keyType, KeyIdType keyIdType)
: m_keyType(keyType)
, m_keyIdType(keyIdType)
@@ -49,6 +42,15 @@
namespace detail {
+const uint32_t MIN_RSA_KEY_SIZE = 2048;
+const uint32_t DEFAULT_RSA_KEY_SIZE = 2048;
+const uint32_t EC_KEY_SIZES[] = {224, 256, 384, 521};
+const uint32_t DEFAULT_EC_KEY_SIZE = 256;
+const uint32_t AES_KEY_SIZES[] = {128, 192, 256};
+const uint32_t DEFAULT_AES_KEY_SIZE = 128;
+const uint32_t MIN_HMAC_KEY_SIZE = 224;
+const uint32_t DEFAULT_HMAC_KEY_SIZE = 256;
+
uint32_t
RsaKeyParamsInfo::checkKeySize(uint32_t size)
{
@@ -95,5 +97,22 @@
return DEFAULT_AES_KEY_SIZE;
}
+uint32_t
+HmacKeyParamsInfo::checkKeySize(uint32_t size)
+{
+ // the minimum key size depends on the exact digest algorithm used in the HMAC, so we
+ // only do a basic sanity check here and postpone stricter checking until the actual
+ // HMAC computation in SignerFilter/VerifierFilter, where the digest algorithm is known
+ if (size < MIN_HMAC_KEY_SIZE || size % 8 != 0)
+ NDN_THROW(KeyParams::Error("Unsupported HMAC key size " + to_string(size)));
+ return size;
+}
+
+uint32_t
+HmacKeyParamsInfo::getDefaultSize()
+{
+ return DEFAULT_HMAC_KEY_SIZE;
+}
+
} // namespace detail
} // namespace ndn
diff --git a/ndn-cxx/security/key-params.hpp b/ndn-cxx/security/key-params.hpp
index a7c52b4..4d424c4 100644
--- a/ndn-cxx/security/key-params.hpp
+++ b/ndn-cxx/security/key-params.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -28,7 +28,7 @@
namespace ndn {
/**
- * @brief Base class of key parameters.
+ * @brief Base class for key parameters.
*
* Its subclasses are used to store parameters for key generation.
*/
@@ -70,7 +70,7 @@
protected:
/**
- * @brief Create a key generation parameter
+ * @brief Constructor
*
* @param keyType Type of the created key
* @param keyIdType The method how the key id should be generated; must not be
@@ -79,7 +79,7 @@
KeyParams(KeyType keyType, KeyIdType keyIdType);
/**
- * @brief Create a key generation parameter
+ * @brief Constructor
*
* @param keyType Type of the created key
* @param keyId The user-specified key id. The keyIdType will be set to KeyIdType::USER_SPECIFIED.
@@ -149,7 +149,7 @@
class SimplePublicKeyParams : public KeyParams
{
public:
- /// @brief Create key parameter with user specified @p keyId.
+ /// @brief Create key parameters with user-specified key id.
explicit
SimplePublicKeyParams(const name::Component& keyId,
uint32_t size = KeyParamsInfo::getDefaultSize())
@@ -159,10 +159,10 @@
}
/**
- * @brief Create key parameter with auto-created keyId.
+ * @brief Create key parameters with auto-generated key id.
*
* 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.
+ * By default, an 8-byte random number will be used as key id.
*/
explicit
SimplePublicKeyParams(uint32_t size = KeyParamsInfo::getDefaultSize(),
@@ -217,7 +217,29 @@
/**
* @brief check if @p size is valid and supported for this key type.
*
- * @return KeyParams::Error if the key size is not supported.
+ * @throw KeyParams::Error if the key size is not supported.
+ */
+ static uint32_t
+ checkKeySize(uint32_t size);
+
+ static uint32_t
+ getDefaultSize();
+};
+
+/// @brief HmacKeyParamsInfo is used to instantiate SimpleSymmetricKeyParams for HMAC keys.
+class HmacKeyParamsInfo
+{
+public:
+ static constexpr KeyType
+ getType()
+ {
+ return KeyType::HMAC;
+ }
+
+ /**
+ * @brief check if @p size is valid and supported for this key type.
+ *
+ * @throw KeyParams::Error if the key size is not supported.
*/
static uint32_t
checkKeySize(uint32_t size);
@@ -234,7 +256,7 @@
class SimpleSymmetricKeyParams : public KeyParams
{
public:
- /// @brief Create key parameter with user specified @p keyId.
+ /// @brief Create key parameters with user-specified key id.
explicit
SimpleSymmetricKeyParams(const name::Component& keyId,
uint32_t size = KeyParamsInfo::getDefaultSize())
@@ -244,10 +266,10 @@
}
/**
- * @brief Create key parameter with auto-created keyId.
+ * @brief Create key parameters with auto-generated key id.
*
* 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.
+ * By default, an 8-byte random number will be used as key id.
*/
explicit
SimpleSymmetricKeyParams(uint32_t size = KeyParamsInfo::getDefaultSize(),
@@ -283,6 +305,9 @@
/// @brief AesKeyParams carries parameters for AES key.
typedef SimpleSymmetricKeyParams<detail::AesKeyParamsInfo> AesKeyParams;
+/// @brief HmacKeyParams carries parameters for HMAC key.
+typedef SimpleSymmetricKeyParams<detail::HmacKeyParamsInfo> HmacKeyParams;
+
} // namespace ndn
#endif // NDN_SECURITY_KEY_PARAMS_HPP
diff --git a/ndn-cxx/security/security-common.cpp b/ndn-cxx/security/security-common.cpp
index dd20f6e..93ba0da 100644
--- a/ndn-cxx/security/security-common.cpp
+++ b/ndn-cxx/security/security-common.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -51,6 +51,8 @@
return os << "EC";
case KeyType::AES:
return os << "AES";
+ case KeyType::HMAC:
+ return os << "HMAC";
}
return os << static_cast<int>(keyType);
}
diff --git a/ndn-cxx/security/security-common.hpp b/ndn-cxx/security/security-common.hpp
index c4ec0fd..92067b7 100644
--- a/ndn-cxx/security/security-common.hpp
+++ b/ndn-cxx/security/security-common.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -87,6 +87,7 @@
RSA = 1, ///< RSA key, supports sign/verify and encrypt/decrypt operations
EC = 2, ///< Elliptic Curve key (e.g. for ECDSA), supports sign/verify operations
AES = 128, ///< AES key, supports encrypt/decrypt operations
+ HMAC = 256, ///< HMAC key, supports sign/verify operations
};
std::ostream&
diff --git a/ndn-cxx/security/transform/hmac-filter.hpp b/ndn-cxx/security/transform/hmac-filter.hpp
index f7f3304..2254ba7 100644
--- a/ndn-cxx/security/transform/hmac-filter.hpp
+++ b/ndn-cxx/security/transform/hmac-filter.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -31,6 +31,8 @@
/**
* @brief The module to generate HMAC for input data.
+ *
+ * @deprecated Use SignerFilter and VerifierFilter.
*/
class HmacFilter : public Transform
{
@@ -63,6 +65,7 @@
const unique_ptr<Impl> m_impl;
};
+[[deprecated("use signerFilter and verifierFilter")]]
unique_ptr<Transform>
hmacFilter(DigestAlgorithm algo, const uint8_t* key, size_t keyLen);
diff --git a/ndn-cxx/security/transform/private-key.cpp b/ndn-cxx/security/transform/private-key.cpp
index 91bfbeb..f4029d3 100644
--- a/ndn-cxx/security/transform/private-key.cpp
+++ b/ndn-cxx/security/transform/private-key.cpp
@@ -28,6 +28,7 @@
#include "ndn-cxx/security/impl/openssl-helper.hpp"
#include "ndn-cxx/security/key-params.hpp"
#include "ndn-cxx/encoding/buffer-stream.hpp"
+#include "ndn-cxx/util/random.hpp"
#include <boost/lexical_cast.hpp>
#include <cstring>
@@ -60,21 +61,16 @@
#endif // OPENSSL_VERSION_NUMBER < 0x1010000fL
}
-class PrivateKey::Impl
+class PrivateKey::Impl : noncopyable
{
public:
- Impl() noexcept
- : key(nullptr)
- {
- }
-
~Impl()
{
EVP_PKEY_free(key);
}
public:
- EVP_PKEY* key;
+ EVP_PKEY* key = nullptr;
};
PrivateKey::PrivateKey()
@@ -95,6 +91,8 @@
return KeyType::RSA;
case EVP_PKEY_EC:
return KeyType::EC;
+ case EVP_PKEY_HMAC:
+ return KeyType::HMAC;
default:
return KeyType::NONE;
}
@@ -388,6 +386,7 @@
if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
NDN_THROW(PrivateKey::Error("Failed to generate RSA key"));
+ privateKey->m_keySize = keySize;
return privateKey;
}
@@ -431,6 +430,27 @@
if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
NDN_THROW(PrivateKey::Error("Failed to generate EC key"));
+ privateKey->m_keySize = keySize;
+ return privateKey;
+}
+
+unique_ptr<PrivateKey>
+PrivateKey::generateHmacKey(uint32_t keySize)
+{
+ std::vector<uint8_t> rawKey(keySize / 8);
+ random::generateSecureBytes(rawKey.data(), rawKey.size());
+
+ auto privateKey = make_unique<PrivateKey>();
+ privateKey->m_impl->key =
+#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
+ EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, nullptr, rawKey.data(), rawKey.size());
+#else
+ EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, rawKey.data(), static_cast<int>(rawKey.size()));
+#endif
+ if (privateKey->m_impl->key == nullptr)
+ NDN_THROW(PrivateKey::Error("Failed to generate HMAC key"));
+
+ privateKey->m_keySize = keySize;
return privateKey;
}
@@ -446,6 +466,10 @@
const EcKeyParams& ecParams = static_cast<const EcKeyParams&>(keyParams);
return PrivateKey::generateEcKey(ecParams.getKeySize());
}
+ case KeyType::HMAC: {
+ const HmacKeyParams& hmacParams = static_cast<const HmacKeyParams&>(keyParams);
+ return PrivateKey::generateHmacKey(hmacParams.getKeySize());
+ }
default:
NDN_THROW(std::invalid_argument("Unsupported asymmetric key type " +
boost::lexical_cast<std::string>(keyParams.getKeyType())));
diff --git a/ndn-cxx/security/transform/private-key.hpp b/ndn-cxx/security/transform/private-key.hpp
index 093efe2..d3ae45c 100644
--- a/ndn-cxx/security/transform/private-key.hpp
+++ b/ndn-cxx/security/transform/private-key.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -71,6 +71,18 @@
getKeyType() const;
/**
+ * @brief Get the size of the private key in bits
+ *
+ * @note The return value is meaningful only if the PrivateKey was created via
+ * generatePrivateKey(), otherwise this function will always return zero.
+ */
+ size_t
+ getKeySize() const
+ {
+ return m_keySize;
+ }
+
+ /**
* @brief Load the private key in PKCS#1 format from a buffer @p buf
*/
void
@@ -218,6 +230,7 @@
private:
friend class SignerFilter;
+ friend class VerifierFilter;
/**
* @return A pointer to an OpenSSL EVP_PKEY instance.
@@ -249,9 +262,14 @@
static unique_ptr<PrivateKey>
generateEcKey(uint32_t keySize);
+ static unique_ptr<PrivateKey>
+ generateHmacKey(uint32_t keySize);
+
private:
class Impl;
const unique_ptr<Impl> m_impl;
+
+ size_t m_keySize = 0;
};
/**
diff --git a/ndn-cxx/security/transform/signer-filter.cpp b/ndn-cxx/security/transform/signer-filter.cpp
index 33f380f..ddaf4cd 100644
--- a/ndn-cxx/security/transform/signer-filter.cpp
+++ b/ndn-cxx/security/transform/signer-filter.cpp
@@ -44,6 +44,13 @@
NDN_THROW(Error(getIndex(), "Unsupported digest algorithm " +
boost::lexical_cast<std::string>(algo)));
+ if (key.getKeyType() == KeyType::HMAC) {
+ size_t mdSize = static_cast<size_t>(EVP_MD_size(md)) * 8;
+ if (key.getKeySize() < mdSize)
+ NDN_THROW(Error(getIndex(), "HMAC key is shorter than the digest output (" +
+ to_string(key.getKeySize()) + " < " + to_string(mdSize) + ")"));
+ }
+
if (EVP_DigestSignInit(m_impl->ctx, nullptr, md, nullptr,
reinterpret_cast<EVP_PKEY*>(key.getEvpPkey())) != 1)
NDN_THROW(Error(getIndex(), "Failed to initialize signing context with " +
diff --git a/ndn-cxx/security/transform/verifier-filter.cpp b/ndn-cxx/security/transform/verifier-filter.cpp
index 98cb3c1..afcfd3d 100644
--- a/ndn-cxx/security/transform/verifier-filter.cpp
+++ b/ndn-cxx/security/transform/verifier-filter.cpp
@@ -20,6 +20,7 @@
*/
#include "ndn-cxx/security/transform/verifier-filter.hpp"
+#include "ndn-cxx/security/transform/private-key.hpp"
#include "ndn-cxx/security/transform/public-key.hpp"
#include "ndn-cxx/security/impl/openssl-helper.hpp"
@@ -48,25 +49,54 @@
VerifierFilter::VerifierFilter(DigestAlgorithm algo, const PublicKey& key,
const uint8_t* sig, size_t sigLen)
: m_impl(make_unique<Impl>(sig, sigLen))
+ , m_keyType(key.getKeyType())
+{
+ init(algo, key.getEvpPkey());
+}
+
+VerifierFilter::VerifierFilter(DigestAlgorithm algo, const PrivateKey& key,
+ const uint8_t* sig, size_t sigLen)
+ : m_impl(make_unique<Impl>(sig, sigLen))
+ , m_keyType(key.getKeyType())
+{
+ if (m_keyType != KeyType::HMAC)
+ NDN_THROW(Error(getIndex(), "VerifierFilter only supports private keys of HMAC type"));
+
+ init(algo, key.getEvpPkey());
+}
+
+VerifierFilter::~VerifierFilter() = default;
+
+void
+VerifierFilter::init(DigestAlgorithm algo, void* pkey)
{
const EVP_MD* md = detail::digestAlgorithmToEvpMd(algo);
if (md == nullptr)
NDN_THROW(Error(getIndex(), "Unsupported digest algorithm " +
boost::lexical_cast<std::string>(algo)));
- if (EVP_DigestVerifyInit(m_impl->ctx, nullptr, md, nullptr,
- reinterpret_cast<EVP_PKEY*>(key.getEvpPkey())) != 1)
+ int ret;
+ if (m_keyType == KeyType::HMAC)
+ ret = EVP_DigestSignInit(m_impl->ctx, nullptr, md, nullptr, reinterpret_cast<EVP_PKEY*>(pkey));
+ else
+ ret = EVP_DigestVerifyInit(m_impl->ctx, nullptr, md, nullptr, reinterpret_cast<EVP_PKEY*>(pkey));
+
+ if (ret != 1)
NDN_THROW(Error(getIndex(), "Failed to initialize verification context with " +
boost::lexical_cast<std::string>(algo) + " digest and " +
- boost::lexical_cast<std::string>(key.getKeyType()) + " key"));
+ boost::lexical_cast<std::string>(m_keyType) + " key"));
}
-VerifierFilter::~VerifierFilter() = default;
-
size_t
VerifierFilter::convert(const uint8_t* buf, size_t size)
{
- if (EVP_DigestVerifyUpdate(m_impl->ctx, buf, size) != 1)
+ int ret;
+ if (m_keyType == KeyType::HMAC)
+ ret = EVP_DigestSignUpdate(m_impl->ctx, buf, size);
+ else
+ ret = EVP_DigestVerifyUpdate(m_impl->ctx, buf, size);
+
+ if (ret != 1)
NDN_THROW(Error(getIndex(), "Failed to accept more input"));
return size;
@@ -75,18 +105,35 @@
void
VerifierFilter::finalize()
{
- int res = EVP_DigestVerifyFinal(m_impl->ctx, m_impl->sig, m_impl->siglen);
+ bool ok = false;
+ if (m_keyType == KeyType::HMAC) {
+ auto hmacBuf = make_unique<OBuffer>(EVP_MAX_MD_SIZE);
+ size_t hmacLen = 0;
+
+ if (EVP_DigestSignFinal(m_impl->ctx, hmacBuf->data(), &hmacLen) != 1)
+ NDN_THROW(Error(getIndex(), "Failed to finalize HMAC"));
+
+ ok = CRYPTO_memcmp(hmacBuf->data(), m_impl->sig, std::min(hmacLen, m_impl->siglen)) == 0;
+ }
+ else {
+ ok = EVP_DigestVerifyFinal(m_impl->ctx, m_impl->sig, m_impl->siglen) == 1;
+ }
auto buffer = make_unique<OBuffer>(1);
- (*buffer)[0] = (res == 1) ? 1 : 0;
+ (*buffer)[0] = ok ? 1 : 0;
setOutputBuffer(std::move(buffer));
flushAllOutput();
}
unique_ptr<Transform>
-verifierFilter(DigestAlgorithm algo, const PublicKey& key,
- const uint8_t* sig, size_t sigLen)
+verifierFilter(DigestAlgorithm algo, const PublicKey& key, const uint8_t* sig, size_t sigLen)
+{
+ return make_unique<VerifierFilter>(algo, key, sig, sigLen);
+}
+
+unique_ptr<Transform>
+verifierFilter(DigestAlgorithm algo, const PrivateKey& key, const uint8_t* sig, size_t sigLen)
{
return make_unique<VerifierFilter>(algo, key, sig, sigLen);
}
diff --git a/ndn-cxx/security/transform/verifier-filter.hpp b/ndn-cxx/security/transform/verifier-filter.hpp
index 967921a..deda280 100644
--- a/ndn-cxx/security/transform/verifier-filter.hpp
+++ b/ndn-cxx/security/transform/verifier-filter.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -29,26 +29,33 @@
namespace security {
namespace transform {
+class PrivateKey;
class PublicKey;
/**
* @brief The module to verify signatures.
*
* The next module in the chain is usually BoolSink.
- *
- * @note This module cannot be used to verify HMACs.
*/
class VerifierFilter : public Transform
{
public:
/**
- * @brief Create a verifier module to verify signature @p sig using algorithm @p algo and key @p key
+ * @brief Create a verifier module to verify signature @p sig using algorithm @p algo and public key @p key
*/
VerifierFilter(DigestAlgorithm algo, const PublicKey& key, const uint8_t* sig, size_t sigLen);
+ /**
+ * @brief Create a verifier module to verify signature @p sig using algorithm @p algo and HMAC key @p key
+ */
+ VerifierFilter(DigestAlgorithm algo, const PrivateKey& key, const uint8_t* sig, size_t sigLen);
+
~VerifierFilter();
private:
+ void
+ init(DigestAlgorithm algo, void* pkey);
+
/**
* @brief Write data @p buf into verifier
*
@@ -66,11 +73,16 @@
private:
class Impl;
const unique_ptr<Impl> m_impl;
+
+ KeyType m_keyType;
};
unique_ptr<Transform>
verifierFilter(DigestAlgorithm algo, const PublicKey& key, const uint8_t* sig, size_t sigLen);
+unique_ptr<Transform>
+verifierFilter(DigestAlgorithm algo, const PrivateKey& key, const uint8_t* sig, size_t sigLen);
+
} // namespace transform
} // namespace security
} // namespace ndn
diff --git a/tests/unit/security/key-params.t.cpp b/tests/unit/security/key-params.t.cpp
index 0fc6cd5..336520d 100644
--- a/tests/unit/security/key-params.t.cpp
+++ b/tests/unit/security/key-params.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -36,20 +36,20 @@
RsaKeyParams params;
BOOST_CHECK_EQUAL(params.getKeyType(), KeyType::RSA);
BOOST_CHECK_EQUAL(params.getKeySize(), 2048);
- BOOST_CHECK(params.getKeyIdType() == KeyIdType::RANDOM);
+ BOOST_CHECK_EQUAL(params.getKeyIdType(), KeyIdType::RANDOM);
RsaKeyParams params2(4096, KeyIdType::SHA256);
BOOST_CHECK_EQUAL(params2.getKeyType(), KeyType::RSA);
BOOST_CHECK_EQUAL(params2.getKeySize(), 4096);
- BOOST_CHECK(params2.getKeyIdType() == KeyIdType::SHA256);
+ BOOST_CHECK_EQUAL(params2.getKeyIdType(), KeyIdType::SHA256);
BOOST_CHECK_THROW(RsaKeyParams(1024), KeyParams::Error);
name::Component keyId("keyId");
RsaKeyParams params4(keyId);
- BOOST_CHECK(params4.getKeyType() == KeyType::RSA);
+ BOOST_CHECK_EQUAL(params4.getKeyType(), KeyType::RSA);
BOOST_CHECK_EQUAL(params4.getKeySize(), 2048);
- BOOST_CHECK(params4.getKeyIdType() == KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params4.getKeyIdType(), KeyIdType::USER_SPECIFIED);
BOOST_CHECK_EQUAL(params4.getKeyId(), keyId);
}
@@ -58,20 +58,20 @@
EcKeyParams params;
BOOST_CHECK_EQUAL(params.getKeyType(), KeyType::EC);
BOOST_CHECK_EQUAL(params.getKeySize(), 256);
- BOOST_CHECK(params.getKeyIdType() == KeyIdType::RANDOM);
+ BOOST_CHECK_EQUAL(params.getKeyIdType(), KeyIdType::RANDOM);
EcKeyParams params2(384, KeyIdType::SHA256);
BOOST_CHECK_EQUAL(params2.getKeyType(), KeyType::EC);
BOOST_CHECK_EQUAL(params2.getKeySize(), 384);
- BOOST_CHECK(params2.getKeyIdType() == KeyIdType::SHA256);
+ BOOST_CHECK_EQUAL(params2.getKeyIdType(), KeyIdType::SHA256);
- BOOST_CHECK_THROW(EcKeyParams(3), KeyParams::Error);
+ BOOST_CHECK_THROW(EcKeyParams(64), KeyParams::Error);
name::Component keyId("keyId");
EcKeyParams params4(keyId);
- BOOST_CHECK(params4.getKeyType() == KeyType::EC);
+ BOOST_CHECK_EQUAL(params4.getKeyType(), KeyType::EC);
BOOST_CHECK_EQUAL(params4.getKeySize(), 256);
- BOOST_CHECK(params4.getKeyIdType() == KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params4.getKeyIdType(), KeyIdType::USER_SPECIFIED);
BOOST_CHECK_EQUAL(params4.getKeyId(), keyId);
}
@@ -82,32 +82,73 @@
BOOST_CHECK_EQUAL(params.getKeyType(), KeyType::AES);
BOOST_CHECK_EQUAL(params.getKeySize(), 128);
BOOST_CHECK_EQUAL(params.getKeyIdType(), KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params.getKeyId(), keyId);
AesKeyParams params2(keyId, 192);
- BOOST_CHECK(params2.getKeyType() == KeyType::AES);
+ BOOST_CHECK_EQUAL(params2.getKeyType(), KeyType::AES);
BOOST_CHECK_EQUAL(params2.getKeySize(), 192);
- BOOST_CHECK(params.getKeyIdType() == KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params2.getKeyIdType(), KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params2.getKeyId(), keyId);
AesKeyParams params3(keyId, 256);
BOOST_CHECK_EQUAL(params3.getKeyType(), KeyType::AES);
BOOST_CHECK_EQUAL(params3.getKeySize(), 256);
- BOOST_CHECK(params.getKeyIdType() == KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params3.getKeyIdType(), KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params3.getKeyId(), keyId);
- BOOST_CHECK_THROW(AesKeyParams(keyId, 4), KeyParams::Error);
+ BOOST_CHECK_THROW(AesKeyParams(keyId, 64), KeyParams::Error);
- AesKeyParams params5(keyId);
+ AesKeyParams params4;
+ BOOST_CHECK_EQUAL(params4.getKeyType(), KeyType::AES);
+ BOOST_CHECK_EQUAL(params4.getKeySize(), 128);
+ BOOST_CHECK_EQUAL(params4.getKeyIdType(), KeyIdType::RANDOM);
+
+ AesKeyParams params5(192);
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);
-
- AesKeyParams params6(192);
- BOOST_CHECK(params6.getKeyType() == KeyType::AES);
- BOOST_CHECK_EQUAL(params6.getKeySize(), 192);
- BOOST_CHECK(params6.getKeyIdType() == KeyIdType::RANDOM);
+ BOOST_CHECK_EQUAL(params5.getKeySize(), 192);
+ BOOST_CHECK_EQUAL(params5.getKeyIdType(), KeyIdType::RANDOM);
}
-BOOST_AUTO_TEST_CASE(KeyIdTypeInfo)
+BOOST_AUTO_TEST_CASE(Hmac)
+{
+ name::Component keyId("keyId");
+ HmacKeyParams params(keyId);
+ BOOST_CHECK_EQUAL(params.getKeyType(), KeyType::HMAC);
+ BOOST_CHECK_EQUAL(params.getKeySize(), 256);
+ BOOST_CHECK_EQUAL(params.getKeyIdType(), KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params.getKeyId(), keyId);
+
+ HmacKeyParams params2(keyId, 384);
+ BOOST_CHECK_EQUAL(params2.getKeyType(), KeyType::HMAC);
+ BOOST_CHECK_EQUAL(params2.getKeySize(), 384);
+ BOOST_CHECK_EQUAL(params2.getKeyIdType(), KeyIdType::USER_SPECIFIED);
+ BOOST_CHECK_EQUAL(params2.getKeyId(), keyId);
+
+ BOOST_CHECK_THROW(HmacKeyParams(keyId, 192), KeyParams::Error); // too short
+ BOOST_CHECK_THROW(HmacKeyParams(keyId, 300), KeyParams::Error); // not a multiple of 8
+
+ HmacKeyParams params3;
+ BOOST_CHECK_EQUAL(params3.getKeyType(), KeyType::HMAC);
+ BOOST_CHECK_EQUAL(params3.getKeySize(), 256);
+ BOOST_CHECK_EQUAL(params3.getKeyIdType(), KeyIdType::RANDOM);
+
+ HmacKeyParams params4(1024);
+ BOOST_CHECK_EQUAL(params4.getKeyType(), KeyType::HMAC);
+ BOOST_CHECK_EQUAL(params4.getKeySize(), 1024);
+ BOOST_CHECK_EQUAL(params4.getKeyIdType(), KeyIdType::RANDOM);
+}
+
+BOOST_AUTO_TEST_CASE(KeyTypeToString)
+{
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyType::NONE), "NONE");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyType::RSA), "RSA");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyType::EC), "EC");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyType::AES), "AES");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyType::HMAC), "HMAC");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(static_cast<KeyType>(12345)), "12345");
+}
+
+BOOST_AUTO_TEST_CASE(KeyIdTypeToString)
{
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyIdType::USER_SPECIFIED), "USER_SPECIFIED");
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(KeyIdType::SHA256), "SHA256");
diff --git a/tests/unit/security/transform/private-key.t.cpp b/tests/unit/security/transform/private-key.t.cpp
index 0cef079..de1d9b2 100644
--- a/tests/unit/security/transform/private-key.t.cpp
+++ b/tests/unit/security/transform/private-key.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -22,8 +22,15 @@
#include "ndn-cxx/security/transform/private-key.hpp"
#include "ndn-cxx/encoding/buffer-stream.hpp"
+#include "ndn-cxx/security/impl/openssl.hpp"
#include "ndn-cxx/security/key-params.hpp"
-#include "ndn-cxx/security/transform.hpp"
+#include "ndn-cxx/security/transform/base64-decode.hpp"
+#include "ndn-cxx/security/transform/bool-sink.hpp"
+#include "ndn-cxx/security/transform/buffer-source.hpp"
+#include "ndn-cxx/security/transform/public-key.hpp"
+#include "ndn-cxx/security/transform/signer-filter.hpp"
+#include "ndn-cxx/security/transform/stream-sink.hpp"
+#include "ndn-cxx/security/transform/verifier-filter.hpp"
#include "tests/boost-test.hpp"
@@ -144,7 +151,7 @@
checkPkcs8Encoding(ConstBufferPtr encoding, const std::string& password, ConstBufferPtr pkcs1)
{
PrivateKey sKey;
- sKey.loadPkcs8(encoding->data(), encoding->size(), password.c_str(), password.size());
+ sKey.loadPkcs8(encoding->data(), encoding->size(), password.data(), password.size());
OBufferStream os;
sKey.savePkcs1(os);
BOOST_CHECK_EQUAL_COLLECTIONS(pkcs1->begin(), pkcs1->end(),
@@ -163,7 +170,7 @@
{
T dataSet;
- const uint8_t* sKeyPkcs1Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.c_str());
+ const uint8_t* sKeyPkcs1Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data());
size_t sKeyPkcs1Base64Len = dataSet.privateKeyPkcs1.size();
OBufferStream os;
bufferSource(sKeyPkcs1Base64, sKeyPkcs1Base64Len) >> base64Decode() >> streamSink(os);
@@ -200,7 +207,7 @@
BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1, sKeyPkcs1 + sKeyPkcs1Len,
os3.buf()->begin(), os3.buf()->end());
- const uint8_t* sKeyPkcs8Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs8.c_str());
+ const uint8_t* sKeyPkcs8Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs8.data());
size_t sKeyPkcs8Base64Len = dataSet.privateKeyPkcs8.size();
OBufferStream os4;
bufferSource(sKeyPkcs8Base64, sKeyPkcs8Base64Len) >> base64Decode() >> streamSink(os4);
@@ -218,14 +225,14 @@
// load key in base64-encoded pkcs8 format
PrivateKey sKey5;
BOOST_CHECK_NO_THROW(sKey5.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len,
- password.c_str(), password.size()));
+ password.data(), password.size()));
PrivateKey sKey6;
BOOST_CHECK_NO_THROW(sKey6.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len, pwCallback));
std::stringstream ss7(dataSet.privateKeyPkcs8);
PrivateKey sKey7;
- BOOST_CHECK_NO_THROW(sKey7.loadPkcs8Base64(ss7, password.c_str(), password.size()));
+ BOOST_CHECK_NO_THROW(sKey7.loadPkcs8Base64(ss7, password.data(), password.size()));
std::stringstream ss8(dataSet.privateKeyPkcs8);
PrivateKey sKey8;
@@ -233,7 +240,7 @@
// load key in pkcs8 format
PrivateKey sKey9;
- BOOST_CHECK_NO_THROW(sKey9.loadPkcs8(sKeyPkcs8, sKeyPkcs8Len, password.c_str(), password.size()));
+ BOOST_CHECK_NO_THROW(sKey9.loadPkcs8(sKeyPkcs8, sKeyPkcs8Len, password.data(), password.size()));
PrivateKey sKey10;
BOOST_CHECK_NO_THROW(sKey10.loadPkcs8(sKeyPkcs8, sKeyPkcs8Len, pwCallback));
@@ -241,7 +248,7 @@
std::stringstream ss11;
ss11.write(reinterpret_cast<const char*>(sKeyPkcs8), sKeyPkcs8Len);
PrivateKey sKey11;
- BOOST_CHECK_NO_THROW(sKey11.loadPkcs8(ss11, password.c_str(), password.size()));
+ BOOST_CHECK_NO_THROW(sKey11.loadPkcs8(ss11, password.data(), password.size()));
std::stringstream ss12;
ss12.write(reinterpret_cast<const char*>(sKeyPkcs8), sKeyPkcs8Len);
@@ -250,12 +257,12 @@
// load key using wrong password, Error is expected
PrivateKey sKey13;
- BOOST_CHECK_THROW(sKey13.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len, wrongpw.c_str(), wrongpw.size()),
+ BOOST_CHECK_THROW(sKey13.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len, wrongpw.data(), wrongpw.size()),
PrivateKey::Error);
// save key in base64-encoded pkcs8 format
OBufferStream os14;
- BOOST_REQUIRE_NO_THROW(sKey.savePkcs8Base64(os14, password.c_str(), password.size()));
+ BOOST_REQUIRE_NO_THROW(sKey.savePkcs8Base64(os14, password.data(), password.size()));
checkPkcs8Base64Encoding(os14.buf(), password, sKeyPkcs1Buf);
OBufferStream os15;
@@ -264,7 +271,7 @@
// save key in pkcs8 format
OBufferStream os16;
- BOOST_REQUIRE_NO_THROW(sKey.savePkcs8(os16, password.c_str(), password.size()));
+ BOOST_REQUIRE_NO_THROW(sKey.savePkcs8(os16, password.data(), password.size()));
checkPkcs8Encoding(os16.buf(), password, sKeyPkcs1Buf);
OBufferStream os17;
@@ -276,7 +283,7 @@
{
T dataSet;
- const uint8_t* sKeyPkcs1Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.c_str());
+ const uint8_t* sKeyPkcs1Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data());
size_t sKeyPkcs1Base64Len = dataSet.privateKeyPkcs1.size();
PrivateKey sKey;
sKey.loadPkcs1Base64(sKeyPkcs1Base64, sKeyPkcs1Base64Len);
@@ -294,7 +301,7 @@
RsaKeyTestData dataSet;
PrivateKey sKey;
- sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.c_str()),
+ sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
dataSet.privateKeyPkcs1.size());
BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::RSA);
@@ -320,12 +327,12 @@
RsaKeyTestData dataSet;
PublicKey pKey;
- pKey.loadPkcs8Base64(reinterpret_cast<const uint8_t*>(dataSet.publicKeyPkcs8.c_str()),
+ pKey.loadPkcs8Base64(reinterpret_cast<const uint8_t*>(dataSet.publicKeyPkcs8.data()),
dataSet.publicKeyPkcs8.size());
BOOST_CHECK_EQUAL(pKey.getKeyType(), KeyType::RSA);
PrivateKey sKey;
- sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.c_str()),
+ sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
dataSet.privateKeyPkcs1.size());
BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::RSA);
@@ -337,57 +344,94 @@
decrypted->begin(), decrypted->end());
}
-BOOST_AUTO_TEST_CASE(UnsupportedEcDecryption)
+BOOST_AUTO_TEST_CASE(UnsupportedDecryption)
{
- EcKeyTestData dataSet;
-
- PrivateKey sKey;
- sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.c_str()),
- dataSet.privateKeyPkcs1.size());
- BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::EC);
-
OBufferStream os;
bufferSource("Y2lhbyFob2xhIWhlbGxvIQ==") >> base64Decode() >> streamSink(os);
- BOOST_CHECK_THROW(sKey.decrypt(os.buf()->data(), os.buf()->size()), PrivateKey::Error);
+ auto ecKey = generatePrivateKey(EcKeyParams());
+ BOOST_CHECK_THROW(ecKey->decrypt(os.buf()->data(), os.buf()->size()), PrivateKey::Error);
+
+ auto hmacKey = generatePrivateKey(HmacKeyParams());
+ BOOST_CHECK_THROW(hmacKey->decrypt(os.buf()->data(), os.buf()->size()), PrivateKey::Error);
}
-using KeyParams = boost::mpl::vector<RsaKeyParams, EcKeyParams>;
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(GenerateKey, T, KeyParams)
+struct RsaKeyGenParams
{
- unique_ptr<PrivateKey> sKey = generatePrivateKey(T());
- PublicKey pKey;
- ConstBufferPtr pKeyBits = sKey->derivePublicKey();
- pKey.loadPkcs8(pKeyBits->data(), pKeyBits->size());
+ using Params = RsaKeyParams;
+ using hasPublicKey = std::true_type;
+ using canSavePkcs1 = std::true_type;
+};
+
+struct EcKeyGenParams
+{
+ using Params = EcKeyParams;
+ using hasPublicKey = std::true_type;
+ using canSavePkcs1 = std::true_type;
+};
+
+struct HmacKeyGenParams
+{
+ using Params = HmacKeyParams;
+ using hasPublicKey = std::false_type;
+ using canSavePkcs1 = std::false_type;
+};
+
+using KeyGenParams = boost::mpl::vector<RsaKeyGenParams,
+ EcKeyGenParams,
+ HmacKeyGenParams>;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(GenerateKey, T, KeyGenParams)
+{
+ unique_ptr<PrivateKey> sKey = generatePrivateKey(typename T::Params());
+ BOOST_CHECK_NE(sKey->getKeyType(), KeyType::NONE);
+ BOOST_CHECK_GT(sKey->getKeySize(), 0);
const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
OBufferStream os;
BOOST_REQUIRE_NO_THROW(bufferSource(data, sizeof(data)) >>
signerFilter(DigestAlgorithm::SHA256, *sKey) >>
streamSink(os));
+ auto sig = os.buf();
- ConstBufferPtr sig = os.buf();
bool result = false;
- BOOST_REQUIRE_NO_THROW(bufferSource(data, sizeof(data)) >>
+ if (typename T::hasPublicKey()) {
+ auto pKeyBits = sKey->derivePublicKey();
+ PublicKey pKey;
+ pKey.loadPkcs8(pKeyBits->data(), pKeyBits->size());
+ BOOST_CHECK_NO_THROW(bufferSource(data, sizeof(data)) >>
verifierFilter(DigestAlgorithm::SHA256, pKey, sig->data(), sig->size()) >>
boolSink(result));
+ }
+ else {
+#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
+ BOOST_CHECK_THROW(sKey->derivePublicKey(), PrivateKey::Error);
+#endif
+ BOOST_CHECK_NO_THROW(bufferSource(data, sizeof(data)) >>
+ verifierFilter(DigestAlgorithm::SHA256, *sKey, sig->data(), sig->size()) >>
+ boolSink(result));
+ }
BOOST_CHECK(result);
- unique_ptr<PrivateKey> sKey2 = generatePrivateKey(T());
+ if (typename T::canSavePkcs1()) {
+ unique_ptr<PrivateKey> sKey2 = generatePrivateKey(typename T::Params());
- OBufferStream os1;
- sKey->savePkcs1(os1);
- ConstBufferPtr key1Pkcs1 = os1.buf();
+ OBufferStream os1;
+ sKey->savePkcs1(os1);
+ OBufferStream os2;
+ sKey2->savePkcs1(os2);
- OBufferStream os2;
- sKey2->savePkcs1(os2);
- ConstBufferPtr key2Pkcs1 = os2.buf();
-
- BOOST_CHECK(*key1Pkcs1 != *key2Pkcs1);
+ BOOST_CHECK(*os1.buf() != *os2.buf());
+ }
+ else {
+#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
+ OBufferStream os1;
+ BOOST_CHECK_THROW(sKey->savePkcs1(os1), PrivateKey::Error);
+#endif
+ }
}
-BOOST_AUTO_TEST_CASE(UnsupportedKeyType)
+BOOST_AUTO_TEST_CASE(GenerateKeyUnsupportedType)
{
BOOST_CHECK_THROW(generatePrivateKey(AesKeyParams()), std::invalid_argument);
}
diff --git a/tests/unit/security/transform/signer-filter.t.cpp b/tests/unit/security/transform/signer-filter.t.cpp
index aa6f6e3..4c75204 100644
--- a/tests/unit/security/transform/signer-filter.t.cpp
+++ b/tests/unit/security/transform/signer-filter.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -22,6 +22,7 @@
#include "ndn-cxx/security/transform/signer-filter.hpp"
#include "ndn-cxx/encoding/buffer-stream.hpp"
+#include "ndn-cxx/security/key-params.hpp"
#include "ndn-cxx/security/transform/base64-decode.hpp"
#include "ndn-cxx/security/transform/buffer-source.hpp"
#include "ndn-cxx/security/transform/private-key.hpp"
@@ -39,6 +40,8 @@
BOOST_AUTO_TEST_SUITE(Transform)
BOOST_AUTO_TEST_SUITE(TestSignerFilter)
+const uint8_t DATA[] = {0x01, 0x02, 0x03, 0x04};
+
BOOST_AUTO_TEST_CASE(Rsa)
{
const std::string publicKeyPkcs8 =
@@ -75,7 +78,6 @@
"cuHICmsCgYAtFJ1idqMoHxES3mlRpf2JxyQudP3SCm2WpGmqVzhRYInqeatY5sUd\n"
"lPLHm/p77RT7EyxQHTlwn8FJPuM/4ZH1rQd/vB+Y8qAtYJCexDMsbvLW+Js+VOvk\n"
"jweEC0nrcL31j9mF0vz5E6tfRu4hhJ6L4yfWs0gSejskeVB/w8QY4g==\n";
- const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
OBufferStream os1;
bufferSource(publicKeyPkcs8) >> base64Decode() >> streamSink(os1);
@@ -87,10 +89,10 @@
BOOST_CHECK_THROW(SignerFilter(DigestAlgorithm::NONE, sKey), Error);
OBufferStream os2;
- bufferSource(data, sizeof(data)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
+ bufferSource(DATA, sizeof(DATA)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
auto sig = os2.buf();
- BOOST_CHECK(verifySignature(data, sizeof(data), sig->data(), sig->size(), pubKey->data(), pubKey->size()));
+ BOOST_CHECK(verifySignature(DATA, sizeof(DATA), sig->data(), sig->size(), pubKey->data(), pubKey->size()));
}
BOOST_AUTO_TEST_CASE(Ecdsa)
@@ -112,7 +114,6 @@
"RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA\n"
"//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABGhuFibgwLdEJBDOLdvSg1Hc\n"
"5EJTDxq6ls5FoYLfThp8HOjuwGSz0qw8ocMqyku1y0V5peQ4rEPd0bwcpZd9svA=\n";
- const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
OBufferStream os1;
bufferSource(publicKeyPkcs8) >> base64Decode() >> streamSink(os1);
@@ -124,10 +125,34 @@
BOOST_CHECK_THROW(SignerFilter(DigestAlgorithm::NONE, sKey), Error);
OBufferStream os2;
- bufferSource(data, sizeof(data)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
+ bufferSource(DATA, sizeof(DATA)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
auto sig = os2.buf();
- BOOST_CHECK(verifySignature(data, sizeof(data), sig->data(), sig->size(), pubKey->data(), pubKey->size()));
+ BOOST_CHECK(verifySignature(DATA, sizeof(DATA), sig->data(), sig->size(), pubKey->data(), pubKey->size()));
+}
+
+BOOST_AUTO_TEST_CASE(Hmac)
+{
+ auto sKey = generatePrivateKey(HmacKeyParams());
+
+ BOOST_CHECK_THROW(SignerFilter(DigestAlgorithm::NONE, *sKey), Error);
+
+ OBufferStream os;
+ bufferSource(DATA, sizeof(DATA)) >> signerFilter(DigestAlgorithm::SHA256, *sKey) >> streamSink(os);
+ auto sig = os.buf();
+
+ BOOST_CHECK_EQUAL(sig->size(), 32);
+}
+
+BOOST_AUTO_TEST_CASE(HmacKeyTooShort)
+{
+ auto sKey = generatePrivateKey(HmacKeyParams(256));
+
+ OBufferStream os;
+ BOOST_CHECK_THROW(bufferSource(DATA, sizeof(DATA)) >>
+ signerFilter(DigestAlgorithm::SHA512, *sKey) >>
+ streamSink(os),
+ Error);
}
BOOST_AUTO_TEST_CASE(InvalidKey)
diff --git a/tests/unit/security/transform/verifier-filter.t.cpp b/tests/unit/security/transform/verifier-filter.t.cpp
index ef38276..8d733d3 100644
--- a/tests/unit/security/transform/verifier-filter.t.cpp
+++ b/tests/unit/security/transform/verifier-filter.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -22,6 +22,7 @@
#include "ndn-cxx/security/transform/verifier-filter.hpp"
#include "ndn-cxx/encoding/buffer-stream.hpp"
+#include "ndn-cxx/security/key-params.hpp"
#include "ndn-cxx/security/transform/base64-decode.hpp"
#include "ndn-cxx/security/transform/bool-sink.hpp"
#include "ndn-cxx/security/transform/buffer-source.hpp"
@@ -41,6 +42,8 @@
BOOST_AUTO_TEST_SUITE(Transform)
BOOST_AUTO_TEST_SUITE(TestVerifierFilter)
+const uint8_t DATA[] = {0x01, 0x02, 0x03, 0x04};
+
BOOST_AUTO_TEST_CASE(Rsa)
{
const std::string publicKeyPkcs8 =
@@ -78,7 +81,6 @@
"/YnHJC50/dIKbZakaapXOFFgiep5q1jmxR2U8seb+nvtFPsTLFAdOXCfwUk+4z/h\n"
"kfWtB3+8H5jyoC1gkJ7EMyxu8tb4mz5U6+SPB4QLSetwvfWP2YXS/PkTq19G7iGE\n"
"novjJ9azSBJ6OyR5UH/DxBji\n";
- const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
OBufferStream os1;
bufferSource(publicKeyPkcs8) >> base64Decode() >> streamSink(os1);
@@ -91,13 +93,14 @@
sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()), privateKeyPkcs1.size());
OBufferStream os2;
- bufferSource(data, sizeof(data)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
+ bufferSource(DATA, sizeof(DATA)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
auto sig = os2.buf();
BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::NONE, pKey, sig->data(), sig->size()), Error);
+ BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::SHA256, sKey, sig->data(), sig->size()), Error);
bool result = false;
- bufferSource(data, sizeof(data)) >>
+ bufferSource(DATA, sizeof(DATA)) >>
verifierFilter(DigestAlgorithm::SHA256, pKey, sig->data(), sig->size()) >>
boolSink(result);
@@ -123,7 +126,6 @@
"RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA\n"
"//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABGhuFibgwLdEJBDOLdvSg1Hc\n"
"5EJTDxq6ls5FoYLfThp8HOjuwGSz0qw8ocMqyku1y0V5peQ4rEPd0bwcpZd9svA=\n";
- const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
OBufferStream os1;
bufferSource(publicKeyPkcs8) >> base64Decode() >> streamSink(os1);
@@ -136,23 +138,44 @@
sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()), privateKeyPkcs1.size());
OBufferStream os2;
- bufferSource(data, sizeof(data)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
+ bufferSource(DATA, sizeof(DATA)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
auto sig = os2.buf();
BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::NONE, pKey, sig->data(), sig->size()), Error);
+ BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::SHA256, sKey, sig->data(), sig->size()), Error);
bool result = false;
- bufferSource(data, sizeof(data)) >>
+ bufferSource(DATA, sizeof(DATA)) >>
verifierFilter(DigestAlgorithm::SHA256, pKey, sig->data(), sig->size()) >>
boolSink(result);
BOOST_CHECK_EQUAL(result, true);
}
+BOOST_AUTO_TEST_CASE(Hmac)
+{
+ auto sKey = generatePrivateKey(HmacKeyParams());
+
+ OBufferStream os;
+ bufferSource(DATA, sizeof(DATA)) >> signerFilter(DigestAlgorithm::SHA256, *sKey) >> streamSink(os);
+ auto sig = os.buf();
+
+ BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::NONE, *sKey, sig->data(), sig->size()), Error);
+
+ bool result = false;
+ bufferSource(DATA, sizeof(DATA)) >>
+ verifierFilter(DigestAlgorithm::SHA256, *sKey, sig->data(), sig->size()) >>
+ boolSink(result);
+
+ BOOST_CHECK_EQUAL(result, true);
+}
+
BOOST_AUTO_TEST_CASE(InvalidKey)
{
- PublicKey pKey;
- BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::SHA256, pKey, nullptr, 0), Error);
+ PublicKey pubKey;
+ BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::SHA256, pubKey, nullptr, 0), Error);
+ PrivateKey privKey;
+ BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::SHA256, privKey, nullptr, 0), Error);
}
BOOST_AUTO_TEST_SUITE_END() // TestVerifierFilter