security: Add base64 and hex encoding/decoding support in transformation
Change-Id: I11d5c8921abcf04411aac38382dc285269f553ef
Refs: #3009
diff --git a/src/security/openssl.hpp b/src/security/detail/openssl.hpp
similarity index 75%
rename from src/security/openssl.hpp
rename to src/security/detail/openssl.hpp
index c753497..09a6f68 100644
--- a/src/security/openssl.hpp
+++ b/src/security/detail/openssl.hpp
@@ -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).
*
@@ -19,8 +19,8 @@
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
-#ifndef NDN_SECURITY_OPENSSL_HPP
-#define NDN_SECURITY_OPENSSL_HPP
+#ifndef NDN_SECURITY_DETAIL_OPENSSL_HPP
+#define NDN_SECURITY_DETAIL_OPENSSL_HPP
// suppress deprecation warnings in OSX >= 10.7
@@ -30,16 +30,16 @@
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif // __clang__
-#ifdef __GNUC__
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif // __GNUC__
+#endif // __APPLE__
-#endif
-
-
-#include <openssl/ssl.h>
-#include <openssl/sha.h>
+#include <openssl/rand.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
#include <openssl/rsa.h>
+#include <openssl/ec.h>
+#include <openssl/pem.h>
+#include <openssl/hmac.h>
+#include <openssl/x509.h>
-#endif // NDN_SECURITY_OPENSSL_HPP
+#endif // NDN_SECURITY_DETAIL_OPENSSL_HPP
diff --git a/src/security/transform.hpp b/src/security/transform.hpp
index b29f5c6..b9a960c 100644
--- a/src/security/transform.hpp
+++ b/src/security/transform.hpp
@@ -29,4 +29,9 @@
#include "transform/bool-sink.hpp"
#include "transform/stream-sink.hpp"
+#include "transform/hex-encode.hpp"
+#include "transform/hex-decode.hpp"
+#include "transform/base64-encode.hpp"
+#include "transform/base64-decode.hpp"
+
#endif // NDN_CXX_SECURITY_TRANSFORM_HPP
diff --git a/src/security/transform/base64-decode.cpp b/src/security/transform/base64-decode.cpp
new file mode 100644
index 0000000..7f3cf54
--- /dev/null
+++ b/src/security/transform/base64-decode.cpp
@@ -0,0 +1,135 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "base64-decode.hpp"
+#include "../../encoding/buffer.hpp"
+#include "../detail/openssl.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief The implementation class which contains the internal state of the filter
+ * which includes openssl specific structures.
+ */
+class Base64Decode::Impl
+{
+public:
+ Impl()
+ : m_base64(BIO_new(BIO_f_base64()))
+ , m_source(BIO_new(BIO_s_mem()))
+ {
+ // Input may not be written in a single time.
+ // Do not return EOF when source is empty unless explicitly requested
+ BIO_set_mem_eof_return(m_source, -1);
+
+ // connect base64 transform to the data source.
+ BIO_push(m_base64, m_source);
+ }
+
+ ~Impl()
+ {
+ BIO_free_all(m_source);
+ }
+
+public:
+ BIO* m_base64;
+ BIO* m_source; // BIO_f_base64 alone does not work without a source
+};
+
+static const size_t BUFFER_LENGTH = 1024;
+
+Base64Decode::Base64Decode(bool expectNewlineEvery64Bytes)
+ : m_impl(new Impl)
+{
+ if (!expectNewlineEvery64Bytes)
+ BIO_set_flags(m_impl->m_base64, BIO_FLAGS_BASE64_NO_NL);
+}
+
+void
+Base64Decode::preTransform()
+{
+ while (isOutputBufferEmpty()) {
+ fillOutputBuffer();
+ if (isOutputBufferEmpty()) // nothing to read from BIO, return
+ return;
+
+ flushOutputBuffer();
+ }
+}
+
+size_t
+Base64Decode::convert(const uint8_t* buf, size_t size)
+{
+ int wLen = BIO_write(m_impl->m_source, buf, size);
+
+ if (wLen <= 0) { // fail to write data
+ if (!BIO_should_retry(m_impl->m_source)) {
+ // we haven't written everything but some error happens, and we cannot retry
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to accept more input"));
+ }
+ return 0;
+ }
+ else { // update number of bytes written
+ return wLen;
+ }
+}
+
+void
+Base64Decode::finalize()
+{
+ BIO_set_mem_eof_return(m_impl->m_source, 0);
+
+ fillOutputBuffer();
+
+ while (!isOutputBufferEmpty()) {
+ flushOutputBuffer();
+ if (isOutputBufferEmpty())
+ fillOutputBuffer();
+ }
+}
+
+void
+Base64Decode::fillOutputBuffer()
+{
+ // OpenSSL base64 BIO cannot give us the number bytes of partial decoded result,
+ // so we just try to read a chunk.
+ auto buffer = make_unique<OBuffer>(BUFFER_LENGTH);
+ int rLen = BIO_read(m_impl->m_base64, &(*buffer)[0], buffer->size());
+ if (rLen <= 0)
+ return;
+
+ if (static_cast<size_t>(rLen) < buffer->size())
+ buffer->erase(buffer->begin() + rLen, buffer->end());
+
+ setOutputBuffer(std::move(buffer));
+}
+
+unique_ptr<Transform>
+base64Decode(bool expectNewlineEvery64Bytes)
+{
+ return make_unique<Base64Decode>(expectNewlineEvery64Bytes);
+}
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/src/security/transform/base64-decode.hpp b/src/security/transform/base64-decode.hpp
new file mode 100644
index 0000000..cfd5876
--- /dev/null
+++ b/src/security/transform/base64-decode.hpp
@@ -0,0 +1,89 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_CXX_SECURITY_TRANSFORM_BASE64_DECODE_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_BASE64_DECODE_HPP
+
+#include "transform-base.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief The module to perform Base64 decoding transformation.
+ */
+class Base64Decode : public Transform
+{
+public:
+ /**
+ * @brief Create a base64 decoding module
+ *
+ * @p expectNewlineEvery64Bytes if true, expect newline after every 64 bytes, otherwise expect
+ * all input to be in a single line. Output is undefined if input
+ * does not conform to the requirement.
+ */
+ explicit
+ Base64Decode(bool expectNewlineEvery64Bytes = true);
+
+private:
+
+ /**
+ * @brief Read partial transformation results into output buffer and write them into next module.
+ */
+ virtual void
+ preTransform() final;
+
+ /**
+ * @brief Decode data @p buf in base64 format
+ *
+ * @return number of bytes that have been accepted by the converter
+ */
+ virtual size_t
+ convert(const uint8_t* buf, size_t size) final;
+
+ /**
+ * @brief Finalize base64 decoding
+ *
+ * This method with read all decoding results from the converter and write them into next module.
+ */
+ virtual void
+ finalize() final;
+
+ /**
+ * @brief Try to fill partial decoding result into output buffer.
+ */
+ void
+ fillOutputBuffer();
+
+private:
+ class Impl;
+ unique_ptr<Impl> m_impl;
+};
+
+unique_ptr<Transform>
+base64Decode(bool expectNewlineEvery64Bytes = true);
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_BASE64_DECODE_HPP
diff --git a/src/security/transform/base64-encode.cpp b/src/security/transform/base64-encode.cpp
new file mode 100644
index 0000000..0a27bed
--- /dev/null
+++ b/src/security/transform/base64-encode.cpp
@@ -0,0 +1,135 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "base64-encode.hpp"
+#include "../../encoding/buffer.hpp"
+#include "../detail/openssl.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief The implementation class which contains the internal state of the filter
+ * which includes openssl specific structures.
+ */
+class Base64Encode::Impl
+{
+public:
+ Impl()
+ : m_base64(BIO_new(BIO_f_base64()))
+ , m_sink(BIO_new(BIO_s_mem()))
+ {
+ // connect base64 transform to the data sink.
+ BIO_push(m_base64, m_sink);
+ }
+
+ ~Impl()
+ {
+ BIO_free_all(m_sink);
+ }
+
+public:
+ BIO* m_base64;
+ BIO* m_sink; // BIO_f_base64 alone does not work without a sink
+};
+
+Base64Encode::Base64Encode(bool needBreak)
+ : m_impl(new Impl)
+{
+ if (!needBreak)
+ BIO_set_flags(m_impl->m_base64, BIO_FLAGS_BASE64_NO_NL);
+}
+
+void
+Base64Encode::preTransform()
+{
+ fillOutputBuffer();
+}
+
+size_t
+Base64Encode::convert(const uint8_t* data, size_t dataLen)
+{
+ if (dataLen == 0)
+ return 0;
+
+ int wLen = BIO_write(m_impl->m_base64, data, dataLen);
+
+ if (wLen <= 0) { // fail to write data
+ if (!BIO_should_retry(m_impl->m_base64)) {
+ // we haven't written everything but some error happens, and we cannot retry
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to accept more input"));
+ }
+ return 0;
+ }
+ else { // update number of bytes written
+ fillOutputBuffer();
+ return wLen;
+ }
+}
+
+void
+Base64Encode::finalize()
+{
+ if (BIO_flush(m_impl->m_base64) != 1)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to flush"));
+
+ while (!isConverterEmpty()) {
+ fillOutputBuffer();
+ while (!isOutputBufferEmpty()) {
+ flushOutputBuffer();
+ }
+ }
+}
+
+void
+Base64Encode::fillOutputBuffer()
+{
+ int nRead = BIO_pending(m_impl->m_sink);
+ if (nRead <= 0)
+ return;
+
+ // there is something to read from BIO
+ auto buffer = make_unique<OBuffer>(nRead);
+ int rLen = BIO_read(m_impl->m_sink, &(*buffer)[0], nRead);
+ if (rLen < 0)
+ return;
+
+ if (rLen < nRead)
+ buffer->erase(buffer->begin() + rLen, buffer->end());
+ setOutputBuffer(std::move(buffer));
+}
+
+bool
+Base64Encode::isConverterEmpty()
+{
+ return (BIO_pending(m_impl->m_sink) <= 0);
+}
+
+unique_ptr<Transform>
+base64Encode(bool needBreak)
+{
+ return make_unique<Base64Encode>(needBreak);
+}
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/src/security/transform/base64-encode.hpp b/src/security/transform/base64-encode.hpp
new file mode 100644
index 0000000..ac9c664
--- /dev/null
+++ b/src/security/transform/base64-encode.hpp
@@ -0,0 +1,91 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_CXX_SECURITY_TRANSFORM_BASE64_ENCODE_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_BASE64_ENCODE_HPP
+
+#include "transform-base.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief The module to perform Base64 encoding transformation.
+ */
+class Base64Encode : public Transform
+{
+public:
+ /**
+ * @brief Create a base64 encoding module
+ *
+ * @p needBreak if true, insert newline after every 64 bytes, otherwise no newline is inserted
+ */
+ explicit
+ Base64Encode(bool needBreak = true);
+
+private:
+ /**
+ * @brief Read partial transformation result (if exists) from BIO
+ */
+ virtual void
+ preTransform() final;
+
+ /**
+ * @brief Encode @data into base64 format.
+ * @return The number of input bytes that have been accepted by the converter.
+ */
+ virtual size_t
+ convert(const uint8_t* data, size_t dataLen) final;
+
+ /**
+ * @brief Finalize base64 encoding
+ *
+ * This method with read all encoding results from the converter and write them into next module.
+ */
+ virtual void
+ finalize() final;
+
+ /**
+ * @brief Fill output buffer with the transformation result from BIO.
+ */
+ void
+ fillOutputBuffer();
+
+ /**
+ * @return true if converter does not have partial result.
+ */
+ bool
+ isConverterEmpty();
+
+private:
+ class Impl;
+ unique_ptr<Impl> m_impl;
+};
+
+unique_ptr<Transform>
+base64Encode(bool needBreak = true);
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_BASE64_ENCODE_HPP
diff --git a/src/security/transform/hex-decode.cpp b/src/security/transform/hex-decode.cpp
new file mode 100644
index 0000000..aa82461
--- /dev/null
+++ b/src/security/transform/hex-decode.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "hex-decode.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+static const int8_t C2H[256] = { // hex decoding pad.
+// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32-47
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48-63
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64-79
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80-95
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96-111
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 112-127
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 240-255
+};
+
+HexDecode::HexDecode()
+ : m_hasOddByte(false)
+ , m_oddByte(0)
+{
+}
+
+size_t
+HexDecode::convert(const uint8_t* hex, size_t hexLen)
+{
+ if (hexLen == 0)
+ return 0;
+
+ setOutputBuffer(toBytes(hex, hexLen));
+
+ size_t totalDecodedLen = hexLen + (m_hasOddByte ? 1 : 0);
+ if (totalDecodedLen % 2 == 1) {
+ m_oddByte = hex[hexLen - 1];
+ m_hasOddByte = true;
+ }
+ else
+ m_hasOddByte = false;
+
+ return hexLen;
+}
+
+void
+HexDecode::finalize()
+{
+ if (m_hasOddByte)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Incomplete input"));
+}
+
+unique_ptr<Transform::OBuffer>
+HexDecode::toBytes(const uint8_t* hex, size_t hexLen)
+{
+ size_t bufferSize = (hexLen + (m_hasOddByte ? 1 : 0)) >> 1;
+ auto buffer = make_unique<OBuffer>(bufferSize);
+ uint8_t* buf = &buffer->front();
+
+ if (m_hasOddByte) {
+ if (C2H[hex[0]] < 0 || C2H[m_oddByte] < 0)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Wrong input byte"));
+
+ buf[0] = (C2H[m_oddByte] << 4) + (C2H[hex[0]]);
+ buf += 1;
+ hex += 1;
+ hexLen -= 1;
+ }
+
+ while (hexLen > 1) {
+ if (C2H[hex[0]] < 0 || C2H[hex[1]] < 0)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Wrong input byte"));
+
+ buf[0] = (C2H[hex[0]] << 4) + (C2H[hex[1]]);
+ buf += 1;
+ hex += 2;
+ hexLen -= 2;
+ }
+
+ return buffer;
+}
+
+unique_ptr<Transform>
+hexDecode()
+{
+ return make_unique<HexDecode>();
+}
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/src/security/transform/hex-decode.hpp b/src/security/transform/hex-decode.hpp
new file mode 100644
index 0000000..77d477d
--- /dev/null
+++ b/src/security/transform/hex-decode.hpp
@@ -0,0 +1,80 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_CXX_SECURITY_TRANSFORM_HEX_DECODE_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_HEX_DECODE_HPP
+
+#include "transform-base.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief The module to perform hexadecimal decoding transformation.
+ *
+ * For example, if the input is a string "012345", the output will be
+ * a byte stream: 0x01, 0x23, 0x45.
+ *
+ * If the total length of input is not even (2n + 1), the module will throw Error.
+ */
+class HexDecode : public Transform
+{
+public:
+ /**
+ * @brief Create a hex decoding module
+ */
+ HexDecode();
+
+private:
+ /**
+ * @brief Decode data @p buf, and write the result into output buffer directly.
+ *
+ * @return number of input bytes that are accepted
+ */
+ virtual size_t
+ convert(const uint8_t* buf, size_t size) final;
+
+ /**
+ * @throws Error if pending byte exists.
+ */
+ virtual void
+ finalize() final;
+
+ /**
+ * @return results of decoding concatenation of @p oddByte and @p hex.
+ */
+ unique_ptr<Transform::OBuffer>
+ toBytes(const uint8_t* hex, size_t hexLen);
+
+private:
+ bool m_hasOddByte;
+ uint8_t m_oddByte;
+};
+
+unique_ptr<Transform>
+hexDecode();
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_HEX_DECODE_HPP
diff --git a/src/security/transform/hex-encode.cpp b/src/security/transform/hex-encode.cpp
new file mode 100644
index 0000000..6d54f0e
--- /dev/null
+++ b/src/security/transform/hex-encode.cpp
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "hex-encode.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+static const char H2CL[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+};
+
+static const char H2CU[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+HexEncode::HexEncode(bool useUpperCase)
+ : m_useUpperCase(useUpperCase)
+{
+}
+
+size_t
+HexEncode::convert(const uint8_t* data, size_t dataLen)
+{
+ setOutputBuffer(toHex(data, dataLen));
+ return dataLen;
+}
+
+unique_ptr<Transform::OBuffer>
+HexEncode::toHex(const uint8_t* data, size_t dataLen)
+{
+ const char* encodePad = (m_useUpperCase) ? H2CU : H2CL;
+
+ auto encoded = make_unique<OBuffer>(dataLen * 2);
+ uint8_t* buf = &encoded->front();
+ for (size_t i = 0; i < dataLen; i++) {
+ buf[0] = encodePad[((data[i] >> 4) & 0x0F)];
+ buf++;
+ buf[0] = encodePad[(data[i] & 0x0F)];
+ buf++;
+ }
+ return encoded;
+}
+
+
+
+unique_ptr<Transform>
+hexEncode(bool useUpperCase)
+{
+ return make_unique<HexEncode>(useUpperCase);
+}
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/src/security/transform/hex-encode.hpp b/src/security/transform/hex-encode.hpp
new file mode 100644
index 0000000..95fc6e8
--- /dev/null
+++ b/src/security/transform/hex-encode.hpp
@@ -0,0 +1,74 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_CXX_SECURITY_TRANSFORM_HEX_ENCODE_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_HEX_ENCODE_HPP
+
+#include "transform-base.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief The module to perform hexadecimal encoding transformation.
+ *
+ * For example, if the input is a byte stream 0x01, 0x23, 0x45,
+ * the output will be a string "012345".
+ */
+class HexEncode : public Transform
+{
+public:
+ /**
+ * @brief Create a hex encoding module
+ *
+ * @param useUpperCase if true, use upper case letters, otherwise lower case
+ */
+ explicit
+ HexEncode(bool useUpperCase = false);
+
+private:
+ /**
+ * @brief Encode @p data, and write the result into next module directly.
+ *
+ * @return The number of input bytes that have been accepted by the converter.
+ */
+ virtual size_t
+ convert(const uint8_t* data, size_t dataLen) final;
+
+ /**
+ * @return results of encoding @p data
+ */
+ unique_ptr<Transform::OBuffer>
+ toHex(const uint8_t* data, size_t dataLen);
+
+private:
+ bool m_useUpperCase;
+};
+
+unique_ptr<Transform>
+hexEncode(bool useUpperCase = false);
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_HEX_ENCODE_HPP
diff --git a/src/security/transform/transform-base.cpp b/src/security/transform/transform-base.cpp
index 85df6b9..936e0ae 100644
--- a/src/security/transform/transform-base.cpp
+++ b/src/security/transform/transform-base.cpp
@@ -74,6 +74,76 @@
}
}
+Transform::Transform()
+ : m_oBuffer(nullptr)
+ , m_outputOffset(0)
+{
+}
+
+void
+Transform::flushOutputBuffer()
+{
+ if (isOutputBufferEmpty())
+ return;
+
+ size_t nWritten = m_next->write(&(*m_oBuffer)[m_outputOffset],
+ m_oBuffer->size() - m_outputOffset);
+ m_outputOffset += nWritten;
+}
+
+void
+Transform::setOutputBuffer(unique_ptr<OBuffer> buffer)
+{
+ BOOST_ASSERT(isOutputBufferEmpty());
+ m_oBuffer = std::move(buffer);
+ m_outputOffset = 0;
+}
+
+bool
+Transform::isOutputBufferEmpty() const
+{
+ return (m_oBuffer == nullptr || m_oBuffer->size() == m_outputOffset);
+}
+
+size_t
+Transform::doWrite(const uint8_t* data, size_t dataLen)
+{
+ flushOutputBuffer();
+ if (!isOutputBufferEmpty())
+ return 0;
+
+ preTransform();
+ flushOutputBuffer();
+ if (!isOutputBufferEmpty())
+ return 0;
+
+ size_t nConverted = convert(data, dataLen);
+
+ flushOutputBuffer();
+
+ return nConverted;
+}
+
+void
+Transform::doEnd()
+{
+ finalize();
+ m_next->end();
+}
+
+void
+Transform::preTransform()
+{
+}
+
+void
+Transform::finalize()
+{
+ while (!isOutputBufferEmpty()) {
+ flushOutputBuffer();
+ }
+}
+
Source::Source()
: m_nModules(1) // source per se is counted as one module
{
diff --git a/src/security/transform/transform-base.hpp b/src/security/transform/transform-base.hpp
index 7f64145..5e3a72b 100644
--- a/src/security/transform/transform-base.hpp
+++ b/src/security/transform/transform-base.hpp
@@ -23,6 +23,7 @@
#define NDN_CXX_SECURITY_TRANSFORM_BASE_HPP
#include "../../common.hpp"
+#include <vector>
namespace ndn {
namespace security {
@@ -178,6 +179,80 @@
public Downstream,
noncopyable
{
+protected:
+ typedef std::vector<uint8_t> OBuffer;
+
+ Transform();
+
+ /**
+ * @brief Read the content from output buffer and write it into next module.
+ */
+ void
+ flushOutputBuffer();
+
+ /**
+ * @brief Set output buffer to @p buffer
+ */
+ void
+ setOutputBuffer(unique_ptr<OBuffer> buffer);
+
+ /**
+ * @brief Check if output buffer is empty
+ */
+ bool
+ isOutputBufferEmpty() const;
+
+private:
+
+ /**
+ * @brief Abstraction of data processing in an intermediate module
+ */
+ virtual size_t
+ doWrite(const uint8_t* data, size_t dataLen) final;
+
+ /**
+ * @brief Finalize transformation in this module
+ *
+ * This method will not return until all transformation result is written into next module
+ */
+ virtual void
+ doEnd() final;
+
+ /**
+ * @brief Process before transformation.
+ *
+ * @pre output buffer is empty.
+ *
+ * This method is invoked before every convert(...) invocation.
+ *
+ * This implementation does nothing. A subclass can override this method to perform
+ * specific pre-transformation procedure, e.g., read partial transformation results into
+ * output buffer.
+ */
+ virtual void
+ preTransform();
+
+ /**
+ * @brief Convert input @p data.
+ *
+ * @return The number of input bytes that have been accepted by the converter.
+ */
+ virtual size_t
+ convert(const uint8_t* data, size_t dataLen) = 0;
+
+ /**
+ * @brief Finalize the transformation.
+ *
+ * This implementation only flushes content in output buffer into next module.
+ * A subclass can override this method to perform specific finalization procedure, i.e.,
+ * finalize the transformation and flush the result into next module.
+ */
+ virtual void
+ finalize();
+
+private:
+ unique_ptr<OBuffer> m_oBuffer;
+ size_t m_outputOffset;
};
/**
diff --git a/tests/unit-tests/security/transform.t.cpp b/tests/unit-tests/security/transform.t.cpp
index 6999df4..ea2fa0f 100644
--- a/tests/unit-tests/security/transform.t.cpp
+++ b/tests/unit-tests/security/transform.t.cpp
@@ -46,6 +46,18 @@
transform::StreamSink* streamSink = nullptr;
BOOST_CHECK(streamSink == nullptr);
+
+ transform::HexEncode* hexEncode = nullptr;
+ BOOST_CHECK(hexEncode == nullptr);
+
+ transform::HexDecode* hexDecode = nullptr;
+ BOOST_CHECK(hexDecode == nullptr);
+
+ transform::Base64Encode* base64Encode = nullptr;
+ BOOST_CHECK(base64Encode == nullptr);
+
+ transform::Base64Decode* base64Decode = nullptr;
+ BOOST_CHECK(base64Decode == nullptr);
}
BOOST_AUTO_TEST_SUITE_END() // TestTransform
diff --git a/tests/unit-tests/security/transform/base64-decode.t.cpp b/tests/unit-tests/security/transform/base64-decode.t.cpp
new file mode 100644
index 0000000..05c9e56
--- /dev/null
+++ b/tests/unit-tests/security/transform/base64-decode.t.cpp
@@ -0,0 +1,183 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/base64-decode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "encoding/buffer-stream.hpp"
+#include <iostream>
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestBase64Decode)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ std::string in =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=\n";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ OBufferStream os;
+ bufferSource(in) >> base64Decode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(NoNewLine)
+{
+ std::string in =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=";
+
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ OBufferStream os;
+ bufferSource(in) >> base64Decode(false) >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(StepByStep)
+{
+ std::string in =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ const uint8_t* input = reinterpret_cast<const uint8_t*>(in.data());
+ OBufferStream os;
+ StepSource source;
+ source >> base64Decode() >> streamSink(os);
+ source.write(input, 65); // complete line with "\n"
+ source.write(input + 65, 64); // complete line without "\n"
+ source.write(input + 129, 1); // single "\n"
+ source.write(input + 130, 35); // front of a line
+ source.write(input + 165, 30); // end of a line with "\n"
+ source.write(input + 195, 25); // front of a line
+ source.write(input + 220, 20); // middle of a line
+ source.write(input + 240, 19); // end of a line without "\n"
+ source.write(input + 259, 101); // "\n" plus one and half line
+ source.write(input + 360, 65); // end of a line plus front of another line
+ source.write(input + 425, 95); // remaining
+ source.end();
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(EmptyInput)
+{
+ OBufferStream os;
+ StepSource source;
+ source >> base64Decode() >> streamSink(os);
+ source.end();
+ BOOST_CHECK_EQUAL(os.buf()->size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBase64Decode
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/transform/base64-encode.t.cpp b/tests/unit-tests/security/transform/base64-encode.t.cpp
new file mode 100644
index 0000000..8d383ab
--- /dev/null
+++ b/tests/unit-tests/security/transform/base64-encode.t.cpp
@@ -0,0 +1,179 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/base64-encode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "encoding/buffer-stream.hpp"
+#include <iostream>
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestBase64Encode)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=\n";
+
+ OBufferStream os;
+ bufferSource(in, sizeof(in)) >> base64Encode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(NoNewLine)
+{
+ uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=";
+
+ OBufferStream os;
+ BufferSource(in, sizeof(in)) >> base64Encode(false) >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(StepByStep)
+{
+ uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
+ "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n";
+
+ OBufferStream os;
+ StepSource source;
+ source >> base64Encode() >> streamSink(os);
+ source.write(in, 64); // complete chunk
+ source.write(in + 64, 32); // first half of a chunk
+ source.write(in + 96, 32); // second half of a chunk
+ source.write(in + 128, 24); // front of a chunk
+ source.write(in + 152, 20); // middle of a chunk
+ source.write(in + 172, 20); // end of a chunk
+ source.write(in + 192, 63); // odd number of bytes
+ source.write(in + 255, 85); // one and half chunk
+ source.write(in + 340, 44); // remaining part
+ source.end();
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(EmptyInput)
+{
+ OBufferStream os;
+ StepSource source;
+ source >> base64Encode() >> streamSink(os);
+ source.end();
+ BOOST_CHECK_EQUAL(os.buf()->size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBase64Encode
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/transform/hex-decode.t.cpp b/tests/unit-tests/security/transform/hex-decode.t.cpp
new file mode 100644
index 0000000..4a9c78e
--- /dev/null
+++ b/tests/unit-tests/security/transform/hex-decode.t.cpp
@@ -0,0 +1,295 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/hex-decode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "encoding/buffer-stream.hpp"
+#include <iostream>
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestHexDecode)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ std::string in =
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ OBufferStream os;
+ bufferSource(in) >> hexDecode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(UpperCase)
+{
+ std::string in =
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ OBufferStream os;
+ bufferSource(in) >> hexDecode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(MixCase)
+{
+ std::string in =
+ "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
+ "000102030405060708090A0B0C0D0E0F"
+ "101112131415161718191A1B1C1D1E1F"
+ "202122232425262728292A2B2C2D2E2F"
+ "303132333435363738393A3B3C3D3E3F"
+ "404142434445464748494A4B4C4D4E4F"
+ "505152535455565758595A5B5C5D5E5F"
+ "606162636465666768696A6B6C6D6E6F"
+ "707172737475767778797A7B7C7D7E7F"
+ "808182838485868788898A8B8C8D8E8F"
+ "909192939495969798999A9B9C9D9E9F"
+ "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"
+ "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"
+ "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"
+ "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"
+ "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"
+ "aaabacadaeafaAaBaCaD"
+ "babbbcbdbebfbAbBbCbD"
+ "cacbcccdcecfcAcBcCcD"
+ "dadbdcdddedfdAdBdCdD"
+ "eaebecedeeefeAeBeCeD"
+ "fafbfcfdfefffAfBfCfD"
+ "AaAbAcAdAeAfAAABACAD"
+ "BaBbBcBdBeBfBABBBCBD"
+ "CaCbCcCdCeCfCACBCCCD"
+ "DaDbDcDdDeDfDADBDCDD";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+ 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+ 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+ 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xAA, 0xAB, 0xAC, 0xAD,
+ 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBA, 0xBB, 0xBC, 0xBD,
+ 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xDA, 0xDB, 0xDC, 0xDD,
+ 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xEA, 0xEB, 0xEC, 0xED,
+ 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFA, 0xFB, 0xFC, 0xFD,
+ 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xAA, 0xAB, 0xAC, 0xAD,
+ 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBA, 0xBB, 0xBC, 0xBD,
+ 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xDA, 0xDB, 0xDC, 0xDD
+ };
+
+ OBufferStream os;
+ bufferSource(in) >> hexDecode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+
+BOOST_AUTO_TEST_CASE(StepByStep)
+{
+ std::string in =
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
+
+ uint8_t out[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ const uint8_t* input = reinterpret_cast<const uint8_t*>(in.data());
+ OBufferStream os;
+ StepSource source;
+ source >> hexDecode() >> streamSink(os);
+ source.write(input, 128); // complete chunk
+ source.write(input + 128, 64); // first half of a chunk
+ source.write(input + 192, 64); // second half of a chunk
+ source.write(input + 256, 127); // odd number of byets
+ source.write(input + 383, 192); // one and half chunk
+ source.write(input + 575, 193); // remaining part
+ source.end();
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(OddByte)
+{
+ std::string in1 = "0001020304050";
+
+ OBufferStream os1;
+ BOOST_REQUIRE_THROW(bufferSource(in1) >> hexDecode() >> streamSink(os1), transform::Error);
+
+ std::string in2 = "0001020304xy";
+
+ OBufferStream os2;
+ BOOST_REQUIRE_THROW(bufferSource(in2) >> hexDecode() >> streamSink(os2), transform::Error);
+}
+
+BOOST_AUTO_TEST_CASE(EmptyInput)
+{
+ OBufferStream os;
+ StepSource source;
+ source >> hexDecode() >> streamSink(os);
+ source.end();
+ BOOST_CHECK_EQUAL(os.buf()->size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestHexDecode
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/transform/hex-encode.t.cpp b/tests/unit-tests/security/transform/hex-encode.t.cpp
new file mode 100644
index 0000000..5edcaaa
--- /dev/null
+++ b/tests/unit-tests/security/transform/hex-encode.t.cpp
@@ -0,0 +1,185 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/transform/hex-encode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "encoding/buffer-stream.hpp"
+#include <iostream>
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestHexEncode)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ uint8_t in[128] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
+
+ OBufferStream os;
+ bufferSource(in, sizeof(in)) >> hexEncode() >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(UpperCase)
+{
+ uint8_t in[128] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+ "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F";
+
+ OBufferStream os;
+ bufferSource(in, sizeof(in)) >> hexEncode(true) >> streamSink(os);
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(StepByStep)
+{
+ uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::string out =
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
+ "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
+
+ OBufferStream os;
+ StepSource source;
+ source >> hexEncode() >> streamSink(os);
+ source.write(in, 64); // complete chunk
+ source.write(in + 64, 32); // first half of a chunk
+ source.write(in + 96, 32); // second half of a chunk
+ source.write(in + 128, 20); // front of a chunk
+ source.write(in + 148, 20); // middle of a chunk
+ source.write(in + 168, 24); // end of a chunk
+ source.write(in + 192, 63); // odd number of bytes
+ source.write(in + 255, 85); // one and half chunk
+ source.write(in + 340, 44); // remaining part
+ source.end();
+
+ ConstBufferPtr buf1 = os.buf();
+ BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
+}
+
+BOOST_AUTO_TEST_CASE(EmptyInput)
+{
+ OBufferStream os;
+ StepSource source;
+ source >> hexEncode() >> streamSink(os);
+ source.end();
+ BOOST_CHECK_EQUAL(os.buf()->size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestHexEncode
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn