util: backport C++20 std::span and use it in various APIs

Implementation taken from span-lite by Martin Moene,
commit 337af6e23f6d3264136c16565546244da23159ba

Change-Id: Icfd0ba6841cbf6ef7870c31c881df940da9faf7e
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e988485..d9f98d8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -51,7 +51,7 @@
         include:
           - xcode: '12.5'
             os: macos-11
-          - xcode: '13'
+          - xcode: '13.2'
             os: macos-11
     runs-on: ${{ matrix.os }}
     env:
diff --git a/COPYING.md b/COPYING.md
index b72dd74..199c0c3 100644
--- a/COPYING.md
+++ b/COPYING.md
@@ -15,6 +15,9 @@
 - scope-lite by Martin Moene is licensed under the
   [Boost Software License 1.0](https://github.com/martinmoene/scope-lite/blob/master/LICENSE.txt)
 
+- span-lite by Martin Moene is licensed under the
+  [Boost Software License 1.0](https://github.com/martinmoene/span-lite/blob/master/LICENSE.txt)
+
 - variant-lite by Martin Moene is licensed under the
   [Boost Software License 1.0](https://github.com/martinmoene/variant-lite/blob/master/LICENSE.txt)
 
diff --git a/ndn-cxx/data.cpp b/ndn-cxx/data.cpp
index 52ae571..db0b745 100644
--- a/ndn-cxx/data.cpp
+++ b/ndn-cxx/data.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -318,8 +318,9 @@
 
   wireEncode();
   auto lastSignedIt = std::prev(m_wire.find(tlv::SignatureValue));
-  bufs.emplace_back(m_wire.value(),
-                    std::distance(m_wire.value_begin(), lastSignedIt->end()));
+  // Note: we assume that both iterators point to the same underlying buffer
+  bufs.emplace_back(m_wire.value_begin(), lastSignedIt->end());
+
   return bufs;
 }
 
diff --git a/ndn-cxx/detail/nonstd/span-lite.hpp b/ndn-cxx/detail/nonstd/span-lite.hpp
new file mode 100644
index 0000000..5e611ce
--- /dev/null
+++ b/ndn-cxx/detail/nonstd/span-lite.hpp
@@ -0,0 +1,1884 @@
+//
+// span for C++98 and later.
+// Based on http://wg21.link/p0122r7
+// For more information see https://github.com/martinmoene/span-lite
+//
+// Copyright 2018-2021 Martin Moene
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NONSTD_SPAN_HPP_INCLUDED
+#define NONSTD_SPAN_HPP_INCLUDED
+
+#define span_lite_MAJOR  0
+#define span_lite_MINOR  10
+#define span_lite_PATCH  3
+
+#define span_lite_VERSION  span_STRINGIFY(span_lite_MAJOR) "." span_STRINGIFY(span_lite_MINOR) "." span_STRINGIFY(span_lite_PATCH)
+
+#define span_STRINGIFY(  x )  span_STRINGIFY_( x )
+#define span_STRINGIFY_( x )  #x
+
+// span configuration:
+
+#define span_SPAN_DEFAULT  0
+#define span_SPAN_NONSTD   1
+#define span_SPAN_STD      2
+
+// tweak header support:
+
+#ifdef __has_include
+# if __has_include(<nonstd/span.tweak.hpp>)
+#  include <nonstd/span.tweak.hpp>
+# endif
+#define span_HAVE_TWEAK_HEADER  1
+#else
+#define span_HAVE_TWEAK_HEADER  0
+//# pragma message("span.hpp: Note: Tweak header not supported.")
+#endif
+
+// span selection and configuration:
+
+#define span_HAVE( feature )  ( span_HAVE_##feature )
+
+#ifndef  span_CONFIG_SELECT_SPAN
+# define span_CONFIG_SELECT_SPAN  ( span_HAVE_STD_SPAN ? span_SPAN_STD : span_SPAN_NONSTD )
+#endif
+
+#ifndef  span_CONFIG_EXTENT_TYPE
+# define span_CONFIG_EXTENT_TYPE  std::size_t
+#endif
+
+#ifndef  span_CONFIG_SIZE_TYPE
+# define span_CONFIG_SIZE_TYPE  std::size_t
+#endif
+
+#ifdef span_CONFIG_INDEX_TYPE
+# error `span_CONFIG_INDEX_TYPE` is deprecated since v0.7.0; it is replaced by `span_CONFIG_SIZE_TYPE`.
+#endif
+
+// span configuration (features):
+
+#ifndef  span_FEATURE_WITH_CONTAINER
+#ifdef   span_FEATURE_WITH_CONTAINER_TO_STD
+# define span_FEATURE_WITH_CONTAINER  span_IN_STD( span_FEATURE_WITH_CONTAINER_TO_STD )
+#else
+# define span_FEATURE_WITH_CONTAINER  0
+# define span_FEATURE_WITH_CONTAINER_TO_STD  0
+#endif
+#endif
+
+#ifndef  span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE
+# define span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE  0
+#endif
+
+#ifndef  span_FEATURE_MEMBER_AT
+# define span_FEATURE_MEMBER_AT  0
+#endif
+
+#ifndef  span_FEATURE_MEMBER_BACK_FRONT
+# define span_FEATURE_MEMBER_BACK_FRONT  1
+#endif
+
+#ifndef  span_FEATURE_MEMBER_CALL_OPERATOR
+# define span_FEATURE_MEMBER_CALL_OPERATOR  0
+#endif
+
+#ifndef  span_FEATURE_MEMBER_SWAP
+# define span_FEATURE_MEMBER_SWAP  0
+#endif
+
+#ifndef  span_FEATURE_NON_MEMBER_FIRST_LAST_SUB
+# define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB  0
+#elif    span_FEATURE_NON_MEMBER_FIRST_LAST_SUB
+# define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN       1
+# define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER  1
+#endif
+
+#ifndef  span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN
+# define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN  0
+#endif
+
+#ifndef  span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER
+# define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER  0
+#endif
+
+#ifndef  span_FEATURE_COMPARISON
+# define span_FEATURE_COMPARISON  0  // Note: C++20 does not provide comparison
+#endif
+
+#ifndef  span_FEATURE_SAME
+# define span_FEATURE_SAME  0
+#endif
+
+#if span_FEATURE_SAME && !span_FEATURE_COMPARISON
+# error `span_FEATURE_SAME` requires `span_FEATURE_COMPARISON`
+#endif
+
+#ifndef  span_FEATURE_MAKE_SPAN
+#ifdef   span_FEATURE_MAKE_SPAN_TO_STD
+# define span_FEATURE_MAKE_SPAN  span_IN_STD( span_FEATURE_MAKE_SPAN_TO_STD )
+#else
+# define span_FEATURE_MAKE_SPAN  0
+# define span_FEATURE_MAKE_SPAN_TO_STD  0
+#endif
+#endif
+
+#ifndef  span_FEATURE_BYTE_SPAN
+# define span_FEATURE_BYTE_SPAN  0
+#endif
+
+// Control presence of exception handling (try and auto discover):
+
+#ifndef span_CONFIG_NO_EXCEPTIONS
+# if defined(_MSC_VER)
+#  include <cstddef>    // for _HAS_EXCEPTIONS
+# endif
+# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
+#  define span_CONFIG_NO_EXCEPTIONS  0
+# else
+#  define span_CONFIG_NO_EXCEPTIONS  1
+#  undef  span_CONFIG_CONTRACT_VIOLATION_THROWS
+#  undef  span_CONFIG_CONTRACT_VIOLATION_TERMINATES
+#  define span_CONFIG_CONTRACT_VIOLATION_THROWS  0
+#  define span_CONFIG_CONTRACT_VIOLATION_TERMINATES  1
+# endif
+#endif
+
+// Control pre- and postcondition violation behaviour:
+
+#if    defined( span_CONFIG_CONTRACT_LEVEL_ON )
+# define        span_CONFIG_CONTRACT_LEVEL_MASK  0x11
+#elif  defined( span_CONFIG_CONTRACT_LEVEL_OFF )
+# define        span_CONFIG_CONTRACT_LEVEL_MASK  0x00
+#elif  defined( span_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY )
+# define        span_CONFIG_CONTRACT_LEVEL_MASK  0x01
+#elif  defined( span_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY )
+# define        span_CONFIG_CONTRACT_LEVEL_MASK  0x10
+#else
+# define        span_CONFIG_CONTRACT_LEVEL_MASK  0x11
+#endif
+
+#if    defined( span_CONFIG_CONTRACT_VIOLATION_THROWS )
+# define        span_CONFIG_CONTRACT_VIOLATION_THROWS_V  span_CONFIG_CONTRACT_VIOLATION_THROWS
+#else
+# define        span_CONFIG_CONTRACT_VIOLATION_THROWS_V  0
+#endif
+
+#if    defined( span_CONFIG_CONTRACT_VIOLATION_THROWS     ) && span_CONFIG_CONTRACT_VIOLATION_THROWS && \
+       defined( span_CONFIG_CONTRACT_VIOLATION_TERMINATES ) && span_CONFIG_CONTRACT_VIOLATION_TERMINATES
+# error Please define none or one of span_CONFIG_CONTRACT_VIOLATION_THROWS and span_CONFIG_CONTRACT_VIOLATION_TERMINATES to 1, but not both.
+#endif
+
+// C++ language version detection (C++20 is speculative):
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
+
+#ifndef   span_CPLUSPLUS
+# if defined(_MSVC_LANG ) && !defined(__clang__)
+#  define span_CPLUSPLUS  (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+#  define span_CPLUSPLUS  __cplusplus
+# endif
+#endif
+
+#define span_CPP98_OR_GREATER  ( span_CPLUSPLUS >= 199711L )
+#define span_CPP11_OR_GREATER  ( span_CPLUSPLUS >= 201103L )
+#define span_CPP14_OR_GREATER  ( span_CPLUSPLUS >= 201402L )
+#define span_CPP17_OR_GREATER  ( span_CPLUSPLUS >= 201703L )
+#define span_CPP20_OR_GREATER  ( span_CPLUSPLUS >= 202000L )
+
+// C++ language version (represent 98 as 3):
+
+#define span_CPLUSPLUS_V  ( span_CPLUSPLUS / 100 - (span_CPLUSPLUS > 200000 ? 2000 : 1994) )
+
+#define span_IN_STD( v )  ( ((v) == 98 ? 3 : (v)) >= span_CPLUSPLUS_V )
+
+#define span_CONFIG(         feature )  ( span_CONFIG_##feature )
+#define span_FEATURE(        feature )  ( span_FEATURE_##feature )
+#define span_FEATURE_TO_STD( feature )  ( span_IN_STD( span_FEATURE( feature##_TO_STD ) ) )
+
+// Use C++20 std::span if available and requested:
+
+#if span_CPP20_OR_GREATER && defined(__has_include )
+# if __has_include( <span> )
+#  define span_HAVE_STD_SPAN  1
+# else
+#  define span_HAVE_STD_SPAN  0
+# endif
+#else
+# define  span_HAVE_STD_SPAN  0
+#endif
+
+#define  span_USES_STD_SPAN  ( (span_CONFIG_SELECT_SPAN == span_SPAN_STD) || ((span_CONFIG_SELECT_SPAN == span_SPAN_DEFAULT) && span_HAVE_STD_SPAN) )
+
+//
+// Use C++20 std::span:
+//
+
+#if span_USES_STD_SPAN
+
+#include <span>
+
+namespace nonstd {
+
+using std::span;
+
+// Note: C++20 does not provide comparison
+// using std::operator==;
+// using std::operator!=;
+// using std::operator<;
+// using std::operator<=;
+// using std::operator>;
+// using std::operator>=;
+}  // namespace nonstd
+
+#else  // span_USES_STD_SPAN
+
+#include <algorithm>
+
+// Compiler versions:
+//
+// MSVC++  6.0  _MSC_VER == 1200  span_COMPILER_MSVC_VERSION ==  60  (Visual Studio 6.0)
+// MSVC++  7.0  _MSC_VER == 1300  span_COMPILER_MSVC_VERSION ==  70  (Visual Studio .NET 2002)
+// MSVC++  7.1  _MSC_VER == 1310  span_COMPILER_MSVC_VERSION ==  71  (Visual Studio .NET 2003)
+// MSVC++  8.0  _MSC_VER == 1400  span_COMPILER_MSVC_VERSION ==  80  (Visual Studio 2005)
+// MSVC++  9.0  _MSC_VER == 1500  span_COMPILER_MSVC_VERSION ==  90  (Visual Studio 2008)
+// MSVC++ 10.0  _MSC_VER == 1600  span_COMPILER_MSVC_VERSION == 100  (Visual Studio 2010)
+// MSVC++ 11.0  _MSC_VER == 1700  span_COMPILER_MSVC_VERSION == 110  (Visual Studio 2012)
+// MSVC++ 12.0  _MSC_VER == 1800  span_COMPILER_MSVC_VERSION == 120  (Visual Studio 2013)
+// MSVC++ 14.0  _MSC_VER == 1900  span_COMPILER_MSVC_VERSION == 140  (Visual Studio 2015)
+// MSVC++ 14.1  _MSC_VER >= 1910  span_COMPILER_MSVC_VERSION == 141  (Visual Studio 2017)
+// MSVC++ 14.2  _MSC_VER >= 1920  span_COMPILER_MSVC_VERSION == 142  (Visual Studio 2019)
+
+#if defined(_MSC_VER ) && !defined(__clang__)
+# define span_COMPILER_MSVC_VER      (_MSC_VER )
+# define span_COMPILER_MSVC_VERSION  (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
+#else
+# define span_COMPILER_MSVC_VER      0
+# define span_COMPILER_MSVC_VERSION  0
+#endif
+
+#define span_COMPILER_VERSION( major, minor, patch )  ( 10 * ( 10 * (major) + (minor) ) + (patch) )
+
+#if defined(__clang__)
+# define span_COMPILER_CLANG_VERSION  span_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#else
+# define span_COMPILER_CLANG_VERSION  0
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__)
+# define span_COMPILER_GNUC_VERSION  span_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#else
+# define span_COMPILER_GNUC_VERSION  0
+#endif
+
+// half-open range [lo..hi):
+#define span_BETWEEN( v, lo, hi )  ( (lo) <= (v) && (v) < (hi) )
+
+// Compiler warning suppression:
+
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wundef"
+# pragma clang diagnostic ignored "-Wmismatched-tags"
+# define span_RESTORE_WARNINGS()   _Pragma( "clang diagnostic pop" )
+
+#elif defined __GNUC__
+# pragma GCC   diagnostic push
+# pragma GCC   diagnostic ignored "-Wundef"
+# define span_RESTORE_WARNINGS()   _Pragma( "GCC diagnostic pop" )
+
+#elif span_COMPILER_MSVC_VER >= 1900
+# define span_DISABLE_MSVC_WARNINGS(codes)  __pragma(warning(push))  __pragma(warning(disable: codes))
+# define span_RESTORE_WARNINGS()            __pragma(warning(pop ))
+
+// Suppress the following MSVC GSL warnings:
+// - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept'
+// - C26440, gsl::f.6 : function 'function' can be declared 'noexcept'
+// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
+//                      use brace initialization, gsl::narrow_cast or gsl::narrow
+// - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same
+// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
+// - C26490: gsl::t.1 : don't use reinterpret_cast
+
+span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 )
+
+#else
+# define span_RESTORE_WARNINGS()  /*empty*/
+#endif
+
+// Presence of language and library features:
+
+#ifdef _HAS_CPP0X
+# define span_HAS_CPP0X  _HAS_CPP0X
+#else
+# define span_HAS_CPP0X  0
+#endif
+
+#define span_CPP11_80   (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1400)
+#define span_CPP11_90   (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1500)
+#define span_CPP11_100  (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1600)
+#define span_CPP11_110  (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1700)
+#define span_CPP11_120  (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1800)
+#define span_CPP11_140  (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1900)
+
+#define span_CPP14_000  (span_CPP14_OR_GREATER)
+#define span_CPP14_120  (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1800)
+#define span_CPP14_140  (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1900)
+
+#define span_CPP17_000  (span_CPP17_OR_GREATER)
+
+// Presence of C++11 language features:
+
+#define span_HAVE_ALIAS_TEMPLATE            span_CPP11_140
+#define span_HAVE_AUTO                      span_CPP11_100
+#define span_HAVE_CONSTEXPR_11              span_CPP11_140
+#define span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG  span_CPP11_120
+#define span_HAVE_EXPLICIT_CONVERSION       span_CPP11_140
+#define span_HAVE_INITIALIZER_LIST          span_CPP11_120
+#define span_HAVE_IS_DEFAULT                span_CPP11_140
+#define span_HAVE_IS_DELETE                 span_CPP11_140
+#define span_HAVE_NOEXCEPT                  span_CPP11_140
+#define span_HAVE_NULLPTR                   span_CPP11_100
+#define span_HAVE_STATIC_ASSERT             span_CPP11_100
+
+// Presence of C++14 language features:
+
+#define span_HAVE_CONSTEXPR_14              span_CPP14_000
+
+// Presence of C++17 language features:
+
+#define span_HAVE_DEPRECATED                span_CPP17_000
+#define span_HAVE_NODISCARD                 span_CPP17_000
+#define span_HAVE_NORETURN                  span_CPP17_000
+
+// MSVC: template parameter deduction guides since Visual Studio 2017 v15.7
+
+#if defined(__cpp_deduction_guides)
+# define span_HAVE_DEDUCTION_GUIDES         1
+#else
+# define span_HAVE_DEDUCTION_GUIDES         (span_CPP17_OR_GREATER && ! span_BETWEEN( span_COMPILER_MSVC_VER, 1, 1913 ))
+#endif
+
+// Presence of C++ library features:
+
+#define span_HAVE_ADDRESSOF                 span_CPP17_000
+#define span_HAVE_ARRAY                     span_CPP11_110
+#define span_HAVE_BYTE                      span_CPP17_000
+#define span_HAVE_CONDITIONAL               span_CPP11_120
+#define span_HAVE_CONTAINER_DATA_METHOD    (span_CPP11_140 || ( span_COMPILER_MSVC_VER >= 1500 && span_HAS_CPP0X ))
+#define span_HAVE_DATA                      span_CPP17_000
+#define span_HAVE_LONGLONG                  span_CPP11_80
+#define span_HAVE_REMOVE_CONST              span_CPP11_110
+#define span_HAVE_SNPRINTF                  span_CPP11_140
+#define span_HAVE_STRUCT_BINDING            span_CPP11_120
+#define span_HAVE_TYPE_TRAITS               span_CPP11_90
+
+// Presence of byte-lite:
+
+#ifdef NONSTD_BYTE_LITE_HPP
+# define span_HAVE_NONSTD_BYTE  1
+#else
+# define span_HAVE_NONSTD_BYTE  0
+#endif
+
+// C++ feature usage:
+
+#if span_HAVE_ADDRESSOF
+# define span_ADDRESSOF(x)  std::addressof(x)
+#else
+# define span_ADDRESSOF(x)  (&x)
+#endif
+
+#if span_HAVE_CONSTEXPR_11
+# define span_constexpr constexpr
+#else
+# define span_constexpr /*span_constexpr*/
+#endif
+
+#if span_HAVE_CONSTEXPR_14
+# define span_constexpr14 constexpr
+#else
+# define span_constexpr14 /*span_constexpr*/
+#endif
+
+#if span_HAVE_EXPLICIT_CONVERSION
+# define span_explicit explicit
+#else
+# define span_explicit /*explicit*/
+#endif
+
+#if span_HAVE_IS_DELETE
+# define span_is_delete = delete
+#else
+# define span_is_delete
+#endif
+
+#if span_HAVE_IS_DELETE
+# define span_is_delete_access public
+#else
+# define span_is_delete_access private
+#endif
+
+#if span_HAVE_NOEXCEPT && ! span_CONFIG_CONTRACT_VIOLATION_THROWS_V
+# define span_noexcept noexcept
+#else
+# define span_noexcept /*noexcept*/
+#endif
+
+#if span_HAVE_NULLPTR
+# define span_nullptr nullptr
+#else
+# define span_nullptr NULL
+#endif
+
+#if span_HAVE_DEPRECATED
+# define span_deprecated(msg) [[deprecated(msg)]]
+#else
+# define span_deprecated(msg) /*[[deprecated]]*/
+#endif
+
+#if span_HAVE_NODISCARD
+# define span_nodiscard [[nodiscard]]
+#else
+# define span_nodiscard /*[[nodiscard]]*/
+#endif
+
+#if span_HAVE_NORETURN
+# define span_noreturn [[noreturn]]
+#else
+# define span_noreturn /*[[noreturn]]*/
+#endif
+
+// Other features:
+
+#define span_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR  span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+#define span_HAVE_ITERATOR_CTOR                    span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+
+// Additional includes:
+
+#if span_HAVE( ADDRESSOF )
+# include <memory>
+#endif
+
+#if span_HAVE( ARRAY )
+# include <array>
+#endif
+
+#if span_HAVE( BYTE )
+# include <cstddef>
+#endif
+
+#if span_HAVE( DATA )
+# include <iterator> // for std::data(), std::size()
+#endif
+
+#if span_HAVE( TYPE_TRAITS )
+# include <type_traits>
+#endif
+
+#if ! span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+# include <vector>
+#endif
+
+#if span_FEATURE( MEMBER_AT ) > 1
+# include <cstdio>
+#endif
+
+#if ! span_CONFIG( NO_EXCEPTIONS )
+# include <stdexcept>
+#endif
+
+// Contract violation
+
+#define span_ELIDE_CONTRACT_EXPECTS  ( 0 == ( span_CONFIG_CONTRACT_LEVEL_MASK & 0x01 ) )
+#define span_ELIDE_CONTRACT_ENSURES  ( 0 == ( span_CONFIG_CONTRACT_LEVEL_MASK & 0x10 ) )
+
+#if span_ELIDE_CONTRACT_EXPECTS
+# define span_constexpr_exp    span_constexpr
+# define span_EXPECTS( cond )  /* Expect elided */
+#else
+# define span_constexpr_exp    span_constexpr14
+# define span_EXPECTS( cond )  span_CONTRACT_CHECK( "Precondition", cond )
+#endif
+
+#if span_ELIDE_CONTRACT_ENSURES
+# define span_constexpr_ens    span_constexpr
+# define span_ENSURES( cond )  /* Ensures elided */
+#else
+# define span_constexpr_ens    span_constexpr14
+# define span_ENSURES( cond )  span_CONTRACT_CHECK( "Postcondition", cond )
+#endif
+
+#define span_CONTRACT_CHECK( type, cond ) \
+    cond ? static_cast< void >( 0 ) \
+         : nonstd::span_lite::detail::report_contract_violation( span_LOCATION( __FILE__, __LINE__ ) ": " type " violation." )
+
+#ifdef __GNUG__
+# define span_LOCATION( file, line )  file ":" span_STRINGIFY( line )
+#else
+# define span_LOCATION( file, line )  file "(" span_STRINGIFY( line ) ")"
+#endif
+
+// Method enabling
+
+#if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+
+#define span_REQUIRES_0(VA) \
+    template< bool B = (VA), typename std::enable_if<B, int>::type = 0 >
+
+# if span_BETWEEN( span_COMPILER_MSVC_VERSION, 1, 140 )
+// VS 2013 and earlier seem to have trouble with SFINAE for default non-type arguments
+# define span_REQUIRES_T(VA) \
+    , typename = typename std::enable_if< ( VA ), nonstd::span_lite::detail::enabler >::type
+# else
+# define span_REQUIRES_T(VA) \
+    , typename std::enable_if< (VA), int >::type = 0
+# endif
+
+#define span_REQUIRES_R(R, VA) \
+    typename std::enable_if< (VA), R>::type
+
+#define span_REQUIRES_A(VA) \
+    , typename std::enable_if< (VA), void*>::type = nullptr
+
+#else
+
+# define span_REQUIRES_0(VA)    /*empty*/
+# define span_REQUIRES_T(VA)    /*empty*/
+# define span_REQUIRES_R(R, VA) R
+# define span_REQUIRES_A(VA)    /*empty*/
+
+#endif
+
+namespace nonstd {
+namespace span_lite {
+
+// [views.constants], constants
+
+typedef span_CONFIG_EXTENT_TYPE extent_t;
+typedef span_CONFIG_SIZE_TYPE   size_t;
+
+span_constexpr const extent_t dynamic_extent = static_cast<extent_t>( -1 );
+
+template< class T, extent_t Extent = dynamic_extent >
+class span;
+
+// Tag to select span constructor taking a container (prevent ms-gsl warning C26426):
+
+struct with_container_t { span_constexpr with_container_t() span_noexcept {} };
+const  span_constexpr   with_container_t with_container;
+
+// C++11 emulation:
+
+namespace std11 {
+
+#if span_HAVE( REMOVE_CONST )
+
+using std::remove_cv;
+using std::remove_const;
+using std::remove_volatile;
+
+#else
+
+template< class T > struct remove_const            { typedef T type; };
+template< class T > struct remove_const< T const > { typedef T type; };
+
+template< class T > struct remove_volatile               { typedef T type; };
+template< class T > struct remove_volatile< T volatile > { typedef T type; };
+
+template< class T >
+struct remove_cv
+{
+    typedef typename std11::remove_volatile< typename std11::remove_const< T >::type >::type type;
+};
+
+#endif  // span_HAVE( REMOVE_CONST )
+
+#if span_HAVE( TYPE_TRAITS )
+
+using std::is_same;
+using std::is_signed;
+using std::integral_constant;
+using std::true_type;
+using std::false_type;
+using std::remove_reference;
+
+#else
+
+template< class T, T v > struct integral_constant { enum { value = v }; };
+typedef integral_constant< bool, true  > true_type;
+typedef integral_constant< bool, false > false_type;
+
+template< class T, class U > struct is_same : false_type{};
+template< class T          > struct is_same<T, T> : true_type{};
+
+template< typename T >  struct is_signed : false_type {};
+template<> struct is_signed<signed char> : true_type {};
+template<> struct is_signed<signed int > : true_type {};
+template<> struct is_signed<signed long> : true_type {};
+
+#endif
+
+} // namespace std11
+
+// C++17 emulation:
+
+namespace std17 {
+
+template< bool v > struct bool_constant : std11::integral_constant<bool, v>{};
+
+#if span_CPP11_120
+
+template< class...>
+using void_t = void;
+
+#endif
+
+#if span_HAVE( DATA )
+
+using std::data;
+using std::size;
+
+#elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+template< typename T, std::size_t N >
+inline span_constexpr auto size( const T(&)[N] ) span_noexcept -> size_t
+{
+    return N;
+}
+
+template< typename C >
+inline span_constexpr auto size( C const & cont ) -> decltype( cont.size() )
+{
+    return cont.size();
+}
+
+template< typename T, std::size_t N >
+inline span_constexpr auto data( T(&arr)[N] ) span_noexcept -> T*
+{
+    return &arr[0];
+}
+
+template< typename C >
+inline span_constexpr auto data( C & cont ) -> decltype( cont.data() )
+{
+    return cont.data();
+}
+
+template< typename C >
+inline span_constexpr auto data( C const & cont ) -> decltype( cont.data() )
+{
+    return cont.data();
+}
+
+template< typename E >
+inline span_constexpr auto data( std::initializer_list<E> il ) span_noexcept -> E const *
+{
+    return il.begin();
+}
+
+#endif // span_HAVE( DATA )
+
+#if span_HAVE( BYTE )
+using std::byte;
+#elif span_HAVE( NONSTD_BYTE )
+using nonstd::byte;
+#endif
+
+} // namespace std17
+
+// C++20 emulation:
+
+namespace std20 {
+
+#if span_HAVE( DEDUCTION_GUIDES )
+template< class T >
+using iter_reference_t = decltype( *std::declval<T&>() );
+#endif
+
+} // namespace std20
+
+// Implementation details:
+
+namespace detail {
+
+/*enum*/ struct enabler{};
+
+template< typename T >
+span_constexpr bool is_positive( T x )
+{
+    return std11::is_signed<T>::value ? x >= 0 : true;
+}
+
+#if span_HAVE( TYPE_TRAITS )
+
+template< class Q >
+struct is_span_oracle : std::false_type{};
+
+template< class T, span_CONFIG_EXTENT_TYPE Extent >
+struct is_span_oracle< span<T, Extent> > : std::true_type{};
+
+template< class Q >
+struct is_span : is_span_oracle< typename std::remove_cv<Q>::type >{};
+
+template< class Q >
+struct is_std_array_oracle : std::false_type{};
+
+#if span_HAVE( ARRAY )
+
+template< class T, std::size_t Extent >
+struct is_std_array_oracle< std::array<T, Extent> > : std::true_type{};
+
+#endif
+
+template< class Q >
+struct is_std_array : is_std_array_oracle< typename std::remove_cv<Q>::type >{};
+
+template< class Q >
+struct is_array : std::false_type {};
+
+template< class T >
+struct is_array<T[]> : std::true_type {};
+
+template< class T, std::size_t N >
+struct is_array<T[N]> : std::true_type {};
+
+#if span_CPP11_140 && ! span_BETWEEN( span_COMPILER_GNUC_VERSION, 1, 500 )
+
+template< class, class = void >
+struct has_size_and_data : std::false_type{};
+
+template< class C >
+struct has_size_and_data
+<
+    C, std17::void_t<
+        decltype( std17::size(std::declval<C>()) ),
+        decltype( std17::data(std::declval<C>()) ) >
+> : std::true_type{};
+
+template< class, class, class = void >
+struct is_compatible_element : std::false_type {};
+
+template< class C, class E >
+struct is_compatible_element
+<
+    C, E, std17::void_t<
+        decltype( std17::data(std::declval<C>()) ) >
+> : std::is_convertible< typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[], E(*)[] >{};
+
+template< class C >
+struct is_container : std17::bool_constant
+<
+    ! is_span< C >::value
+    && ! is_array< C >::value
+    && ! is_std_array< C >::value
+    &&   has_size_and_data< C >::value
+>{};
+
+template< class C, class E >
+struct is_compatible_container : std17::bool_constant
+<
+    is_container<C>::value
+    && is_compatible_element<C,E>::value
+>{};
+
+#else // span_CPP11_140
+
+template<
+    class C, class E
+        span_REQUIRES_T((
+            ! is_span< C >::value
+            && ! is_array< C >::value
+            && ! is_std_array< C >::value
+            && ( std::is_convertible< typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[], E(*)[] >::value)
+        //  &&   has_size_and_data< C >::value
+        ))
+        , class = decltype( std17::size(std::declval<C>()) )
+        , class = decltype( std17::data(std::declval<C>()) )
+>
+struct is_compatible_container : std::true_type{};
+
+#endif // span_CPP11_140
+
+#endif // span_HAVE( TYPE_TRAITS )
+
+#if ! span_CONFIG( NO_EXCEPTIONS )
+#if   span_FEATURE( MEMBER_AT ) > 1
+
+// format index and size:
+
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wlong-long"
+#elif defined __GNUC__
+# pragma GCC   diagnostic ignored "-Wformat=ll"
+# pragma GCC   diagnostic ignored "-Wlong-long"
+#endif
+
+span_noreturn inline void throw_out_of_range( size_t idx, size_t size )
+{
+    const char fmt[] = "span::at(): index '%lli' is out of range [0..%lli)";
+    char buffer[ 2 * 20 + sizeof fmt ];
+    sprintf( buffer, fmt, static_cast<long long>(idx), static_cast<long long>(size) );
+
+    throw std::out_of_range( buffer );
+}
+
+#else // MEMBER_AT
+
+span_noreturn inline void throw_out_of_range( size_t /*idx*/, size_t /*size*/ )
+{
+    throw std::out_of_range( "span::at(): index outside span" );
+}
+#endif  // MEMBER_AT
+#endif  // NO_EXCEPTIONS
+
+#if span_CONFIG( CONTRACT_VIOLATION_THROWS_V )
+
+struct contract_violation : std::logic_error
+{
+    explicit contract_violation( char const * const message )
+        : std::logic_error( message )
+    {}
+};
+
+inline void report_contract_violation( char const * msg )
+{
+    throw contract_violation( msg );
+}
+
+#else // span_CONFIG( CONTRACT_VIOLATION_THROWS_V )
+
+span_noreturn inline void report_contract_violation( char const * /*msg*/ ) span_noexcept
+{
+    std::terminate();
+}
+
+#endif // span_CONFIG( CONTRACT_VIOLATION_THROWS_V )
+
+}  // namespace detail
+
+// Prevent signed-unsigned mismatch:
+
+#define span_sizeof(T)  static_cast<extent_t>( sizeof(T) )
+
+template< class T >
+inline span_constexpr size_t to_size( T size )
+{
+    return static_cast<size_t>( size );
+}
+
+//
+// [views.span] - A view over a contiguous, single-dimension sequence of objects
+//
+template< class T, extent_t Extent /*= dynamic_extent*/ >
+class span
+{
+public:
+    // constants and types
+
+    typedef T element_type;
+    typedef typename std11::remove_cv< T >::type value_type;
+
+    typedef T &       reference;
+    typedef T *       pointer;
+    typedef T const * const_pointer;
+    typedef T const & const_reference;
+
+    typedef size_t    size_type;
+    typedef extent_t  extent_type;
+
+    typedef pointer        iterator;
+    typedef const_pointer  const_iterator;
+
+    typedef std::ptrdiff_t difference_type;
+
+    typedef std::reverse_iterator< iterator >       reverse_iterator;
+    typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
+
+//    static constexpr extent_type extent = Extent;
+    enum { extent = Extent };
+
+    // 26.7.3.2 Constructors, copy, and assignment [span.cons]
+
+    span_REQUIRES_0(
+        ( Extent == 0 ) ||
+        ( Extent == dynamic_extent )
+    )
+    span_constexpr span() span_noexcept
+        : data_( span_nullptr )
+        , size_( 0 )
+    {
+        // span_EXPECTS( data() == span_nullptr );
+        // span_EXPECTS( size() == 0 );
+    }
+
+#if span_HAVE( ITERATOR_CTOR )
+    // Didn't yet succeed in combining the next two constructors:
+
+    span_constexpr_exp span( std::nullptr_t, size_type count )
+        : data_( span_nullptr )
+        , size_( count )
+    {
+        span_EXPECTS( data_ == span_nullptr && count == 0 );
+    }
+
+    template< typename It
+        span_REQUIRES_T((
+            std::is_convertible<decltype(*std::declval<It&>()), element_type &>::value
+        ))
+    >
+    span_constexpr_exp span( It first, size_type count )
+        : data_( to_address( first ) )
+        , size_( count )
+    {
+        span_EXPECTS(
+            ( data_ == span_nullptr && count == 0 ) ||
+            ( data_ != span_nullptr && detail::is_positive( count ) )
+        );
+    }
+#else
+    span_constexpr_exp span( pointer ptr, size_type count )
+        : data_( ptr )
+        , size_( count )
+    {
+        span_EXPECTS(
+            ( ptr == span_nullptr && count == 0 ) ||
+            ( ptr != span_nullptr && detail::is_positive( count ) )
+        );
+    }
+#endif
+
+#if span_HAVE( ITERATOR_CTOR )
+    template< typename It, typename End
+        span_REQUIRES_T((
+            std::is_convertible<decltype(&*std::declval<It&>()), element_type *>::value
+            && ! std::is_convertible<End, std::size_t>::value
+        ))
+     >
+    span_constexpr_exp span( It first, End last )
+        : data_( to_address( first ) )
+        , size_( to_size( last - first ) )
+    {
+        span_EXPECTS(
+             last - first >= 0
+        );
+    }
+#else
+    span_constexpr_exp span( pointer first, pointer last )
+        : data_( first )
+        , size_( to_size( last - first ) )
+    {
+        span_EXPECTS(
+            last - first >= 0
+        );
+    }
+#endif
+
+    template< std::size_t N
+        span_REQUIRES_T((
+            (Extent == dynamic_extent || Extent == static_cast<extent_t>(N))
+            && std::is_convertible< value_type(*)[], element_type(*)[] >::value
+        ))
+    >
+    span_constexpr span( element_type ( &arr )[ N ] ) span_noexcept
+        : data_( span_ADDRESSOF( arr[0] ) )
+        , size_( N  )
+    {}
+
+#if span_HAVE( ARRAY )
+
+    template< std::size_t N
+        span_REQUIRES_T((
+            (Extent == dynamic_extent || Extent == static_cast<extent_t>(N))
+            && std::is_convertible< value_type(*)[], element_type(*)[] >::value
+        ))
+    >
+# if span_FEATURE( CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE )
+        span_constexpr span( std::array< element_type, N > & arr ) span_noexcept
+# else
+        span_constexpr span( std::array< value_type, N > & arr ) span_noexcept
+# endif
+        : data_( arr.data() )
+        , size_( to_size( arr.size() ) )
+    {}
+
+    template< std::size_t N
+# if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+        span_REQUIRES_T((
+            (Extent == dynamic_extent || Extent == static_cast<extent_t>(N))
+            && std::is_convertible< value_type(*)[], element_type(*)[] >::value
+        ))
+# endif
+    >
+    span_constexpr span( std::array< value_type, N> const & arr ) span_noexcept
+        : data_( arr.data() )
+        , size_( to_size( arr.size() ) )
+    {}
+
+#endif // span_HAVE( ARRAY )
+
+#if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+    template< class Container
+        span_REQUIRES_T((
+            detail::is_compatible_container< Container, element_type >::value
+        ))
+    >
+    span_constexpr span( Container & cont )
+        : data_( std17::data( cont ) )
+        , size_( to_size( std17::size( cont ) ) )
+    {}
+
+    template< class Container
+        span_REQUIRES_T((
+            std::is_const< element_type >::value
+            && detail::is_compatible_container< Container, element_type >::value
+        ))
+    >
+    span_constexpr span( Container const & cont )
+        : data_( std17::data( cont ) )
+        , size_( to_size( std17::size( cont ) ) )
+    {}
+
+#endif // span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+#if span_FEATURE( WITH_CONTAINER )
+
+    template< class Container >
+    span_constexpr span( with_container_t, Container & cont )
+        : data_( cont.size() == 0 ? span_nullptr : span_ADDRESSOF( cont[0] ) )
+        , size_( to_size( cont.size() ) )
+    {}
+
+    template< class Container >
+    span_constexpr span( with_container_t, Container const & cont )
+        : data_( cont.size() == 0 ? span_nullptr : const_cast<pointer>( span_ADDRESSOF( cont[0] ) ) )
+        , size_( to_size( cont.size() ) )
+    {}
+#endif
+
+#if span_HAVE( IS_DEFAULT )
+    span_constexpr span( span const & other ) span_noexcept = default;
+
+    ~span() span_noexcept = default;
+
+    span_constexpr14 span & operator=( span const & other ) span_noexcept = default;
+#else
+    span_constexpr span( span const & other ) span_noexcept
+        : data_( other.data_ )
+        , size_( other.size_ )
+    {}
+
+    ~span() span_noexcept
+    {}
+
+    span_constexpr14 span & operator=( span const & other ) span_noexcept
+    {
+        data_ = other.data_;
+        size_ = other.size_;
+
+        return *this;
+    }
+#endif
+
+    template< class OtherElementType, extent_type OtherExtent
+        span_REQUIRES_T((
+            (Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent)
+            && std::is_convertible<OtherElementType(*)[], element_type(*)[]>::value
+        ))
+    >
+    span_constexpr_exp span( span<OtherElementType, OtherExtent> const & other ) span_noexcept
+        : data_( other.data() )
+        , size_( other.size() )
+    {
+        span_EXPECTS( OtherExtent == dynamic_extent || other.size() == to_size(OtherExtent) );
+    }
+
+    // 26.7.3.3 Subviews [span.sub]
+
+    template< extent_type Count >
+    span_constexpr_exp span< element_type, Count >
+    first() const
+    {
+        span_EXPECTS( detail::is_positive( Count ) && Count <= size() );
+
+        return span< element_type, Count >( data(), Count );
+    }
+
+    template< extent_type Count >
+    span_constexpr_exp span< element_type, Count >
+    last() const
+    {
+        span_EXPECTS( detail::is_positive( Count ) && Count <= size() );
+
+        return span< element_type, Count >( data() + (size() - Count), Count );
+    }
+
+#if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+    template< size_type Offset, extent_type Count = dynamic_extent >
+#else
+    template< size_type Offset, extent_type Count /*= dynamic_extent*/ >
+#endif
+    span_constexpr_exp span< element_type, Count >
+    subspan() const
+    {
+        span_EXPECTS(
+            ( detail::is_positive( Offset ) && Offset <= size() ) &&
+            ( Count == dynamic_extent || (detail::is_positive( Count ) && Count + Offset <= size()) )
+        );
+
+        return span< element_type, Count >(
+            data() + Offset, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : size() - Offset) );
+    }
+
+    span_constexpr_exp span< element_type, dynamic_extent >
+    first( size_type count ) const
+    {
+        span_EXPECTS( detail::is_positive( count ) && count <= size() );
+
+        return span< element_type, dynamic_extent >( data(), count );
+    }
+
+    span_constexpr_exp span< element_type, dynamic_extent >
+    last( size_type count ) const
+    {
+        span_EXPECTS( detail::is_positive( count ) && count <= size() );
+
+        return span< element_type, dynamic_extent >( data() + ( size() - count ), count );
+    }
+
+    span_constexpr_exp span< element_type, dynamic_extent >
+    subspan( size_type offset, size_type count = static_cast<size_type>(dynamic_extent) ) const
+    {
+        span_EXPECTS(
+            ( ( detail::is_positive( offset ) && offset <= size() ) ) &&
+            ( count == static_cast<size_type>(dynamic_extent) || ( detail::is_positive( count ) && offset + count <= size() ) )
+        );
+
+        return span< element_type, dynamic_extent >(
+            data() + offset, count == static_cast<size_type>(dynamic_extent) ? size() - offset : count );
+    }
+
+    // 26.7.3.4 Observers [span.obs]
+
+    span_constexpr size_type size() const span_noexcept
+    {
+        return size_;
+    }
+
+    span_constexpr std::ptrdiff_t ssize() const span_noexcept
+    {
+        return static_cast<std::ptrdiff_t>( size_ );
+    }
+
+    span_constexpr size_type size_bytes() const span_noexcept
+    {
+        return size() * to_size( sizeof( element_type ) );
+    }
+
+    span_nodiscard span_constexpr bool empty() const span_noexcept
+    {
+        return size() == 0;
+    }
+
+    // 26.7.3.5 Element access [span.elem]
+
+    span_constexpr_exp reference operator[]( size_type idx ) const
+    {
+        span_EXPECTS( detail::is_positive( idx ) && idx < size() );
+
+        return *( data() + idx );
+    }
+
+#if span_FEATURE( MEMBER_CALL_OPERATOR )
+    span_deprecated("replace operator() with operator[]")
+
+    span_constexpr_exp reference operator()( size_type idx ) const
+    {
+        span_EXPECTS( detail::is_positive( idx ) && idx < size() );
+
+        return *( data() + idx );
+    }
+#endif
+
+#if span_FEATURE( MEMBER_AT )
+    span_constexpr14 reference at( size_type idx ) const
+    {
+#if span_CONFIG( NO_EXCEPTIONS )
+        return this->operator[]( idx );
+#else
+        if ( !detail::is_positive( idx ) || size() <= idx )
+        {
+            detail::throw_out_of_range( idx, size() );
+        }
+        return *( data() + idx );
+#endif
+    }
+#endif
+
+    span_constexpr pointer data() const span_noexcept
+    {
+        return data_;
+    }
+
+#if span_FEATURE( MEMBER_BACK_FRONT )
+
+    span_constexpr_exp reference front() const span_noexcept
+    {
+        span_EXPECTS( ! empty() );
+
+        return *data();
+    }
+
+    span_constexpr_exp reference back() const span_noexcept
+    {
+        span_EXPECTS( ! empty() );
+
+        return *( data() + size() - 1 );
+    }
+
+#endif
+
+    // xx.x.x.x Modifiers [span.modifiers]
+
+#if span_FEATURE( MEMBER_SWAP )
+
+    span_constexpr14 void swap( span & other ) span_noexcept
+    {
+        using std::swap;
+        swap( data_, other.data_ );
+        swap( size_, other.size_ );
+    }
+#endif
+
+    // 26.7.3.6 Iterator support [span.iterators]
+
+    span_constexpr iterator begin() const span_noexcept
+    {
+#if span_CPP11_OR_GREATER
+        return { data() };
+#else
+        return iterator( data() );
+#endif
+    }
+
+    span_constexpr iterator end() const span_noexcept
+    {
+#if span_CPP11_OR_GREATER
+        return { data() + size() };
+#else
+        return iterator( data() + size() );
+#endif
+    }
+
+    span_constexpr const_iterator cbegin() const span_noexcept
+    {
+#if span_CPP11_OR_GREATER
+        return { data() };
+#else
+        return const_iterator( data() );
+#endif
+    }
+
+    span_constexpr const_iterator cend() const span_noexcept
+    {
+#if span_CPP11_OR_GREATER
+        return { data() + size() };
+#else
+        return const_iterator( data() + size() );
+#endif
+    }
+
+    span_constexpr reverse_iterator rbegin() const span_noexcept
+    {
+        return reverse_iterator( end() );
+    }
+
+    span_constexpr reverse_iterator rend() const span_noexcept
+    {
+        return reverse_iterator( begin() );
+    }
+
+    span_constexpr const_reverse_iterator crbegin() const span_noexcept
+    {
+        return const_reverse_iterator ( cend() );
+    }
+
+    span_constexpr const_reverse_iterator crend() const span_noexcept
+    {
+        return const_reverse_iterator( cbegin() );
+    }
+
+private:
+
+    // Note: C++20 has std::pointer_traits<Ptr>::to_address( it );
+
+#if span_HAVE( ITERATOR_CTOR )
+    static inline span_constexpr pointer to_address( std::nullptr_t ) span_noexcept
+    {
+        return nullptr;
+    }
+
+    template< typename U >
+    static inline span_constexpr U * to_address( U * p ) span_noexcept
+    {
+        return p;
+    }
+
+    template< typename Ptr
+        span_REQUIRES_T(( ! std::is_pointer<Ptr>::value ))
+    >
+    static inline span_constexpr pointer to_address( Ptr const & it ) span_noexcept
+    {
+        return to_address( it.operator->() );
+    }
+#endif // span_HAVE( ITERATOR_CTOR )
+
+private:
+    pointer   data_;
+    size_type size_;
+};
+
+// class template argument deduction guides:
+
+#if span_HAVE( DEDUCTION_GUIDES )
+
+template< class T, size_t N >
+span( T (&)[N] ) -> span<T, static_cast<extent_t>(N)>;
+
+template< class T, size_t N >
+span( std::array<T, N> & ) -> span<T, static_cast<extent_t>(N)>;
+
+template< class T, size_t N >
+span( std::array<T, N> const & ) -> span<const T, static_cast<extent_t>(N)>;
+
+#if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+template< class Container >
+span( Container& ) -> span<typename Container::value_type>;
+
+template< class Container >
+span( Container const & ) -> span<const typename Container::value_type>;
+
+#endif
+
+// iterator: constraints: It satisfies contiguous_­iterator.
+
+template< class It, class EndOrSize >
+span( It, EndOrSize ) -> span< typename std11::remove_reference< typename std20::iter_reference_t<It> >::type >;
+
+#endif // span_HAVE( DEDUCTION_GUIDES )
+
+// 26.7.3.7 Comparison operators [span.comparison]
+
+#if span_FEATURE( COMPARISON )
+#if span_FEATURE( SAME )
+
+template< class T1, extent_t E1, class T2, extent_t E2  >
+inline span_constexpr bool same( span<T1,E1> const & l, span<T2,E2> const & r ) span_noexcept
+{
+    return std11::is_same<T1, T2>::value
+        && l.size() == r.size()
+        && static_cast<void const*>( l.data() ) == r.data();
+}
+
+#endif
+
+template< class T1, extent_t E1, class T2, extent_t E2  >
+inline span_constexpr bool operator==( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+    return
+#if span_FEATURE( SAME )
+        same( l, r ) ||
+#endif
+        ( l.size() == r.size() && std::equal( l.begin(), l.end(), r.begin() ) );
+}
+
+template< class T1, extent_t E1, class T2, extent_t E2  >
+inline span_constexpr bool operator<( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+    return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+
+template< class T1, extent_t E1, class T2, extent_t E2  >
+inline span_constexpr bool operator!=( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+    return !( l == r );
+}
+
+template< class T1, extent_t E1, class T2, extent_t E2  >
+inline span_constexpr bool operator<=( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+    return !( r < l );
+}
+
+template< class T1, extent_t E1, class T2, extent_t E2  >
+inline span_constexpr bool operator>( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+    return ( r < l );
+}
+
+template< class T1, extent_t E1, class T2, extent_t E2  >
+inline span_constexpr bool operator>=( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+    return !( l < r );
+}
+
+#endif // span_FEATURE( COMPARISON )
+
+// 26.7.2.6 views of object representation [span.objectrep]
+
+#if span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE )
+
+// Avoid MSVC 14.1 (1910), VS 2017: warning C4307: '*': integral constant overflow:
+
+template< typename T, extent_t Extent >
+struct BytesExtent
+{
+#if span_CPP11_OR_GREATER
+    enum ET : extent_t { value = span_sizeof(T) * Extent };
+#else
+    enum ET { value = span_sizeof(T) * Extent };
+#endif
+};
+
+template< typename T >
+struct BytesExtent< T, dynamic_extent >
+{
+#if span_CPP11_OR_GREATER
+    enum ET : extent_t { value = dynamic_extent };
+#else
+    enum ET { value = dynamic_extent };
+#endif
+};
+
+template< class T, extent_t Extent >
+inline span_constexpr span< const std17::byte, BytesExtent<T, Extent>::value >
+as_bytes( span<T,Extent> spn ) span_noexcept
+{
+#if 0
+    return { reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() };
+#else
+    return span< const std17::byte, BytesExtent<T, Extent>::value >(
+        reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() );  // NOLINT
+#endif
+}
+
+template< class T, extent_t Extent >
+inline span_constexpr span< std17::byte, BytesExtent<T, Extent>::value >
+as_writable_bytes( span<T,Extent> spn ) span_noexcept
+{
+#if 0
+    return { reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() };
+#else
+    return span< std17::byte, BytesExtent<T, Extent>::value >(
+        reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() );  // NOLINT
+#endif
+}
+
+#endif // span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE )
+
+// 27.8 Container and view access [iterator.container]
+
+template< class T, extent_t Extent /*= dynamic_extent*/ >
+span_constexpr std::size_t size( span<T,Extent> const & spn )
+{
+    return static_cast<std::size_t>( spn.size() );
+}
+
+template< class T, extent_t Extent /*= dynamic_extent*/ >
+span_constexpr std::ptrdiff_t ssize( span<T,Extent> const & spn )
+{
+    return static_cast<std::ptrdiff_t>( spn.size() );
+}
+
+}  // namespace span_lite
+}  // namespace nonstd
+
+// make available in nonstd:
+
+namespace nonstd {
+
+using span_lite::dynamic_extent;
+
+using span_lite::span;
+
+using span_lite::with_container;
+
+#if span_FEATURE( COMPARISON )
+#if span_FEATURE( SAME )
+using span_lite::same;
+#endif
+
+using span_lite::operator==;
+using span_lite::operator!=;
+using span_lite::operator<;
+using span_lite::operator<=;
+using span_lite::operator>;
+using span_lite::operator>=;
+#endif
+
+#if span_HAVE( BYTE )
+using span_lite::as_bytes;
+using span_lite::as_writable_bytes;
+#endif
+
+using span_lite::size;
+using span_lite::ssize;
+
+}  // namespace nonstd
+
+#endif  // span_USES_STD_SPAN
+
+// make_span() [span-lite extension]:
+
+#if span_FEATURE( MAKE_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER )
+
+#if span_USES_STD_SPAN
+# define  span_constexpr  constexpr
+# define  span_noexcept   noexcept
+# define  span_nullptr    nullptr
+# ifndef  span_CONFIG_EXTENT_TYPE
+#  define span_CONFIG_EXTENT_TYPE  std::size_t
+# endif
+using extent_t = span_CONFIG_EXTENT_TYPE;
+#endif  // span_USES_STD_SPAN
+
+namespace nonstd {
+namespace span_lite {
+
+template< class T >
+inline span_constexpr span<T>
+make_span( T * ptr, size_t count ) span_noexcept
+{
+    return span<T>( ptr, count );
+}
+
+template< class T >
+inline span_constexpr span<T>
+make_span( T * first, T * last ) span_noexcept
+{
+    return span<T>( first, last );
+}
+
+template< class T, std::size_t N >
+inline span_constexpr span<T, static_cast<extent_t>(N)>
+make_span( T ( &arr )[ N ] ) span_noexcept
+{
+    return span<T, static_cast<extent_t>(N)>( &arr[ 0 ], N );
+}
+
+#if span_USES_STD_SPAN || span_HAVE( ARRAY )
+
+template< class T, std::size_t N >
+inline span_constexpr span<T, static_cast<extent_t>(N)>
+make_span( std::array< T, N > & arr ) span_noexcept
+{
+    return span<T, static_cast<extent_t>(N)>( arr );
+}
+
+template< class T, std::size_t N >
+inline span_constexpr span< const T, static_cast<extent_t>(N) >
+make_span( std::array< T, N > const & arr ) span_noexcept
+{
+    return span<const T, static_cast<extent_t>(N)>( arr );
+}
+
+#endif // span_HAVE( ARRAY )
+
+#if span_USES_STD_SPAN
+
+template< class Container, class EP = decltype( std::data(std::declval<Container&>())) >
+inline span_constexpr auto
+make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer<EP>::type >
+{
+    return span< typename std::remove_pointer<EP>::type >( cont );
+}
+
+template< class Container, class EP = decltype( std::data(std::declval<Container&>())) >
+inline span_constexpr auto
+make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer<EP>::type >
+{
+    return span< const typename std::remove_pointer<EP>::type >( cont );
+}
+
+#elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && span_HAVE( AUTO )
+
+template< class Container, class EP = decltype( std17::data(std::declval<Container&>())) >
+inline span_constexpr auto
+make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer<EP>::type >
+{
+    return span< typename std::remove_pointer<EP>::type >( cont );
+}
+
+template< class Container, class EP = decltype( std17::data(std::declval<Container&>())) >
+inline span_constexpr auto
+make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer<EP>::type >
+{
+    return span< const typename std::remove_pointer<EP>::type >( cont );
+}
+
+#else
+
+template< class T >
+inline span_constexpr span<T>
+make_span( span<T> spn ) span_noexcept
+{
+    return spn;
+}
+
+template< class T, class Allocator >
+inline span_constexpr span<T>
+make_span( std::vector<T, Allocator> & cont ) span_noexcept
+{
+    return span<T>( with_container, cont );
+}
+
+template< class T, class Allocator >
+inline span_constexpr span<const T>
+make_span( std::vector<T, Allocator> const & cont ) span_noexcept
+{
+    return span<const T>( with_container, cont );
+}
+
+#endif // span_USES_STD_SPAN || ( ... )
+
+#if ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER )
+
+template< class Container >
+inline span_constexpr span<typename Container::value_type>
+make_span( with_container_t, Container & cont ) span_noexcept
+{
+    return span< typename Container::value_type >( with_container, cont );
+}
+
+template< class Container >
+inline span_constexpr span<const typename Container::value_type>
+make_span( with_container_t, Container const & cont ) span_noexcept
+{
+    return span< const typename Container::value_type >( with_container, cont );
+}
+
+#endif // ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER )
+
+// extensions: non-member views:
+// this feature implies the presence of make_span()
+
+#if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN )
+
+template< extent_t Count, class T, extent_t Extent >
+span_constexpr span<T, Count>
+first( span<T, Extent> spn )
+{
+    return spn.template first<Count>();
+}
+
+template< class T, extent_t Extent >
+span_constexpr span<T>
+first( span<T, Extent> spn, size_t count )
+{
+    return spn.first( count );
+}
+
+template< extent_t Count, class T, extent_t Extent >
+span_constexpr span<T, Count>
+last( span<T, Extent> spn )
+{
+    return spn.template last<Count>();
+}
+
+template< class T, extent_t Extent >
+span_constexpr span<T>
+last( span<T, Extent> spn, size_t count )
+{
+    return spn.last( count );
+}
+
+template< size_t Offset, extent_t Count, class T, extent_t Extent >
+span_constexpr span<T, Count>
+subspan( span<T, Extent> spn )
+{
+    return spn.template subspan<Offset, Count>();
+}
+
+template< class T, extent_t Extent >
+span_constexpr span<T>
+subspan( span<T, Extent> spn, size_t offset, extent_t count = dynamic_extent )
+{
+    return spn.subspan( offset, count );
+}
+
+#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN )
+
+#if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) && span_CPP11_120
+
+template< extent_t Count, class T >
+span_constexpr auto
+first( T & t ) -> decltype( make_span(t).template first<Count>() )
+{
+    return make_span( t ).template first<Count>();
+}
+
+template< class T >
+span_constexpr auto
+first( T & t, size_t count ) -> decltype( make_span(t).first(count) )
+{
+    return make_span( t ).first( count );
+}
+
+template< extent_t Count, class T >
+span_constexpr auto
+last( T & t ) -> decltype( make_span(t).template last<Count>() )
+{
+    return make_span(t).template last<Count>();
+}
+
+template< class T >
+span_constexpr auto
+last( T & t, extent_t count ) -> decltype( make_span(t).last(count) )
+{
+    return make_span( t ).last( count );
+}
+
+template< size_t Offset, extent_t Count = dynamic_extent, class T >
+span_constexpr auto
+subspan( T & t ) -> decltype( make_span(t).template subspan<Offset, Count>() )
+{
+    return make_span( t ).template subspan<Offset, Count>();
+}
+
+template< class T >
+span_constexpr auto
+subspan( T & t, size_t offset, extent_t count = dynamic_extent ) -> decltype( make_span(t).subspan(offset, count) )
+{
+    return make_span( t ).subspan( offset, count );
+}
+
+#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER )
+
+}  // namespace span_lite
+}  // namespace nonstd
+
+// make available in nonstd:
+
+namespace nonstd {
+using span_lite::make_span;
+
+#if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) || ( span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) && span_CPP11_120 )
+
+using span_lite::first;
+using span_lite::last;
+using span_lite::subspan;
+
+#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_[SPAN|CONTAINER] )
+
+}  // namespace nonstd
+
+#endif // #if span_FEATURE_TO_STD( MAKE_SPAN )
+
+#if span_CPP11_OR_GREATER && span_FEATURE( BYTE_SPAN ) && ( span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) )
+
+namespace nonstd {
+namespace span_lite {
+
+template< class T >
+inline span_constexpr auto
+byte_span( T & t ) span_noexcept -> span< std17::byte, span_sizeof(T) >
+{
+    return span< std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte * >( &t ), span_sizeof(T) );
+}
+
+template< class T >
+inline span_constexpr auto
+byte_span( T const & t ) span_noexcept -> span< const std17::byte, span_sizeof(T) >
+{
+    return span< const std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte const * >( &t ), span_sizeof(T) );
+}
+
+}  // namespace span_lite
+}  // namespace nonstd
+
+// make available in nonstd:
+
+namespace nonstd {
+using span_lite::byte_span;
+}  // namespace nonstd
+
+#endif // span_FEATURE( BYTE_SPAN )
+
+#if span_HAVE( STRUCT_BINDING )
+
+#if   span_CPP14_OR_GREATER
+# include <tuple>
+#elif span_CPP11_OR_GREATER
+# include <tuple>
+namespace std {
+    template< std::size_t I, typename T >
+    using tuple_element_t = typename tuple_element<I, T>::type;
+}
+#else
+namespace std {
+    template< typename T >
+    class tuple_size; /*undefined*/
+
+    template< std::size_t I, typename T >
+    class tuple_element; /* undefined */
+}
+#endif // span_CPP14_OR_GREATER
+
+namespace std {
+
+// 26.7.X Tuple interface
+
+// std::tuple_size<>:
+
+template< typename ElementType, nonstd::span_lite::extent_t Extent >
+class tuple_size< nonstd::span<ElementType, Extent> > : public integral_constant<size_t, static_cast<size_t>(Extent)> {};
+
+// std::tuple_size<>: Leave undefined for dynamic extent:
+
+template< typename ElementType >
+class tuple_size< nonstd::span<ElementType, nonstd::dynamic_extent> >;
+
+// std::tuple_element<>:
+
+template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent >
+class tuple_element< I, nonstd::span<ElementType, Extent> >
+{
+public:
+#if span_HAVE( STATIC_ASSERT )
+    static_assert( Extent != nonstd::dynamic_extent && I < Extent, "tuple_element<I,span>: dynamic extent or index out of range" );
+#endif
+    using type = ElementType;
+};
+
+// std::get<>(), 2 variants:
+
+template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent >
+span_constexpr ElementType & get( nonstd::span<ElementType, Extent> & spn ) span_noexcept
+{
+#if span_HAVE( STATIC_ASSERT )
+    static_assert( Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range" );
+#endif
+    return spn[I];
+}
+
+template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent >
+span_constexpr ElementType const & get( nonstd::span<ElementType, Extent> const & spn ) span_noexcept
+{
+#if span_HAVE( STATIC_ASSERT )
+    static_assert( Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range" );
+#endif
+    return spn[I];
+}
+
+} // end namespace std
+
+#endif // span_HAVE( STRUCT_BINDING )
+
+#if ! span_USES_STD_SPAN
+span_RESTORE_WARNINGS()
+#endif  // span_USES_STD_SPAN
+
+#endif  // NONSTD_SPAN_HPP_INCLUDED
diff --git a/ndn-cxx/encoding/block-helpers.cpp b/ndn-cxx/encoding/block-helpers.cpp
index dd6e08f..f7ea61e 100644
--- a/ndn-cxx/encoding/block-helpers.cpp
+++ b/ndn-cxx/encoding/block-helpers.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -178,22 +178,16 @@
 // ---- binary ----
 
 Block
-makeBinaryBlock(uint32_t type, const uint8_t* value, size_t length)
+makeBinaryBlock(uint32_t type, span<const uint8_t> value)
 {
   EncodingEstimator estimator;
-  size_t totalLength = estimator.prependByteArrayBlock(type, value, length);
+  size_t totalLength = estimator.prependByteArrayBlock(type, value.data(), value.size());
 
   EncodingBuffer encoder(totalLength, 0);
-  encoder.prependByteArrayBlock(type, value, length);
+  encoder.prependByteArrayBlock(type, value.data(), value.size());
 
   return encoder.block();
 }
 
-Block
-makeBinaryBlock(uint32_t type, const char* value, size_t length)
-{
-  return makeBinaryBlock(type, reinterpret_cast<const uint8_t*>(value), length);
-}
-
 } // namespace encoding
 } // namespace ndn
diff --git a/ndn-cxx/encoding/block-helpers.hpp b/ndn-cxx/encoding/block-helpers.hpp
index 2986752..043ca85 100644
--- a/ndn-cxx/encoding/block-helpers.hpp
+++ b/ndn-cxx/encoding/block-helpers.hpp
@@ -25,6 +25,7 @@
 #include "ndn-cxx/encoding/block.hpp"
 #include "ndn-cxx/encoding/encoding-buffer.hpp"
 #include "ndn-cxx/util/concepts.hpp"
+#include "ndn-cxx/util/span.hpp"
 
 namespace ndn {
 namespace encoding {
@@ -181,23 +182,37 @@
 double
 readDouble(const Block& block);
 
-/** @brief Create a TLV block copying TLV-VALUE from raw buffer.
+/** @brief Create a TLV block copying the TLV-VALUE from a range.
  *  @param type TLV-TYPE number
- *  @param value raw buffer as TLV-VALUE
- *  @param length length of value buffer
+ *  @param value range of bytes to use as TLV-VALUE
  *  @sa Encoder::prependByteArrayBlock
  */
 Block
-makeBinaryBlock(uint32_t type, const uint8_t* value, size_t length);
+makeBinaryBlock(uint32_t type, span<const uint8_t> value);
 
-/** @brief Create a TLV block copying TLV-VALUE from raw buffer.
+/** @brief Create a TLV block copying the TLV-VALUE from a raw buffer.
  *  @param type TLV-TYPE number
  *  @param value raw buffer as TLV-VALUE
  *  @param length length of value buffer
  *  @sa Encoder::prependByteArrayBlock
  */
-Block
-makeBinaryBlock(uint32_t type, const char* value, size_t length);
+inline Block
+makeBinaryBlock(uint32_t type, const uint8_t* value, size_t length)
+{
+  return makeBinaryBlock(type, {value, length});
+}
+
+/** @brief Create a TLV block copying the TLV-VALUE from a raw buffer.
+ *  @param type TLV-TYPE number
+ *  @param value raw buffer as TLV-VALUE
+ *  @param length length of value buffer
+ *  @sa Encoder::prependByteArrayBlock
+ */
+inline Block
+makeBinaryBlock(uint32_t type, const char* value, size_t length)
+{
+  return makeBinaryBlock(type, {reinterpret_cast<const uint8_t*>(value), length});
+}
 
 namespace detail {
 
@@ -252,8 +267,8 @@
 } // namespace detail
 
 /** @brief Create a TLV block copying TLV-VALUE from iterators.
- *  @tparam Iterator an InputIterator dereferencable to an 1-octet type; faster implementation is
- *                   available for RandomAccessIterator
+ *  @tparam Iterator an InputIterator dereferenceable to a 1-octet type; a faster implementation is
+ *                   automatically selected for RandomAccessIterator
  *  @param type TLV-TYPE number
  *  @param first begin iterator
  *  @param last past-the-end iterator
diff --git a/ndn-cxx/encoding/block.cpp b/ndn-cxx/encoding/block.cpp
index 2c40fdb..052b049 100644
--- a/ndn-cxx/encoding/block.cpp
+++ b/ndn-cxx/encoding/block.cpp
@@ -520,7 +520,7 @@
 
   for (const char* end = input + len; input != end; ++input) {
     if (std::strchr("0123456789ABCDEF", *input) != nullptr) {
-      ss.write(reinterpret_cast<const uint8_t*>(input), 1);
+      ss.write({reinterpret_cast<const uint8_t*>(input), 1});
     }
   }
 
diff --git a/ndn-cxx/impl/name-component-types.hpp b/ndn-cxx/impl/name-component-types.hpp
index 2ab5570..5f224ae 100644
--- a/ndn-cxx/impl/name-component-types.hpp
+++ b/ndn-cxx/impl/name-component-types.hpp
@@ -63,10 +63,10 @@
 
   /** \brief Return the minimum allowable TLV-VALUE of this component type.
    */
-  virtual const std::vector<uint8_t>&
+  virtual span<const uint8_t>
   getMinValue() const
   {
-    static std::vector<uint8_t> value;
+    static const std::vector<uint8_t> value;
     return value;
   }
 
@@ -197,13 +197,13 @@
   Component
   create(ConstBufferPtr value) const
   {
-    return Component(Block(m_type, std::move(value)));
+    return Block(m_type, std::move(value));
   }
 
   Component
-  create(const uint8_t* value, size_t valueSize) const
+  create(span<const uint8_t> value) const
   {
-    return Component(makeBinaryBlock(m_type, value, valueSize));
+    return makeBinaryBlock(m_type, value);
   }
 
   std::pair<bool, Component>
@@ -218,10 +218,10 @@
     return {false, Component(successor)};
   }
 
-  const std::vector<uint8_t>&
+  span<const uint8_t>
   getMinValue() const final
   {
-    static std::vector<uint8_t> value(util::Sha256::DIGEST_SIZE);
+    static const std::vector<uint8_t> value(util::Sha256::DIGEST_SIZE);
     return value;
   }
 
diff --git a/ndn-cxx/interest.cpp b/ndn-cxx/interest.cpp
index d4bdcf5..f1b3171 100644
--- a/ndn-cxx/interest.cpp
+++ b/ndn-cxx/interest.cpp
@@ -611,15 +611,15 @@
   wireEncode();
 
   // Get Interest name minus any ParametersSha256DigestComponent
-  // Name is guaranteed to be non-empty if wireEncode does not throw
+  // Name is guaranteed to be non-empty if wireEncode() does not throw
   BOOST_ASSERT(!m_name.empty());
   if (m_name[-1].type() != tlv::ParametersSha256DigestComponent) {
     NDN_THROW(Error("Interest Name must end with a ParametersSha256DigestComponent"));
   }
 
-  bufs.emplace_back(m_name[0].wire(), std::distance(m_name[0].wire(), m_name[-1].wire()));
+  bufs.emplace_back(m_name[0].wire(), m_name[-1].wire());
 
-  // Ensure has InterestSignatureInfo field
+  // Ensure InterestSignatureInfo element is present
   auto sigInfoIt = findFirstParameter(tlv::InterestSignatureInfo);
   if (sigInfoIt == m_parameters.end()) {
     NDN_THROW(Error("Interest missing InterestSignatureInfo"));
@@ -628,9 +628,10 @@
   // Get range from ApplicationParameters to InterestSignatureValue
   // or end of parameters (whichever is first)
   BOOST_ASSERT(!m_parameters.empty() && m_parameters.begin()->type() == tlv::ApplicationParameters);
-  auto sigValueIt = findFirstParameter(tlv::InterestSignatureValue);
-  bufs.emplace_back(m_parameters.begin()->wire(),
-                    std::distance(m_parameters.begin()->begin(), std::prev(sigValueIt)->end()));
+  auto lastSignedIt = std::prev(findFirstParameter(tlv::InterestSignatureValue));
+  // Note: we assume that both iterators point to the same underlying buffer
+  bufs.emplace_back(m_parameters.front().begin(), lastSignedIt->end());
+
   return bufs;
 }
 
@@ -667,7 +668,7 @@
   in >> digestFilter(DigestAlgorithm::SHA256) >> streamSink(out);
 
   for (const auto& block : m_parameters) {
-    in.write(block.wire(), block.size());
+    in.write({block.wire(), block.size()});
   }
   in.end();
 
diff --git a/ndn-cxx/key-locator.cpp b/ndn-cxx/key-locator.cpp
index 88b7f03..6cf24ac 100644
--- a/ndn-cxx/key-locator.cpp
+++ b/ndn-cxx/key-locator.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -184,7 +184,7 @@
 KeyLocator::setKeyDigest(const ConstBufferPtr& keyDigest)
 {
   BOOST_ASSERT(keyDigest != nullptr);
-  m_locator = makeBinaryBlock(tlv::KeyDigest, keyDigest->data(), keyDigest->size());
+  m_locator = makeBinaryBlock(tlv::KeyDigest, *keyDigest);
   m_wire.reset();
   return *this;
 }
diff --git a/ndn-cxx/metadata-object.cpp b/ndn-cxx/metadata-object.cpp
index 7f9a16d..e5da47c 100644
--- a/ndn-cxx/metadata-object.cpp
+++ b/ndn-cxx/metadata-object.cpp
@@ -81,7 +81,8 @@
 const name::Component&
 MetadataObject::getKeywordComponent()
 {
-  static const name::Component nc(tlv::KeywordNameComponent, {'m', 'e', 't', 'a', 'd', 'a', 't', 'a'});
+  static const name::Component nc(tlv::KeywordNameComponent,
+                                  std::array<uint8_t, 8>({'m', 'e', 't', 'a', 'd', 'a', 't', 'a'}));
   return nc;
 }
 
diff --git a/ndn-cxx/mgmt/status-dataset-context.cpp b/ndn-cxx/mgmt/status-dataset-context.cpp
index 81e0b96..3ada4e6 100644
--- a/ndn-cxx/mgmt/status-dataset-context.cpp
+++ b/ndn-cxx/mgmt/status-dataset-context.cpp
@@ -79,7 +79,7 @@
     if (cur != block.end()) {
       BOOST_ASSERT(m_buffer.size() == MAX_PAYLOAD_LENGTH);
       m_dataSender(Name(m_prefix).appendSegment(m_segmentNo++),
-                   makeBinaryBlock(tlv::Content, m_buffer.begin(), m_buffer.end()),
+                   makeBinaryBlock(tlv::Content, m_buffer),
                    false);
       m_buffer.clear();
     }
@@ -95,7 +95,7 @@
 
   m_state = State::FINALIZED;
   m_dataSender(Name(m_prefix).appendSegment(m_segmentNo),
-               makeBinaryBlock(tlv::Content, m_buffer.begin(), m_buffer.end()),
+               makeBinaryBlock(tlv::Content, m_buffer),
                true);
 }
 
diff --git a/ndn-cxx/name-component.cpp b/ndn-cxx/name-component.cpp
index d9434f0..23f0060 100644
--- a/ndn-cxx/name-component.cpp
+++ b/ndn-cxx/name-component.cpp
@@ -143,8 +143,8 @@
   ensureValid();
 }
 
-Component::Component(uint32_t type, const uint8_t* value, size_t valueLen)
-  : Block(makeBinaryBlock(type, value, valueLen))
+Component::Component(uint32_t type, span<const uint8_t> value)
+  : Block(makeBinaryBlock(type, value))
 {
   ensureValid();
 }
@@ -440,13 +440,13 @@
 Component
 Component::fromImplicitSha256Digest(ConstBufferPtr digest)
 {
-  return detail::getComponentType1().create(digest);
+  return detail::getComponentType1().create(std::move(digest));
 }
 
 Component
-Component::fromImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
+Component::fromImplicitSha256Digest(span<const uint8_t> digest)
 {
-  return detail::getComponentType1().create(digest, digestSize);
+  return detail::getComponentType1().create(digest);
 }
 
 bool
@@ -458,13 +458,13 @@
 Component
 Component::fromParametersSha256Digest(ConstBufferPtr digest)
 {
-  return detail::getComponentType2().create(digest);
+  return detail::getComponentType2().create(std::move(digest));
 }
 
 Component
-Component::fromParametersSha256Digest(const uint8_t* digest, size_t digestSize)
+Component::fromParametersSha256Digest(span<const uint8_t> digest)
 {
-  return detail::getComponentType2().create(digest, digestSize);
+  return detail::getComponentType2().create(digest);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -507,14 +507,13 @@
 {
   bool isOverflow = false;
   Component successor;
-  std::tie(isOverflow, successor) =
-    detail::getComponentTypeTable().get(type()).getSuccessor(*this);
+  std::tie(isOverflow, successor) = detail::getComponentTypeTable().get(type()).getSuccessor(*this);
   if (!isOverflow) {
     return successor;
   }
 
   uint32_t type = this->type() + 1;
-  const std::vector<uint8_t>& value = detail::getComponentTypeTable().get(type).getMinValue();
+  auto value = detail::getComponentTypeTable().get(type).getMinValue();
   return Component(type, value.data(), value.size());
 }
 
diff --git a/ndn-cxx/name-component.hpp b/ndn-cxx/name-component.hpp
index eac758b..dde0ae8 100644
--- a/ndn-cxx/name-component.hpp
+++ b/ndn-cxx/name-component.hpp
@@ -154,16 +154,13 @@
   /**
    * @brief Construct a NameComponent of TLV-TYPE @p type, copying TLV-VALUE from @p buffer.
    */
-  Component(uint32_t type, const Buffer& buffer)
-    : Component(type, buffer.data(), buffer.size())
-  {
-  }
+  Component(uint32_t type, span<const uint8_t> buffer);
 
   /**
    * @brief Construct a GenericNameComponent, copying TLV-VALUE from @p buffer.
    */
   explicit
-  Component(const Buffer& buffer)
+  Component(span<const uint8_t> buffer)
     : Component(tlv::GenericNameComponent, buffer)
   {
   }
@@ -172,13 +169,16 @@
    * @brief Construct a NameComponent of TLV-TYPE @p type, copying @p count bytes at @p value as
    *        TLV-VALUE.
    */
-  Component(uint32_t type, const uint8_t* value, size_t count);
+  Component(uint32_t type, const uint8_t* value, size_t count)
+    : Component(type, {value, count})
+  {
+  }
 
   /**
    * @brief Construct a GenericNameComponent, copying @p count bytes at @p value as TLV-VALUE.
    */
   Component(const uint8_t* value, size_t count)
-    : Component(tlv::GenericNameComponent, value, count)
+    : Component(tlv::GenericNameComponent, {value, count})
   {
   }
 
@@ -504,7 +504,7 @@
    * @brief Create ImplicitSha256DigestComponent component
    */
   static Component
-  fromImplicitSha256Digest(const uint8_t* digest, size_t digestSize);
+  fromImplicitSha256Digest(span<const uint8_t> digest);
 
   /**
    * @brief Check if the component is ParametersSha256DigestComponent
@@ -522,7 +522,7 @@
    * @brief Create ParametersSha256DigestComponent component
    */
   static Component
-  fromParametersSha256Digest(const uint8_t* digest, size_t digestSize);
+  fromParametersSha256Digest(span<const uint8_t> digest);
 
 public: // comparison
   NDN_CXX_NODISCARD bool
diff --git a/ndn-cxx/name.hpp b/ndn-cxx/name.hpp
index 72b6c64..a061d65 100644
--- a/ndn-cxx/name.hpp
+++ b/ndn-cxx/name.hpp
@@ -473,9 +473,9 @@
    * @return a reference to this name, to allow chaining
    */
   Name&
-  appendImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
+  appendImplicitSha256Digest(span<const uint8_t> digestBytes)
   {
-    return append(Component::fromImplicitSha256Digest(digest, digestSize));
+    return append(Component::fromImplicitSha256Digest(digestBytes));
   }
 
   /**
@@ -493,9 +493,9 @@
    * @return a reference to this name, to allow chaining
    */
   Name&
-  appendParametersSha256Digest(const uint8_t* digest, size_t digestSize)
+  appendParametersSha256Digest(span<const uint8_t> digestBytes)
   {
-    return append(Component::fromParametersSha256Digest(digest, digestSize));
+    return append(Component::fromParametersSha256Digest(digestBytes));
   }
 
   /**
diff --git a/ndn-cxx/prefix-announcement.cpp b/ndn-cxx/prefix-announcement.cpp
index 6e315d3..cfad221 100644
--- a/ndn-cxx/prefix-announcement.cpp
+++ b/ndn-cxx/prefix-announcement.cpp
@@ -122,7 +122,7 @@
 const name::Component&
 PrefixAnnouncement::getKeywordComponent()
 {
-  static const name::Component nc(tlv::KeywordNameComponent, {'P', 'A'});
+  static const name::Component nc(tlv::KeywordNameComponent, std::array<uint8_t, 2>({'P', 'A'}));
   return nc;
 }
 
diff --git a/ndn-cxx/security/certificate.cpp b/ndn-cxx/security/certificate.cpp
index 1e93583..b033282 100644
--- a/ndn-cxx/security/certificate.cpp
+++ b/ndn-cxx/security/certificate.cpp
@@ -162,7 +162,7 @@
   {
     using namespace transform;
     util::IndentedStream os2(os, "  ");
-    bufferSource(cert.getPublicKey().data(), cert.getPublicKey().size()) >> base64Encode() >> streamSink(os2);
+    bufferSource(cert.getPublicKey()) >> base64Encode() >> streamSink(os2);
   }
 
   os << "Signature Information:\n";
diff --git a/ndn-cxx/security/impl/openssl-helper.cpp b/ndn-cxx/security/impl/openssl-helper.cpp
index 104723c..cff01b1 100644
--- a/ndn-cxx/security/impl/openssl-helper.cpp
+++ b/ndn-cxx/security/impl/openssl-helper.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -121,19 +121,19 @@
 }
 
 bool
-Bio::read(uint8_t* buf, size_t buflen) const noexcept
+Bio::read(span<uint8_t> buf) const noexcept
 {
-  BOOST_ASSERT(buflen <= std::numeric_limits<int>::max());
-  int n = BIO_read(m_bio, buf, static_cast<int>(buflen));
-  return n >= 0 && static_cast<size_t>(n) == buflen;
+  BOOST_ASSERT(buf.size() <= std::numeric_limits<int>::max());
+  int n = BIO_read(m_bio, buf.data(), static_cast<int>(buf.size()));
+  return n >= 0 && static_cast<size_t>(n) == buf.size();
 }
 
 bool
-Bio::write(const uint8_t* buf, size_t buflen) noexcept
+Bio::write(span<const uint8_t> buf) noexcept
 {
-  BOOST_ASSERT(buflen <= std::numeric_limits<int>::max());
-  int n = BIO_write(m_bio, buf, static_cast<int>(buflen));
-  return n >= 0 && static_cast<size_t>(n) == buflen;
+  BOOST_ASSERT(buf.size() <= std::numeric_limits<int>::max());
+  int n = BIO_write(m_bio, buf.data(), static_cast<int>(buf.size()));
+  return n >= 0 && static_cast<size_t>(n) == buf.size();
 }
 
 } // namespace detail
diff --git a/ndn-cxx/security/impl/openssl-helper.hpp b/ndn-cxx/security/impl/openssl-helper.hpp
index 679a694..647bba4 100644
--- a/ndn-cxx/security/impl/openssl-helper.hpp
+++ b/ndn-cxx/security/impl/openssl-helper.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -91,10 +91,10 @@
   }
 
   NDN_CXX_NODISCARD bool
-  read(uint8_t* buf, size_t buflen) const noexcept;
+  read(span<uint8_t> buf) const noexcept;
 
   NDN_CXX_NODISCARD bool
-  write(const uint8_t* buf, size_t buflen) noexcept;
+  write(span<const uint8_t> buf) noexcept;
 
 private:
   BIO* m_bio;
diff --git a/ndn-cxx/security/interest-signer.cpp b/ndn-cxx/security/interest-signer.cpp
index 36c131e..31f1427 100644
--- a/ndn-cxx/security/interest-signer.cpp
+++ b/ndn-cxx/security/interest-signer.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -42,7 +42,7 @@
 
   if (signingFlags & WantNonce) {
     std::vector<uint8_t> nonce(8);
-    random::generateSecureBytes(nonce.data(), nonce.size());
+    random::generateSecureBytes(nonce);
     info.setNonce(nonce);
   }
 
diff --git a/ndn-cxx/security/key-chain.cpp b/ndn-cxx/security/key-chain.cpp
index 63a37fb..0328d0f 100644
--- a/ndn-cxx/security/key-chain.cpp
+++ b/ndn-cxx/security/key-chain.cpp
@@ -371,7 +371,7 @@
   Certificate cert(std::move(certData));
   Name identity = cert.getIdentity();
   Name keyName = cert.getKeyName();
-  const Buffer publicKeyBits = cert.getPublicKey();
+  const auto publicKeyBits = cert.getPublicKey();
 
   if (m_tpm->hasKey(keyName)) {
     NDN_THROW(Error("Private key `" + keyName.toUri() + "` already exists"));
@@ -387,9 +387,7 @@
   }
 
   try {
-    m_tpm->importPrivateKey(keyName,
-                            safeBag.getEncryptedKey().data(), safeBag.getEncryptedKey().size(),
-                            pw, pwLen);
+    m_tpm->importPrivateKey(keyName, safeBag.getEncryptedKey(), pw, pwLen);
   }
   catch (const Tpm::Error&) {
     NDN_THROW_NESTED(Error("Failed to import private key `" + keyName.toUri() + "`"));
@@ -409,10 +407,10 @@
   {
     using namespace transform;
     PublicKey publicKey;
-    publicKey.loadPkcs8(publicKeyBits.data(), publicKeyBits.size());
-    bufferSource(content, sizeof(content)) >> verifierFilter(DigestAlgorithm::SHA256, publicKey,
-                                                             sigBits->data(), sigBits->size())
-                                           >> boolSink(isVerified);
+    publicKey.loadPkcs8(publicKeyBits);
+    bufferSource(content) >> verifierFilter(DigestAlgorithm::SHA256, publicKey,
+                                            sigBits->data(), sigBits->size())
+                          >> boolSink(isVerified);
   }
   if (!isVerified) {
     m_tpm->deleteKey(keyName);
diff --git a/ndn-cxx/security/pib/identity.cpp b/ndn-cxx/security/pib/identity.cpp
index c9bd82b..3b972b1 100644
--- a/ndn-cxx/security/pib/identity.cpp
+++ b/ndn-cxx/security/pib/identity.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -29,7 +29,7 @@
 Identity::Identity() = default;
 
 Identity::Identity(weak_ptr<detail::IdentityImpl> impl)
-  : m_impl(impl)
+  : m_impl(std::move(impl))
 {
 }
 
@@ -42,13 +42,13 @@
 Key
 Identity::addKey(const uint8_t* key, size_t keyLen, const Name& keyName) const
 {
-  return lock()->addKey(key, keyLen, keyName);
+  return lock()->addKey({key, keyLen}, keyName);
 }
 
 void
 Identity::removeKey(const Name& keyName) const
 {
-  return lock()->removeKey(keyName);
+  lock()->removeKey(keyName);
 }
 
 Key
@@ -72,7 +72,7 @@
 const Key&
 Identity::setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName) const
 {
-  return lock()->setDefaultKey(key, keyLen, keyName);
+  return lock()->setDefaultKey({key, keyLen}, keyName);
 }
 
 const Key&
diff --git a/ndn-cxx/security/pib/impl/identity-impl.cpp b/ndn-cxx/security/pib/impl/identity-impl.cpp
index dd77a1b..4c6adb4 100644
--- a/ndn-cxx/security/pib/impl/identity-impl.cpp
+++ b/ndn-cxx/security/pib/impl/identity-impl.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -45,10 +45,10 @@
 }
 
 Key
-IdentityImpl::addKey(const uint8_t* key, size_t keyLen, const Name& keyName)
+IdentityImpl::addKey(span<const uint8_t> key, const Name& keyName)
 {
   BOOST_ASSERT(m_keys.isConsistent());
-  return m_keys.add(key, keyLen, keyName);
+  return m_keys.add(key, keyName);
 }
 
 void
@@ -88,9 +88,9 @@
 }
 
 const Key&
-IdentityImpl::setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName)
+IdentityImpl::setDefaultKey(span<const uint8_t> key, const Name& keyName)
 {
-  addKey(key, keyLen, keyName);
+  addKey(key, keyName);
   return setDefaultKey(keyName);
 }
 
diff --git a/ndn-cxx/security/pib/impl/identity-impl.hpp b/ndn-cxx/security/pib/impl/identity-impl.hpp
index 8d9a86d..e71d170 100644
--- a/ndn-cxx/security/pib/impl/identity-impl.hpp
+++ b/ndn-cxx/security/pib/impl/identity-impl.hpp
@@ -63,16 +63,16 @@
   }
 
   /**
-   * @brief Add a @p key of @p keyLen bytes with @p keyName (in PKCS#8 format).
+   * @brief Add @p key with name @p keyName (in PKCS #8 format).
    *
    * If no default key is set before, the new key will be set as the default key of the identity.
-   * If a key with the same name already exists, overwrite the key.
+   * If a key with the same name already exists, it will be overwritten.
    *
    * @return the added key.
    * @throw std::invalid_argument key name does not match identity
    */
   Key
-  addKey(const uint8_t* key, size_t keyLen, const Name& keyName);
+  addKey(span<const uint8_t> key, const Name& keyName);
 
   /**
    * @brief Remove a key with @p keyName
@@ -106,13 +106,13 @@
   setDefaultKey(const Name& keyName);
 
   /**
-   * @brief Add @p key of @p keyLen bytes with @p keyName and set it as the default key
+   * @brief Add @p key with name @p keyName and set it as the default key.
    * @throw std::invalid_argument @p keyName does not match identity
    * @throw Pib::Error the key with the same name already exists
    * @return the default key
    */
   const Key&
-  setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName);
+  setDefaultKey(span<const uint8_t> key, const Name& keyName);
 
   /**
    * @brief Get the default key for this Identity.
diff --git a/ndn-cxx/security/pib/impl/key-impl.cpp b/ndn-cxx/security/pib/impl/key-impl.cpp
index 1447a98..dc0a7b0 100644
--- a/ndn-cxx/security/pib/impl/key-impl.cpp
+++ b/ndn-cxx/security/pib/impl/key-impl.cpp
@@ -29,10 +29,10 @@
 namespace pib {
 namespace detail {
 
-KeyImpl::KeyImpl(const Name& keyName, const uint8_t* key, size_t keyLen, shared_ptr<PibImpl> pibImpl)
+KeyImpl::KeyImpl(const Name& keyName, span<const uint8_t> key, shared_ptr<PibImpl> pibImpl)
   : m_identity(extractIdentityFromKeyName(keyName))
   , m_keyName(keyName)
-  , m_key(key, keyLen)
+  , m_key(key.begin(), key.end())
   , m_pib(std::move(pibImpl))
   , m_certificates(keyName, m_pib)
   , m_isDefaultCertificateLoaded(false)
@@ -41,14 +41,14 @@
 
   transform::PublicKey publicKey;
   try {
-    publicKey.loadPkcs8(key, keyLen);
+    publicKey.loadPkcs8(key);
   }
   catch (const transform::PublicKey::Error&) {
     NDN_THROW_NESTED(std::invalid_argument("Invalid key bits"));
   }
   m_keyType = publicKey.getKeyType();
 
-  m_pib->addKey(m_identity, m_keyName, key, keyLen);
+  m_pib->addKey(m_identity, m_keyName, key);
 }
 
 KeyImpl::KeyImpl(const Name& keyName, shared_ptr<PibImpl> pibImpl)
@@ -63,7 +63,7 @@
   m_key = m_pib->getKeyBits(m_keyName);
 
   transform::PublicKey key;
-  key.loadPkcs8(m_key.data(), m_key.size());
+  key.loadPkcs8(m_key);
   m_keyType = key.getKeyType();
 }
 
diff --git a/ndn-cxx/security/pib/impl/key-impl.hpp b/ndn-cxx/security/pib/impl/key-impl.hpp
index 64a00d7..ea43dac 100644
--- a/ndn-cxx/security/pib/impl/key-impl.hpp
+++ b/ndn-cxx/security/pib/impl/key-impl.hpp
@@ -34,9 +34,9 @@
 namespace detail {
 
 /**
- * @brief Backend instance of Key
+ * @brief Backend instance of Key.
  *
- * An Key has only one backend instance, but may have multiple frontend handles.
+ * A Key has only one backend instance, but may have multiple frontend handles.
  * Each frontend handle is associated with the only one backend KeyImpl.
  *
  * @throw PibImpl::Error when underlying implementation has non-semantic error.
@@ -51,12 +51,11 @@
    * If a key with the same name already exists, it will be overwritten.
    *
    * @param keyName The name of the key.
-   * @param key The public key to add.
-   * @param keyLen The length of the key.
+   * @param key The public key bits.
    * @param pibImpl The Pib backend implementation.
    * @throw std::invalid_argument @p key is invalid.
    */
-  KeyImpl(const Name& keyName, const uint8_t* key, size_t keyLen, shared_ptr<PibImpl> pibImpl);
+  KeyImpl(const Name& keyName, span<const uint8_t> key, shared_ptr<PibImpl> pibImpl);
 
   /**
    * @brief Create a KeyImpl with @p keyName.
@@ -97,7 +96,7 @@
   /**
    * @brief Get public key bits.
    */
-  const Buffer&
+  span<const uint8_t>
   getPublicKey() const
   {
     return m_key;
diff --git a/ndn-cxx/security/pib/impl/pib-memory.cpp b/ndn-cxx/security/pib/impl/pib-memory.cpp
index 22e7b48..65f729f 100644
--- a/ndn-cxx/security/pib/impl/pib-memory.cpp
+++ b/ndn-cxx/security/pib/impl/pib-memory.cpp
@@ -130,12 +130,11 @@
 }
 
 void
-PibMemory::addKey(const Name& identity, const Name& keyName,
-                  const uint8_t* key, size_t keyLen)
+PibMemory::addKey(const Name& identity, const Name& keyName, span<const uint8_t> key)
 {
   addIdentity(identity);
 
-  m_keys[keyName] = Buffer(key, keyLen);
+  m_keys[keyName] = Buffer(key.begin(), key.end());
 
   if (m_defaultKeys.count(identity) == 0) {
     m_defaultKeys[identity] = keyName;
@@ -210,11 +209,11 @@
 void
 PibMemory::addCertificate(const Certificate& certificate)
 {
-  Name certName = certificate.getName();
-  Name keyName = certificate.getKeyName();
-  Name identity = certificate.getIdentity();
+  const Name& certName = certificate.getName();
+  const Name& keyName = certificate.getKeyName();
 
-  addKey(identity, keyName, certificate.getContent().value(), certificate.getContent().value_size());
+  const auto& content = certificate.getContent();
+  addKey(certificate.getIdentity(), keyName, {content.value(), content.value_size()});
 
   m_certs[certName] = certificate;
   if (m_defaultCerts.count(keyName) == 0) {
diff --git a/ndn-cxx/security/pib/impl/pib-memory.hpp b/ndn-cxx/security/pib/impl/pib-memory.hpp
index 63a3b49..fb1bf13 100644
--- a/ndn-cxx/security/pib/impl/pib-memory.hpp
+++ b/ndn-cxx/security/pib/impl/pib-memory.hpp
@@ -81,7 +81,7 @@
   hasKey(const Name& keyName) const override;
 
   void
-  addKey(const Name& identity, const Name& keyName, const uint8_t* key, size_t keyLen) override;
+  addKey(const Name& identity, const Name& keyName, span<const uint8_t> key) override;
 
   void
   removeKey(const Name& keyName) override;
diff --git a/ndn-cxx/security/pib/impl/pib-sqlite3.cpp b/ndn-cxx/security/pib/impl/pib-sqlite3.cpp
index 0e42c52..7b00591 100644
--- a/ndn-cxx/security/pib/impl/pib-sqlite3.cpp
+++ b/ndn-cxx/security/pib/impl/pib-sqlite3.cpp
@@ -364,8 +364,7 @@
 }
 
 void
-PibSqlite3::addKey(const Name& identity, const Name& keyName,
-                   const uint8_t* key, size_t keyLen)
+PibSqlite3::addKey(const Name& identity, const Name& keyName, span<const uint8_t> key)
 {
   // ensure identity exists
   addIdentity(identity);
@@ -376,13 +375,13 @@
                                "VALUES ((SELECT id FROM identities WHERE identity=?), ?, ?)");
     statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
     statement.bind(2, keyName.wireEncode(), SQLITE_TRANSIENT);
-    statement.bind(3, key, keyLen, SQLITE_STATIC);
+    statement.bind(3, key.data(), key.size(), SQLITE_STATIC);
     statement.step();
   }
   else {
     Sqlite3Statement statement(m_database,
                                "UPDATE keys SET key_bits=? WHERE key_name=?");
-    statement.bind(1, key, keyLen, SQLITE_STATIC);
+    statement.bind(1, key.data(), key.size(), SQLITE_STATIC);
     statement.bind(2, keyName.wireEncode(), SQLITE_TRANSIENT);
     statement.step();
   }
@@ -486,8 +485,9 @@
 PibSqlite3::addCertificate(const Certificate& certificate)
 {
   // ensure key exists
-  const Block& content = certificate.getContent();
-  addKey(certificate.getIdentity(), certificate.getKeyName(), content.value(), content.value_size());
+  const auto& content = certificate.getContent();
+  addKey(certificate.getIdentity(), certificate.getKeyName(),
+         {content.value(), content.value_size()});
 
   if (!hasCertificate(certificate.getName())) {
     Sqlite3Statement statement(m_database,
diff --git a/ndn-cxx/security/pib/impl/pib-sqlite3.hpp b/ndn-cxx/security/pib/impl/pib-sqlite3.hpp
index d5960c7..783a6a7 100644
--- a/ndn-cxx/security/pib/impl/pib-sqlite3.hpp
+++ b/ndn-cxx/security/pib/impl/pib-sqlite3.hpp
@@ -96,8 +96,7 @@
   hasKey(const Name& keyName) const final;
 
   void
-  addKey(const Name& identity, const Name& keyName,
-         const uint8_t* key, size_t keyLen) final;
+  addKey(const Name& identity, const Name& keyName, span<const uint8_t> key) final;
 
   void
   removeKey(const Name& keyName) final;
diff --git a/ndn-cxx/security/pib/key-container.cpp b/ndn-cxx/security/pib/key-container.cpp
index ceae0a7..aefb6b4 100644
--- a/ndn-cxx/security/pib/key-container.cpp
+++ b/ndn-cxx/security/pib/key-container.cpp
@@ -113,7 +113,7 @@
 }
 
 Key
-KeyContainer::add(const uint8_t* key, size_t keyLen, const Name& keyName)
+KeyContainer::add(span<const uint8_t> key, const Name& keyName)
 {
   if (m_identity != extractIdentityFromKeyName(keyName)) {
     NDN_THROW(std::invalid_argument("Key name `" + keyName.toUri() + "` does not match identity "
@@ -121,8 +121,7 @@
   }
 
   m_keyNames.insert(keyName);
-  m_keys[keyName] = make_shared<detail::KeyImpl>(keyName, key, keyLen, m_pib);
-
+  m_keys[keyName] = make_shared<detail::KeyImpl>(keyName, key, m_pib);
   return get(keyName);
 }
 
diff --git a/ndn-cxx/security/pib/key-container.hpp b/ndn-cxx/security/pib/key-container.hpp
index 1db0bae..b5b94ec 100644
--- a/ndn-cxx/security/pib/key-container.hpp
+++ b/ndn-cxx/security/pib/key-container.hpp
@@ -100,13 +100,14 @@
   size() const;
 
   /**
-   * @brief Add @p key of @p keyLen bytes with @p keyName into the container
-   * @throw std::invalid_argument @p keyName does not match the identity
+   * @brief Add @p key with name @p keyName into the container.
    *
-   * If a key with the same name already exists, overwrite the key.
+   * If a key with the same name already exists, it will be overwritten.
+   *
+   * @throw std::invalid_argument @p keyName does not match the identity
    */
   Key
-  add(const uint8_t* key, size_t keyLen, const Name& keyName);
+  add(span<const uint8_t> key, const Name& keyName);
 
   /**
    * @brief Remove a key with @p keyName from the container
diff --git a/ndn-cxx/security/pib/key.cpp b/ndn-cxx/security/pib/key.cpp
index d6fe78a..634ee46 100644
--- a/ndn-cxx/security/pib/key.cpp
+++ b/ndn-cxx/security/pib/key.cpp
@@ -52,7 +52,7 @@
   return lock()->getKeyType();
 }
 
-const Buffer&
+span<const uint8_t>
 Key::getPublicKey() const
 {
   return lock()->getPublicKey();
diff --git a/ndn-cxx/security/pib/key.hpp b/ndn-cxx/security/pib/key.hpp
index 0c4df65..09d1d5e 100644
--- a/ndn-cxx/security/pib/key.hpp
+++ b/ndn-cxx/security/pib/key.hpp
@@ -98,7 +98,7 @@
   /**
    * @brief Get public key bits.
    */
-  const Buffer&
+  span<const uint8_t>
   getPublicKey() const;
 
   /**
diff --git a/ndn-cxx/security/pib/pib-impl.hpp b/ndn-cxx/security/pib/pib-impl.hpp
index 99e4233..5b61c86 100644
--- a/ndn-cxx/security/pib/pib-impl.hpp
+++ b/ndn-cxx/security/pib/pib-impl.hpp
@@ -151,13 +151,12 @@
    * one as default key of the identity.  If no default identity has been set, @p identity
    * becomes the default.
    *
-   * @param identity The name of the belonged identity.
+   * @param identity The name of the identity that will own the added key.
    * @param keyName The key name.
    * @param key The public key bits.
-   * @param keyLen The length of the public key.
    */
   virtual void
-  addKey(const Name& identity, const Name& keyName, const uint8_t* key, size_t keyLen) = 0;
+  addKey(const Name& identity, const Name& keyName, span<const uint8_t> key) = 0;
 
   /**
    * @brief Remove a key with @p keyName and related certificates
diff --git a/ndn-cxx/security/safe-bag.cpp b/ndn-cxx/security/safe-bag.cpp
index 3502c5d..7612e45 100644
--- a/ndn-cxx/security/safe-bag.cpp
+++ b/ndn-cxx/security/safe-bag.cpp
@@ -39,10 +39,9 @@
   this->wireDecode(wire);
 }
 
-SafeBag::SafeBag(const Data& certificate,
-                 const Buffer& encryptedKey)
+SafeBag::SafeBag(const Data& certificate, span<const uint8_t> encryptedKey)
   : m_certificate(certificate)
-  , m_encryptedKey(encryptedKey)
+  , m_encryptedKey(encryptedKey.begin(), encryptedKey.end())
 {
 }
 
diff --git a/ndn-cxx/security/safe-bag.hpp b/ndn-cxx/security/safe-bag.hpp
index acc7813..05312de 100644
--- a/ndn-cxx/security/safe-bag.hpp
+++ b/ndn-cxx/security/safe-bag.hpp
@@ -52,19 +52,20 @@
   /**
    * @brief Create a new SafeBag object with the given certificate and private key
    *
-   * @param certificate A reference to the certificate data packet
-   * @param encryptedKey A reference to a Buffer with the private key in PKCS #8 format
+   * @param certificate The certificate data packet
+   * @param encryptedKey A buffer with the private key in PKCS #8 format
    */
-  SafeBag(const Data& certificate,
-          const Buffer& encryptedKey);
+  SafeBag(const Data& certificate, span<const uint8_t> encryptedKey);
 
   /**
    * @brief Create a new SafeBag object with the given certificate and private key
+   * @deprecated Use SafeBag(const Data&, span<const uint8_t>)
    *
    * @param certificate A reference to the certificate data packet
    * @param encryptedKey A pointer to the private key in PKCS #8 format
    * @param encryptedKeyLen The length of @p encryptedKey
    */
+  [[deprecated("use the constructor taking a span<>")]]
   SafeBag(const Data& certificate,
           const uint8_t* encryptedKey,
           size_t encryptedKeyLen);
@@ -102,7 +103,7 @@
   /**
    * @brief Get the private key in PKCS #8 format from safe bag
    */
-  const Buffer&
+  span<const uint8_t>
   getEncryptedKey() const
   {
     return m_encryptedKey;
diff --git a/ndn-cxx/security/security-common.hpp b/ndn-cxx/security/security-common.hpp
index 046a97f..dfbe6cf 100644
--- a/ndn-cxx/security/security-common.hpp
+++ b/ndn-cxx/security/security-common.hpp
@@ -23,6 +23,7 @@
 #define NDN_CXX_SECURITY_SECURITY_COMMON_HPP
 
 #include "ndn-cxx/detail/common.hpp"
+#include "ndn-cxx/util/span.hpp"
 
 #include <vector>
 
@@ -55,9 +56,9 @@
 } // namespace command_interest
 
 #ifndef DOXYGEN
-using InputBuffers = std::vector<std::pair<const uint8_t*, size_t>>;
+using InputBuffers = std::vector<span<const uint8_t>>;
 #else
-/// Represents a range of distcontiguous buffers as input to a security operation
+/// Represents a collection of discontiguous memory buffers as input to a security operation
 class InputBuffers;
 #endif
 
diff --git a/ndn-cxx/security/signing-info.cpp b/ndn-cxx/security/signing-info.cpp
index 81724f4..aa73fea 100644
--- a/ndn-cxx/security/signing-info.cpp
+++ b/ndn-cxx/security/signing-info.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -142,7 +142,7 @@
     transform::base64Decode(false) >>
     transform::streamSink(os);
   m_hmacKey = make_shared<transform::PrivateKey>();
-  m_hmacKey->loadRaw(KeyType::HMAC, os.buf()->data(), os.buf()->size());
+  m_hmacKey->loadRaw(KeyType::HMAC, *os.buf());
 
   // generate key name
   m_name = getHmacIdentity();
diff --git a/ndn-cxx/security/tpm/back-end.cpp b/ndn-cxx/security/tpm/back-end.cpp
index 480ab03..f8f450a 100644
--- a/ndn-cxx/security/tpm/back-end.cpp
+++ b/ndn-cxx/security/tpm/back-end.cpp
@@ -93,12 +93,12 @@
 }
 
 void
-BackEnd::importKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen)
+BackEnd::importKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen)
 {
   if (hasKey(keyName)) {
     NDN_THROW(Error("Key `" + keyName.toUri() + "` already exists"));
   }
-  doImportKey(keyName, pkcs8, pkcs8Len, pw, pwLen);
+  doImportKey(keyName, pkcs8, pw, pwLen);
 }
 
 void
@@ -107,7 +107,7 @@
   if (hasKey(keyName)) {
     NDN_THROW(Error("Key `" + keyName.toUri() + "` already exists"));
   }
-  doImportKey(keyName, key);
+  doImportKey(keyName, std::move(key));
 }
 
 Name
diff --git a/ndn-cxx/security/tpm/back-end.hpp b/ndn-cxx/security/tpm/back-end.hpp
index 057f5f2..41078f2 100644
--- a/ndn-cxx/security/tpm/back-end.hpp
+++ b/ndn-cxx/security/tpm/back-end.hpp
@@ -99,15 +99,14 @@
    * @brief Import a private key in encrypted PKCS #8 format.
    *
    * @param keyName The name of the key to use in the TPM.
-   * @param pkcs8 Pointer to the key in encrypted PKCS #8 format.
-   * @param pkcs8Len The size of the key in encrypted PKCS #8 format.
+   * @param pkcs8 The key in encrypted PKCS #8 format.
    * @param pw The password to decrypt the private key.
    * @param pwLen The length of the password.
    *
    * @throw Error The key could not be imported.
    */
   void
-  importKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen);
+  importKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen);
 
   /**
    * @brief Import a private key.
@@ -191,7 +190,7 @@
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) = 0;
 
   virtual void
-  doImportKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen) = 0;
+  doImportKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen) = 0;
 
   virtual void
   doImportKey(const Name& keyName, shared_ptr<transform::PrivateKey> key) = 0;
diff --git a/ndn-cxx/security/tpm/impl/back-end-file.cpp b/ndn-cxx/security/tpm/impl/back-end-file.cpp
index f31a139..b1914b7 100644
--- a/ndn-cxx/security/tpm/impl/back-end-file.cpp
+++ b/ndn-cxx/security/tpm/impl/back-end-file.cpp
@@ -74,7 +74,7 @@
     std::ostringstream os;
     {
       using namespace transform;
-      bufferSource(keyName.wireEncode().wire(), keyName.wireEncode().size())
+      bufferSource(make_span(keyName.wireEncode().wire(), keyName.wireEncode().size()))
         >> digestFilter(DigestAlgorithm::SHA256)
         >> hexEncode()
         >> streamSink(os);
@@ -183,11 +183,11 @@
 }
 
 void
-BackEndFile::doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen)
+BackEndFile::doImportKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen)
 {
   try {
     PrivateKey key;
-    key.loadPkcs8(buf, size, pw, pwLen);
+    key.loadPkcs8(pkcs8, pw, pwLen);
     saveKey(keyName, key);
   }
   catch (const PrivateKey::Error&) {
diff --git a/ndn-cxx/security/tpm/impl/back-end-file.hpp b/ndn-cxx/security/tpm/impl/back-end-file.hpp
index b41e695..6841681 100644
--- a/ndn-cxx/security/tpm/impl/back-end-file.hpp
+++ b/ndn-cxx/security/tpm/impl/back-end-file.hpp
@@ -72,7 +72,7 @@
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
 
   void
-  doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
+  doImportKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen) final;
 
   void
   doImportKey(const Name& keyName, shared_ptr<transform::PrivateKey> key) final;
diff --git a/ndn-cxx/security/tpm/impl/back-end-mem.cpp b/ndn-cxx/security/tpm/impl/back-end-mem.cpp
index dae98db..094c7af 100644
--- a/ndn-cxx/security/tpm/impl/back-end-mem.cpp
+++ b/ndn-cxx/security/tpm/impl/back-end-mem.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -113,11 +113,11 @@
 }
 
 void
-BackEndMem::doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen)
+BackEndMem::doImportKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen)
 {
   auto key = make_shared<PrivateKey>();
   try {
-    key->loadPkcs8(buf, size, pw, pwLen);
+    key->loadPkcs8(pkcs8, pw, pwLen);
   }
   catch (const PrivateKey::Error&) {
     NDN_THROW_NESTED(Error("Cannot import private key"));
diff --git a/ndn-cxx/security/tpm/impl/back-end-mem.hpp b/ndn-cxx/security/tpm/impl/back-end-mem.hpp
index b210369..176833b 100644
--- a/ndn-cxx/security/tpm/impl/back-end-mem.hpp
+++ b/ndn-cxx/security/tpm/impl/back-end-mem.hpp
@@ -64,7 +64,7 @@
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
 
   void
-  doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
+  doImportKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen) final;
 
   void
   doImportKey(const Name& keyName, shared_ptr<transform::PrivateKey> key) final;
diff --git a/ndn-cxx/security/tpm/impl/back-end-osx.cpp b/ndn-cxx/security/tpm/impl/back-end-osx.cpp
index da318fd..6bdb17e 100644
--- a/ndn-cxx/security/tpm/impl/back-end-osx.cpp
+++ b/ndn-cxx/security/tpm/impl/back-end-osx.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -48,9 +48,9 @@
 };
 
 static CFReleaser<CFDataRef>
-makeCFDataNoCopy(const uint8_t* buf, size_t buflen)
+makeCFDataNoCopy(span<const uint8_t> buf)
 {
-  return CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, buf, buflen, kCFAllocatorNull);
+  return CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, buf.data(), buf.size(), kCFAllocatorNull);
 }
 
 static CFReleaser<CFMutableDictionaryRef>
@@ -181,8 +181,9 @@
     NDN_THROW(Tpm::Error("Failed to export private key: "s + getErrorMessage(res)));
   }
 
-  outKey.loadPkcs8(CFDataGetBytePtr(exportedKey.get()), CFDataGetLength(exportedKey.get()),
-                   pw, std::strlen(pw));
+  auto keyPtr = CFDataGetBytePtr(exportedKey.get());
+  auto keyLen = static_cast<size_t>(CFDataGetLength(exportedKey.get()));
+  outKey.loadPkcs8({keyPtr, keyLen}, pw, std::strlen(pw));
 }
 
 BackEndOsx::BackEndOsx(const std::string&)
@@ -265,7 +266,7 @@
   // Set input
   auto buffer = digestSink.buf();
   BOOST_ASSERT(buffer->size() * 8 == static_cast<size_t>(getDigestSize(digestAlgo)));
-  auto data = makeCFDataNoCopy(buffer->data(), buffer->size());
+  auto data = makeCFDataNoCopy(*buffer);
   SecTransformSetAttribute(signer.get(), kSecTransformInputAttributeName, data.get(), &error.get());
   if (error != nullptr) {
     NDN_THROW(Error("Failed to configure input of sign transform: " + getFailureReason(error.get())));
@@ -308,7 +309,7 @@
 }
 
 ConstBufferPtr
-BackEndOsx::decrypt(const KeyRefOsx& key, const uint8_t* cipherText, size_t cipherSize)
+BackEndOsx::decrypt(const KeyRefOsx& key, span<const uint8_t> cipherText)
 {
   CFReleaser<CFErrorRef> error;
   CFReleaser<SecTransformRef> decryptor = SecDecryptTransformCreate(key.get(), &error.get());
@@ -316,7 +317,7 @@
     NDN_THROW(Error("Failed to create decrypt transform: " + getFailureReason(error.get())));
   }
 
-  auto data = makeCFDataNoCopy(cipherText, cipherSize);
+  auto data = makeCFDataNoCopy(cipherText);
   SecTransformSetAttribute(decryptor.get(), kSecTransformInputAttributeName, data.get(), &error.get());
   if (error != nullptr) {
     NDN_THROW(Error("Failed to configure input of decrypt transform: " + getFailureReason(error.get())));
@@ -455,20 +456,19 @@
 }
 
 void
-BackEndOsx::doImportKey(const Name& keyName, const uint8_t* buf, size_t size,
-                        const char* pw, size_t pwLen)
+BackEndOsx::doImportKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen)
 {
   transform::PrivateKey privKey;
   OBufferStream pkcs1;
   try {
     // do the PKCS8 decoding ourselves, see bug #4450
-    privKey.loadPkcs8(buf, size, pw, pwLen);
+    privKey.loadPkcs8(pkcs8, pw, pwLen);
     privKey.savePkcs1(pkcs1);
   }
   catch (const transform::PrivateKey::Error&) {
     NDN_THROW_NESTED(Error("Failed to import private key"));
   }
-  auto keyToImport = makeCFDataNoCopy(pkcs1.buf()->data(), pkcs1.buf()->size());
+  auto keyToImport = makeCFDataNoCopy(*pkcs1.buf());
 
   SecExternalFormat externalFormat = kSecFormatOpenSSL;
   SecExternalItemType externalType = kSecItemTypePrivateKey;
diff --git a/ndn-cxx/security/tpm/impl/back-end-osx.hpp b/ndn-cxx/security/tpm/impl/back-end-osx.hpp
index a1a1f49..eda536e 100644
--- a/ndn-cxx/security/tpm/impl/back-end-osx.hpp
+++ b/ndn-cxx/security/tpm/impl/back-end-osx.hpp
@@ -77,7 +77,7 @@
    * @brief Decrypt @p cipherText with @p key.
    */
   static ConstBufferPtr
-  decrypt(const KeyRefOsx& key, const uint8_t* cipherText, size_t cipherSize);
+  decrypt(const KeyRefOsx& key, span<const uint8_t> cipherText);
 
   static ConstBufferPtr
   derivePublicKey(const KeyRefOsx& key);
@@ -99,7 +99,7 @@
   doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
 
   void
-  doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen) final;
+  doImportKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen) final;
 
   void
   doImportKey(const Name& keyName, shared_ptr<transform::PrivateKey> key) final;
diff --git a/ndn-cxx/security/tpm/impl/key-handle-mem.cpp b/ndn-cxx/security/tpm/impl/key-handle-mem.cpp
index fcee350..12f6c54 100644
--- a/ndn-cxx/security/tpm/impl/key-handle-mem.cpp
+++ b/ndn-cxx/security/tpm/impl/key-handle-mem.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -39,30 +39,31 @@
 }
 
 ConstBufferPtr
-KeyHandleMem::doSign(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs) const
+KeyHandleMem::doSign(DigestAlgorithm digestAlgo, const InputBuffers& bufs) const
 {
   using namespace transform;
 
   OBufferStream sigOs;
-  bufferSource(bufs) >> signerFilter(digestAlgorithm, *m_key) >> streamSink(sigOs);
+  bufferSource(bufs) >> signerFilter(digestAlgo, *m_key) >> streamSink(sigOs);
   return sigOs.buf();
 }
 
 bool
-KeyHandleMem::doVerify(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs,
-                       const uint8_t* sig, size_t sigLen) const
+KeyHandleMem::doVerify(DigestAlgorithm digestAlgo, const InputBuffers& bufs,
+                       span<const uint8_t> sig) const
 {
   using namespace transform;
 
   bool result = false;
-  bufferSource(bufs) >> verifierFilter(digestAlgorithm, *m_key, sig, sigLen) >> boolSink(result);
+  bufferSource(bufs) >> verifierFilter(digestAlgo, *m_key, sig.data(), sig.size())
+                     >> boolSink(result);
   return result;
 }
 
 ConstBufferPtr
-KeyHandleMem::doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const
+KeyHandleMem::doDecrypt(span<const uint8_t> cipherText) const
 {
-  return m_key->decrypt(cipherText, cipherTextLen);
+  return m_key->decrypt(cipherText);
 }
 
 ConstBufferPtr
diff --git a/ndn-cxx/security/tpm/impl/key-handle-mem.hpp b/ndn-cxx/security/tpm/impl/key-handle-mem.hpp
index b25015e..07516da 100644
--- a/ndn-cxx/security/tpm/impl/key-handle-mem.hpp
+++ b/ndn-cxx/security/tpm/impl/key-handle-mem.hpp
@@ -44,14 +44,13 @@
 
 private:
   ConstBufferPtr
-  doSign(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs) const final;
+  doSign(DigestAlgorithm digestAlgo, const InputBuffers& bufs) const final;
 
   bool
-  doVerify(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs,
-           const uint8_t* sig, size_t sigLen) const final;
+  doVerify(DigestAlgorithm digestAlgo, const InputBuffers& bufs, span<const uint8_t> sig) const final;
 
   ConstBufferPtr
-  doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const final;
+  doDecrypt(span<const uint8_t> cipherText) const final;
 
   ConstBufferPtr
   doDerivePublicKey() const final;
diff --git a/ndn-cxx/security/tpm/impl/key-handle-osx.cpp b/ndn-cxx/security/tpm/impl/key-handle-osx.cpp
index 63d5095..db43fa4 100644
--- a/ndn-cxx/security/tpm/impl/key-handle-osx.cpp
+++ b/ndn-cxx/security/tpm/impl/key-handle-osx.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -40,16 +40,15 @@
 }
 
 bool
-KeyHandleOsx::doVerify(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs,
-                       const uint8_t* sig, size_t sigLen) const
+KeyHandleOsx::doVerify(DigestAlgorithm, const InputBuffers&, span<const uint8_t>) const
 {
   NDN_THROW(Error("Signature verification is not supported with macOS Keychain-based TPM"));
 }
 
 ConstBufferPtr
-KeyHandleOsx::doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const
+KeyHandleOsx::doDecrypt(span<const uint8_t> cipherText) const
 {
-  return BackEndOsx::decrypt(m_key, cipherText, cipherTextLen);
+  return BackEndOsx::decrypt(m_key, cipherText);
 }
 
 ConstBufferPtr
diff --git a/ndn-cxx/security/tpm/impl/key-handle-osx.hpp b/ndn-cxx/security/tpm/impl/key-handle-osx.hpp
index cd1bea4..49bd655 100644
--- a/ndn-cxx/security/tpm/impl/key-handle-osx.hpp
+++ b/ndn-cxx/security/tpm/impl/key-handle-osx.hpp
@@ -49,10 +49,10 @@
 
   bool
   doVerify(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs,
-           const uint8_t* sig, size_t sigLen) const final;
+           span<const uint8_t> sig) const final;
 
   ConstBufferPtr
-  doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const final;
+  doDecrypt(span<const uint8_t> cipherText) const final;
 
   ConstBufferPtr
   doDerivePublicKey() const final;
diff --git a/ndn-cxx/security/tpm/key-handle.cpp b/ndn-cxx/security/tpm/key-handle.cpp
index dc850bb..13af2b0 100644
--- a/ndn-cxx/security/tpm/key-handle.cpp
+++ b/ndn-cxx/security/tpm/key-handle.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -33,30 +33,17 @@
   return doSign(digestAlgorithm, bufs);
 }
 
-ConstBufferPtr
-KeyHandle::sign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const
-{
-  return doSign(digestAlgorithm, {{buf, size}});
-}
-
 bool
 KeyHandle::verify(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs,
-                  const uint8_t* sig, size_t sigLen) const
+                  span<const uint8_t> sig) const
 {
-  return doVerify(digestAlgorithm, bufs, sig, sigLen);
-}
-
-bool
-KeyHandle::verify(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t bufLen,
-                  const uint8_t* sig, size_t sigLen) const
-{
-  return doVerify(digestAlgorithm, {{buf, bufLen}}, sig, sigLen);
+  return doVerify(digestAlgorithm, bufs, sig);
 }
 
 ConstBufferPtr
-KeyHandle::decrypt(const uint8_t* cipherText, size_t cipherTextLen) const
+KeyHandle::decrypt(span<const uint8_t> cipherText) const
 {
-  return doDecrypt(cipherText, cipherTextLen);
+  return doDecrypt(cipherText);
 }
 
 ConstBufferPtr
diff --git a/ndn-cxx/security/tpm/key-handle.hpp b/ndn-cxx/security/tpm/key-handle.hpp
index 962d20d..d718e54 100644
--- a/ndn-cxx/security/tpm/key-handle.hpp
+++ b/ndn-cxx/security/tpm/key-handle.hpp
@@ -54,30 +54,16 @@
   sign(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs) const;
 
   /**
-   * @brief Generate a digital signature for @p buf using this key with @p digestAlgorithm.
-   */
-  ConstBufferPtr
-  sign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const;
-
-  /**
-   * @brief Verify the signature @p sig for @p bufs using this key and @p digestAlgorithm.
+   * @brief Verify the signature @p sig over @p bufs using this key and @p digestAlgorithm.
    */
   bool
-  verify(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs,
-         const uint8_t* sig, size_t sigLen) const;
-
-  /**
-   * @brief Verify the signature @p sig for @p buf using this key and @p digestAlgorithm.
-   */
-  bool
-  verify(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t bufLen,
-         const uint8_t* sig, size_t sigLen) const;
+  verify(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs, span<const uint8_t> sig) const;
 
   /**
    * @brief Return plain text content decrypted from @p cipherText using this key.
    */
   ConstBufferPtr
-  decrypt(const uint8_t* cipherText, size_t cipherTextLen) const;
+  decrypt(span<const uint8_t> cipherText) const;
 
   /**
    * @return the PCKS#8 encoded public key bits derived from this key.
@@ -99,14 +85,13 @@
 
 private:
   virtual ConstBufferPtr
-  doSign(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs) const = 0;
+  doSign(DigestAlgorithm digestAlgo, const InputBuffers& bufs) const = 0;
 
   virtual bool
-  doVerify(DigestAlgorithm digestAlgorithm, const InputBuffers& bufs,
-           const uint8_t* sig, size_t sigLen) const = 0;
+  doVerify(DigestAlgorithm digestAlgo, const InputBuffers& bufs, span<const uint8_t> sig) const = 0;
 
   virtual ConstBufferPtr
-  doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const = 0;
+  doDecrypt(span<const uint8_t> cipherText) const = 0;
 
   virtual ConstBufferPtr
   doDerivePublicKey() const = 0;
diff --git a/ndn-cxx/security/tpm/tpm.cpp b/ndn-cxx/security/tpm/tpm.cpp
index 27a2f05..7966ee0 100644
--- a/ndn-cxx/security/tpm/tpm.cpp
+++ b/ndn-cxx/security/tpm/tpm.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -103,7 +103,7 @@
     return boost::logic::indeterminate;
   }
   else {
-    return key->verify(digestAlgorithm, bufs, sig, sigLen);
+    return key->verify(digestAlgorithm, bufs, {sig, sigLen});
   }
 }
 
@@ -115,7 +115,7 @@
   if (key == nullptr)
     return nullptr;
   else
-    return key->decrypt(buf, size);
+    return key->decrypt({buf, size});
 }
 
 bool
@@ -149,10 +149,9 @@
 }
 
 void
-Tpm::importPrivateKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len,
-                      const char* pw, size_t pwLen)
+Tpm::importPrivateKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen)
 {
-  m_backEnd->importKey(keyName, pkcs8, pkcs8Len, pw, pwLen);
+  m_backEnd->importKey(keyName, pkcs8, pw, pwLen);
 }
 
 void
diff --git a/ndn-cxx/security/tpm/tpm.hpp b/ndn-cxx/security/tpm/tpm.hpp
index d1da79b..b6b02f2 100644
--- a/ndn-cxx/security/tpm/tpm.hpp
+++ b/ndn-cxx/security/tpm/tpm.hpp
@@ -216,6 +216,7 @@
    * @param pw The password to encrypt the private key
    * @param pwLen The length of the password
    * @return The encoded private key wrapper.
+   *
    * @throw Error The key does not exist or it could not be exported.
    */
   ConstBufferPtr
@@ -224,16 +225,17 @@
   /**
    * @brief Import a private key.
    *
-   * @param keyName The private key name
-   * @param pkcs8 The private key wrapper
-   * @param pkcs8Len The length of the private key wrapper
-   * @param pw The password to encrypt the private key
-   * @param pwLen The length of the password
+   * Import a private key in encrypted PKCS #8 format.
+   *
+   * @param keyName The private key name.
+   * @param pkcs8 The key encoded in PKCS #8 format.
+   * @param pw The password to decrypt the private key.
+   * @param pwLen The length of the password.
+   *
    * @throw Error The key could not be imported.
    */
   void
-  importPrivateKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len,
-                   const char* pw, size_t pwLen);
+  importPrivateKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen);
 
   /**
    * @brief Import a private key.
diff --git a/ndn-cxx/security/transform/base64-decode.cpp b/ndn-cxx/security/transform/base64-decode.cpp
index 5b4de25..7b731a0 100644
--- a/ndn-cxx/security/transform/base64-decode.cpp
+++ b/ndn-cxx/security/transform/base64-decode.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -26,11 +26,7 @@
 namespace security {
 namespace transform {
 
-/**
- * @brief The implementation class which contains the internal state of the filter
- *        which includes openssl specific structures.
- */
-class Base64Decode::Impl
+class Base64Decode::Impl : boost::noncopyable
 {
 public:
   Impl()
@@ -55,7 +51,6 @@
   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(make_unique<Impl>())
@@ -79,9 +74,9 @@
 }
 
 size_t
-Base64Decode::convert(const uint8_t* buf, size_t size)
+Base64Decode::convert(span<const uint8_t> buf)
 {
-  int wLen = BIO_write(m_impl->m_source, buf, size);
+  int wLen = BIO_write(m_impl->m_source, buf.data(), buf.size());
 
   if (wLen <= 0) { // fail to write data
     if (!BIO_should_retry(m_impl->m_source)) {
@@ -114,7 +109,7 @@
 {
   // 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);
+  auto buffer = make_unique<OBuffer>(1024);
   int rLen = BIO_read(m_impl->m_base64, buffer->data(), buffer->size());
   if (rLen <= 0)
     return;
diff --git a/ndn-cxx/security/transform/base64-decode.hpp b/ndn-cxx/security/transform/base64-decode.hpp
index b7fdbe3..38949d3 100644
--- a/ndn-cxx/security/transform/base64-decode.hpp
+++ b/ndn-cxx/security/transform/base64-decode.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -31,20 +31,20 @@
 /**
  * @brief The module to perform Base64 decoding transformation.
  */
-class Base64Decode : public Transform
+class Base64Decode final : 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.
+   * @param 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);
 
-  ~Base64Decode();
+  ~Base64Decode() final;
 
 private:
   /**
@@ -54,12 +54,11 @@
   preTransform() final;
 
   /**
-   * @brief Decode data @p buf in base64 format
-   *
-   * @return number of bytes that have been accepted by the converter
+   * @brief Decode @p buf from base64 format.
+   * @return The number of bytes that have been accepted by the converter.
    */
   size_t
-  convert(const uint8_t* buf, size_t size) final;
+  convert(span<const uint8_t> buf) final;
 
   /**
    * @brief Finalize base64 decoding
diff --git a/ndn-cxx/security/transform/base64-encode.cpp b/ndn-cxx/security/transform/base64-encode.cpp
index f581300..51f5e50 100644
--- a/ndn-cxx/security/transform/base64-encode.cpp
+++ b/ndn-cxx/security/transform/base64-encode.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -26,11 +26,7 @@
 namespace security {
 namespace transform {
 
-/**
- * @brief The implementation class which contains the internal state of the filter
- *        which includes openssl specific structures.
- */
-class Base64Encode::Impl
+class Base64Encode::Impl : boost::noncopyable
 {
 public:
   Impl()
@@ -51,6 +47,7 @@
   BIO* m_sink; // BIO_f_base64 alone does not work without a sink
 };
 
+
 Base64Encode::Base64Encode(bool needBreak)
   : m_impl(make_unique<Impl>())
 {
@@ -67,12 +64,12 @@
 }
 
 size_t
-Base64Encode::convert(const uint8_t* data, size_t dataLen)
+Base64Encode::convert(span<const uint8_t> data)
 {
-  if (dataLen == 0)
+  if (data.empty())
     return 0;
 
-  int wLen = BIO_write(m_impl->m_base64, data, dataLen);
+  int wLen = BIO_write(m_impl->m_base64, data.data(), data.size());
 
   if (wLen <= 0) { // fail to write data
     if (!BIO_should_retry(m_impl->m_base64)) {
@@ -116,13 +113,14 @@
 
   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);
+  return BIO_pending(m_impl->m_sink) <= 0;
 }
 
 unique_ptr<Transform>
diff --git a/ndn-cxx/security/transform/base64-encode.hpp b/ndn-cxx/security/transform/base64-encode.hpp
index 145d36c..1c09376 100644
--- a/ndn-cxx/security/transform/base64-encode.hpp
+++ b/ndn-cxx/security/transform/base64-encode.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -31,18 +31,18 @@
 /**
  * @brief The module to perform Base64 encoding transformation.
  */
-class Base64Encode : public Transform
+class Base64Encode final : public Transform
 {
 public:
   /**
    * @brief Create a base64 encoding module
    *
-   * @p needBreak if true, insert newline after every 64 bytes, otherwise no newline is inserted
+   * @param needBreak if true, insert newline after every 64 bytes, otherwise no newline is inserted
    */
   explicit
   Base64Encode(bool needBreak = true);
 
-  ~Base64Encode();
+  ~Base64Encode() final;
 
 private:
   /**
@@ -56,7 +56,7 @@
    * @return The number of input bytes that have been accepted by the converter.
    */
   size_t
-  convert(const uint8_t* data, size_t dataLen) final;
+  convert(span<const uint8_t> data) final;
 
   /**
    * @brief Finalize base64 encoding
diff --git a/ndn-cxx/security/transform/block-cipher.cpp b/ndn-cxx/security/transform/block-cipher.cpp
index 985720e..ec3be08 100644
--- a/ndn-cxx/security/transform/block-cipher.cpp
+++ b/ndn-cxx/security/transform/block-cipher.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 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 security {
 namespace transform {
 
-class BlockCipher::Impl
+class BlockCipher::Impl : boost::noncopyable
 {
 public:
   Impl() noexcept
@@ -73,12 +73,12 @@
 }
 
 size_t
-BlockCipher::convert(const uint8_t* data, size_t dataLen)
+BlockCipher::convert(span<const uint8_t> data)
 {
-  if (dataLen == 0)
+  if (data.empty())
     return 0;
 
-  int wLen = BIO_write(m_impl->m_cipher, data, dataLen);
+  int wLen = BIO_write(m_impl->m_cipher, data.data(), data.size());
 
   if (wLen <= 0) { // failed to write data
     if (!BIO_should_retry(m_impl->m_cipher)) {
diff --git a/ndn-cxx/security/transform/block-cipher.hpp b/ndn-cxx/security/transform/block-cipher.hpp
index 3ea5ba5..9834f47 100644
--- a/ndn-cxx/security/transform/block-cipher.hpp
+++ b/ndn-cxx/security/transform/block-cipher.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -35,7 +35,7 @@
  * The padding scheme of the block cipher is set to the OpenSSL default,
  * which is PKCS padding.
  */
-class BlockCipher : public Transform
+class BlockCipher final : public Transform
 {
 public:
   /**
@@ -52,25 +52,25 @@
               const uint8_t* key, size_t keyLen,
               const uint8_t* iv, size_t ivLen);
 
-  ~BlockCipher();
+  ~BlockCipher() final;
 
 private:
   /**
-   * @brief Read partial transformation result (if exists) from BIO
+   * @brief Read partial transformation result (if exists) from BIO.
    */
   void
   preTransform() final;
 
   /**
-   * @brief Write @p data into the cipher
+   * @brief Write @p data into the cipher.
    *
-   * @return number of bytes that are actually accepted
+   * @return Number of bytes that are actually accepted.
    */
   size_t
-  convert(const uint8_t* data, size_t dataLen) final;
+  convert(span<const uint8_t> data) final;
 
   /**
-   * @brief Finalize the encryption
+   * @brief Finalize the encryption.
    */
   void
   finalize() final;
diff --git a/ndn-cxx/security/transform/bool-sink.cpp b/ndn-cxx/security/transform/bool-sink.cpp
index 0c702e7..c57cf77 100644
--- a/ndn-cxx/security/transform/bool-sink.cpp
+++ b/ndn-cxx/security/transform/bool-sink.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -32,13 +32,13 @@
 }
 
 size_t
-BoolSink::doWrite(const uint8_t* buf, size_t size)
+BoolSink::doWrite(span<const uint8_t> buf)
 {
-  if (!m_hasValue && size > 0) {
-    m_value = (buf[0] != 0);
+  if (!m_hasValue && !buf.empty()) {
+    m_value = (buf.front() != 0);
     m_hasValue = true;
   }
-  return size;
+  return buf.size();
 }
 
 void
diff --git a/ndn-cxx/security/transform/bool-sink.hpp b/ndn-cxx/security/transform/bool-sink.hpp
index c270543..827019a 100644
--- a/ndn-cxx/security/transform/bool-sink.hpp
+++ b/ndn-cxx/security/transform/bool-sink.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -50,7 +50,7 @@
    * @return the same value as @p size.
    */
   size_t
-  doWrite(const uint8_t* buf, size_t size) final;
+  doWrite(span<const uint8_t> buf) final;
 
   /**
    * @brief Finalize sink processing
diff --git a/ndn-cxx/security/transform/buffer-source.cpp b/ndn-cxx/security/transform/buffer-source.cpp
index 36f5d2d..515964f 100644
--- a/ndn-cxx/security/transform/buffer-source.cpp
+++ b/ndn-cxx/security/transform/buffer-source.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -25,8 +25,13 @@
 namespace security {
 namespace transform {
 
+BufferSource::BufferSource(span<const uint8_t> buffer)
+  : m_bufs({buffer})
+{
+}
+
 BufferSource::BufferSource(const uint8_t* buf, size_t size)
-  : m_bufs({{buf, size}})
+  : BufferSource(make_span(buf, size))
 {
 }
 
@@ -35,11 +40,6 @@
 {
 }
 
-BufferSource::BufferSource(const Buffer& buffer)
-  : m_bufs({{buffer.data(), buffer.size()}})
-{
-}
-
 BufferSource::BufferSource(InputBuffers buffers)
   : m_bufs(std::move(buffers))
 {
@@ -50,14 +50,10 @@
 {
   BOOST_ASSERT(m_next != nullptr);
 
-  for (const auto& buffer : m_bufs) {
-    const uint8_t* buf = buffer.first;
-    size_t size = buffer.second;
-
-    while (size > 0) {
-      size_t nBytesWritten = m_next->write(buf, size);
-      buf += nBytesWritten;
-      size -= nBytesWritten;
+  for (auto buffer : m_bufs) {
+    while (!buffer.empty()) {
+      size_t nBytesWritten = m_next->write(buffer);
+      buffer = buffer.last(buffer.size() - nBytesWritten);
     }
   }
 
diff --git a/ndn-cxx/security/transform/buffer-source.hpp b/ndn-cxx/security/transform/buffer-source.hpp
index 4b4ab44..43069a0 100644
--- a/ndn-cxx/security/transform/buffer-source.hpp
+++ b/ndn-cxx/security/transform/buffer-source.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -37,10 +37,20 @@
 {
 public:
   /**
-   * @brief Take a buffer @p buf with size @p size as input.
+   * @brief Take @p buffer as input.
    *
    * Caller must not destroy the buffer before the transformation is completed.
    */
+  explicit
+  BufferSource(span<const uint8_t> buffer);
+
+  /**
+   * @brief Take a buffer @p buf with size @p size as input.
+   * @deprecated Use BufferSource(span<const uint8_t>)
+   *
+   * Caller must not destroy the buffer before the transformation is completed.
+   */
+  [[deprecated("use the constructor taking a span<>")]]
   BufferSource(const uint8_t* buf, size_t size);
 
   /**
@@ -52,14 +62,6 @@
   BufferSource(const std::string& string);
 
   /**
-   * @brief Take @p buffer as input.
-   *
-   * Caller must not destroy the buffer before the transformation is completed.
-   */
-  explicit
-  BufferSource(const Buffer& buffer);
-
-  /**
    * @brief Take @p buffers as input.
    *
    * Caller must not destroy any of the input buffers before the transformation is completed.
@@ -78,7 +80,7 @@
   InputBuffers m_bufs;
 };
 
-typedef BufferSource bufferSource;
+using bufferSource = BufferSource;
 
 } // namespace transform
 } // namespace security
diff --git a/ndn-cxx/security/transform/digest-filter.cpp b/ndn-cxx/security/transform/digest-filter.cpp
index 2293739..6462075 100644
--- a/ndn-cxx/security/transform/digest-filter.cpp
+++ b/ndn-cxx/security/transform/digest-filter.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -49,12 +49,12 @@
 DigestFilter::~DigestFilter() = default;
 
 size_t
-DigestFilter::convert(const uint8_t* buf, size_t size)
+DigestFilter::convert(span<const uint8_t> buf)
 {
-  if (EVP_DigestUpdate(m_impl->ctx, buf, size) == 0)
+  if (EVP_DigestUpdate(m_impl->ctx, buf.data(), buf.size()) == 0)
     NDN_THROW(Error(getIndex(), "Failed to accept more input"));
 
-  return size;
+  return buf.size();
 }
 
 void
diff --git a/ndn-cxx/security/transform/digest-filter.hpp b/ndn-cxx/security/transform/digest-filter.hpp
index 4a26bf0..30f96ec 100644
--- a/ndn-cxx/security/transform/digest-filter.hpp
+++ b/ndn-cxx/security/transform/digest-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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -30,9 +30,9 @@
 namespace transform {
 
 /**
- * @brief The module to calculate digest.
+ * @brief The module to calculate digests.
  */
-class DigestFilter : public Transform
+class DigestFilter final : public Transform
 {
 public:
   /**
@@ -41,7 +41,7 @@
   explicit
   DigestFilter(DigestAlgorithm algo);
 
-  ~DigestFilter();
+  ~DigestFilter() final;
 
 private:
   /**
@@ -50,7 +50,7 @@
    * @return The number of bytes that have been accepted
    */
   size_t
-  convert(const uint8_t* buf, size_t size) final;
+  convert(span<const uint8_t> buf) final;
 
   /**
    * @brief Finalize digest calculation and write the digest into next module.
diff --git a/ndn-cxx/security/transform/hex-decode.cpp b/ndn-cxx/security/transform/hex-decode.cpp
index 9a91ee6..d46c301 100644
--- a/ndn-cxx/security/transform/hex-decode.cpp
+++ b/ndn-cxx/security/transform/hex-decode.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -55,22 +55,23 @@
 }
 
 size_t
-HexDecode::convert(const uint8_t* hex, size_t hexLen)
+HexDecode::convert(span<const uint8_t> hex)
 {
-  if (hexLen == 0)
+  if (hex.empty())
     return 0;
 
-  setOutputBuffer(toBytes(hex, hexLen));
+  setOutputBuffer(toBytes(hex.data(), hex.size()));
 
-  size_t totalDecodedLen = hexLen + (m_hasOddByte ? 1 : 0);
+  size_t totalDecodedLen = hex.size() + (m_hasOddByte ? 1 : 0);
   if (totalDecodedLen % 2 == 1) {
-    m_oddByte = hex[hexLen - 1];
+    m_oddByte = hex.back();
     m_hasOddByte = true;
   }
-  else
+  else {
     m_hasOddByte = false;
+  }
 
-  return hexLen;
+  return hex.size();
 }
 
 void
diff --git a/ndn-cxx/security/transform/hex-decode.hpp b/ndn-cxx/security/transform/hex-decode.hpp
index d57be64..43c7e71 100644
--- a/ndn-cxx/security/transform/hex-decode.hpp
+++ b/ndn-cxx/security/transform/hex-decode.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -36,7 +36,7 @@
  *
  * If the total length of input is not even (2n + 1), the module will throw Error.
  */
-class HexDecode : public Transform
+class HexDecode final : public Transform
 {
 public:
   /**
@@ -48,10 +48,10 @@
   /**
    * @brief Decode data @p buf, and write the result into output buffer directly.
    *
-   * @return number of input bytes that are accepted
+   * @return Number of input bytes that are accepted.
    */
   size_t
-  convert(const uint8_t* buf, size_t size) final;
+  convert(span<const uint8_t> hex) final;
 
   /**
    * @throws Error if pending byte exists.
diff --git a/ndn-cxx/security/transform/hex-encode.cpp b/ndn-cxx/security/transform/hex-encode.cpp
index 219e14e..865bb6b 100644
--- a/ndn-cxx/security/transform/hex-encode.cpp
+++ b/ndn-cxx/security/transform/hex-encode.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -44,10 +44,10 @@
 }
 
 size_t
-HexEncode::convert(const uint8_t* data, size_t dataLen)
+HexEncode::convert(span<const uint8_t> data)
 {
-  setOutputBuffer(toHex(data, dataLen));
-  return dataLen;
+  setOutputBuffer(toHex(data.data(), data.size()));
+  return data.size();
 }
 
 unique_ptr<Transform::OBuffer>
diff --git a/ndn-cxx/security/transform/hex-encode.hpp b/ndn-cxx/security/transform/hex-encode.hpp
index a395616..71031e8 100644
--- a/ndn-cxx/security/transform/hex-encode.hpp
+++ b/ndn-cxx/security/transform/hex-encode.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -34,7 +34,7 @@
  * For example, if the input is a byte stream 0x01, 0x23, 0x45,
  * the output will be a string "012345".
  */
-class HexEncode : public Transform
+class HexEncode final : public Transform
 {
 public:
   /**
@@ -52,7 +52,7 @@
    * @return The number of input bytes that have been accepted by the converter.
    */
   size_t
-  convert(const uint8_t* data, size_t dataLen) final;
+  convert(span<const uint8_t> data) final;
 
   /**
    * @return results of encoding @p data
diff --git a/ndn-cxx/security/transform/private-key.cpp b/ndn-cxx/security/transform/private-key.cpp
index 242bcba..d0300a1 100644
--- a/ndn-cxx/security/transform/private-key.cpp
+++ b/ndn-cxx/security/transform/private-key.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -147,12 +147,12 @@
     NDN_THROW(Error("Key length mismatch"));
 
   OBufferStream os;
-  bufferSource(buf, len) >> digestFilter(algo) >> streamSink(os);
+  bufferSource(make_span(buf, len)) >> digestFilter(algo) >> streamSink(os);
   return os.buf();
 }
 
 void
-PrivateKey::loadRaw(KeyType type, const uint8_t* buf, size_t size)
+PrivateKey::loadRaw(KeyType type, span<const uint8_t> buf)
 {
   ENSURE_PRIVATE_KEY_NOT_LOADED(m_impl->key);
 
@@ -167,9 +167,9 @@
 
   m_impl->key =
 #if OPENSSL_VERSION_NUMBER >= 0x1010100fL
-      EVP_PKEY_new_raw_private_key(pkeyType, nullptr, buf, size);
+      EVP_PKEY_new_raw_private_key(pkeyType, nullptr, buf.data(), buf.size());
 #else
-      EVP_PKEY_new_mac_key(pkeyType, nullptr, buf, static_cast<int>(size));
+      EVP_PKEY_new_mac_key(pkeyType, nullptr, buf.data(), static_cast<int>(buf.size()));
 #endif
   if (m_impl->key == nullptr)
     NDN_THROW(Error("Failed to load private key"));
@@ -180,12 +180,13 @@
 }
 
 void
-PrivateKey::loadPkcs1(const uint8_t* buf, size_t size)
+PrivateKey::loadPkcs1(span<const uint8_t> buf)
 {
   ENSURE_PRIVATE_KEY_NOT_LOADED(m_impl->key);
   opensslInitAlgorithms();
 
-  if (d2i_AutoPrivateKey(&m_impl->key, &buf, static_cast<long>(size)) == nullptr)
+  auto ptr = buf.data();
+  if (d2i_AutoPrivateKey(&m_impl->key, &ptr, static_cast<long>(buf.size())) == nullptr)
     NDN_THROW(Error("Failed to load private key"));
 }
 
@@ -194,15 +195,15 @@
 {
   OBufferStream os;
   streamSource(is) >> streamSink(os);
-  this->loadPkcs1(os.buf()->data(), os.buf()->size());
+  loadPkcs1(*os.buf());
 }
 
 void
-PrivateKey::loadPkcs1Base64(const uint8_t* buf, size_t size)
+PrivateKey::loadPkcs1Base64(span<const uint8_t> buf)
 {
   OBufferStream os;
-  bufferSource(buf, size) >> base64Decode() >> streamSink(os);
-  this->loadPkcs1(os.buf()->data(), os.buf()->size());
+  bufferSource(buf) >> base64Decode() >> streamSink(os);
+  loadPkcs1(*os.buf());
 }
 
 void
@@ -210,18 +211,18 @@
 {
   OBufferStream os;
   streamSource(is) >> base64Decode() >> streamSink(os);
-  this->loadPkcs1(os.buf()->data(), os.buf()->size());
+  loadPkcs1(*os.buf());
 }
 
 void
-PrivateKey::loadPkcs8(const uint8_t* buf, size_t size, const char* pw, size_t pwLen)
+PrivateKey::loadPkcs8(span<const uint8_t> buf, const char* pw, size_t pwLen)
 {
   BOOST_ASSERT(std::strlen(pw) == pwLen);
   ENSURE_PRIVATE_KEY_NOT_LOADED(m_impl->key);
   opensslInitAlgorithms();
 
   detail::Bio membio(BIO_s_mem());
-  if (!membio.write(buf, size))
+  if (!membio.write(buf))
     NDN_THROW(Error("Failed to copy buffer"));
 
   if (d2i_PKCS8PrivateKey_bio(membio, &m_impl->key, nullptr, const_cast<char*>(pw)) == nullptr)
@@ -237,13 +238,13 @@
 }
 
 void
-PrivateKey::loadPkcs8(const uint8_t* buf, size_t size, PasswordCallback pwCallback)
+PrivateKey::loadPkcs8(span<const uint8_t> buf, PasswordCallback pwCallback)
 {
   ENSURE_PRIVATE_KEY_NOT_LOADED(m_impl->key);
   opensslInitAlgorithms();
 
   detail::Bio membio(BIO_s_mem());
-  if (!membio.write(buf, size))
+  if (!membio.write(buf))
     NDN_THROW(Error("Failed to copy buffer"));
 
   if (pwCallback)
@@ -260,7 +261,7 @@
 {
   OBufferStream os;
   streamSource(is) >> streamSink(os);
-  this->loadPkcs8(os.buf()->data(), os.buf()->size(), pw, pwLen);
+  loadPkcs8(*os.buf(), pw, pwLen);
 }
 
 void
@@ -268,23 +269,23 @@
 {
   OBufferStream os;
   streamSource(is) >> streamSink(os);
-  this->loadPkcs8(os.buf()->data(), os.buf()->size(), pwCallback);
+  loadPkcs8(*os.buf(), std::move(pwCallback));
 }
 
 void
-PrivateKey::loadPkcs8Base64(const uint8_t* buf, size_t size, const char* pw, size_t pwLen)
+PrivateKey::loadPkcs8Base64(span<const uint8_t> buf, const char* pw, size_t pwLen)
 {
   OBufferStream os;
-  bufferSource(buf, size) >> base64Decode() >> streamSink(os);
-  this->loadPkcs8(os.buf()->data(), os.buf()->size(), pw, pwLen);
+  bufferSource(buf) >> base64Decode() >> streamSink(os);
+  loadPkcs8(*os.buf(), pw, pwLen);
 }
 
 void
-PrivateKey::loadPkcs8Base64(const uint8_t* buf, size_t size, PasswordCallback pwCallback)
+PrivateKey::loadPkcs8Base64(span<const uint8_t> buf, PasswordCallback pwCallback)
 {
   OBufferStream os;
-  bufferSource(buf, size) >> base64Decode() >> streamSink(os);
-  this->loadPkcs8(os.buf()->data(), os.buf()->size(), pwCallback);
+  bufferSource(buf) >> base64Decode() >> streamSink(os);
+  loadPkcs8(*os.buf(), std::move(pwCallback));
 }
 
 void
@@ -292,7 +293,7 @@
 {
   OBufferStream os;
   streamSource(is) >> base64Decode() >> streamSink(os);
-  this->loadPkcs8(os.buf()->data(), os.buf()->size(), pw, pwLen);
+  loadPkcs8(*os.buf(), pw, pwLen);
 }
 
 void
@@ -300,43 +301,43 @@
 {
   OBufferStream os;
   streamSource(is) >> base64Decode() >> streamSink(os);
-  this->loadPkcs8(os.buf()->data(), os.buf()->size(), pwCallback);
+  loadPkcs8(*os.buf(), std::move(pwCallback));
 }
 
 void
 PrivateKey::savePkcs1(std::ostream& os) const
 {
-  bufferSource(*this->toPkcs1()) >> streamSink(os);
+  bufferSource(*toPkcs1()) >> streamSink(os);
 }
 
 void
 PrivateKey::savePkcs1Base64(std::ostream& os) const
 {
-  bufferSource(*this->toPkcs1()) >> base64Encode() >> streamSink(os);
+  bufferSource(*toPkcs1()) >> base64Encode() >> streamSink(os);
 }
 
 void
 PrivateKey::savePkcs8(std::ostream& os, const char* pw, size_t pwLen) const
 {
-  bufferSource(*this->toPkcs8(pw, pwLen)) >> streamSink(os);
+  bufferSource(*toPkcs8(pw, pwLen)) >> streamSink(os);
 }
 
 void
 PrivateKey::savePkcs8(std::ostream& os, PasswordCallback pwCallback) const
 {
-  bufferSource(*this->toPkcs8(pwCallback)) >> streamSink(os);
+  bufferSource(*toPkcs8(std::move(pwCallback))) >> streamSink(os);
 }
 
 void
 PrivateKey::savePkcs8Base64(std::ostream& os, const char* pw, size_t pwLen) const
 {
-  bufferSource(*this->toPkcs8(pw, pwLen)) >> base64Encode() >> streamSink(os);
+  bufferSource(*toPkcs8(pw, pwLen)) >> base64Encode() >> streamSink(os);
 }
 
 void
 PrivateKey::savePkcs8Base64(std::ostream& os, PasswordCallback pwCallback) const
 {
-  bufferSource(*this->toPkcs8(pwCallback)) >> base64Encode() >> streamSink(os);
+  bufferSource(*toPkcs8(std::move(pwCallback))) >> base64Encode() >> streamSink(os);
 }
 
 ConstBufferPtr
@@ -356,7 +357,7 @@
 }
 
 ConstBufferPtr
-PrivateKey::decrypt(const uint8_t* cipherText, size_t cipherLen) const
+PrivateKey::decrypt(span<const uint8_t> cipherText) const
 {
   ENSURE_PRIVATE_KEY_LOADED(m_impl->key);
 
@@ -365,7 +366,7 @@
     case EVP_PKEY_NONE:
       NDN_THROW(Error("Failed to determine key type"));
     case EVP_PKEY_RSA:
-      return rsaDecrypt(cipherText, cipherLen);
+      return rsaDecrypt(cipherText);
     default:
       NDN_THROW(Error("Decryption is not supported for key type " + to_string(keyType)));
   }
@@ -388,7 +389,7 @@
     NDN_THROW(Error("Cannot convert key to PKCS #1 format"));
 
   auto buffer = make_shared<Buffer>(BIO_pending(membio));
-  if (!membio.read(buffer->data(), buffer->size()))
+  if (!membio.read(*buffer))
     NDN_THROW(Error("Read error during PKCS #1 conversion"));
 
   return buffer;
@@ -407,7 +408,7 @@
     NDN_THROW(Error("Cannot convert key to PKCS #8 format"));
 
   auto buffer = make_shared<Buffer>(BIO_pending(membio));
-  if (!membio.read(buffer->data(), buffer->size()))
+  if (!membio.read(*buffer))
     NDN_THROW(Error("Read error during PKCS #8 conversion"));
 
   return buffer;
@@ -425,14 +426,14 @@
     NDN_THROW(Error("Cannot convert key to PKCS #8 format"));
 
   auto buffer = make_shared<Buffer>(BIO_pending(membio));
-  if (!membio.read(buffer->data(), buffer->size()))
+  if (!membio.read(*buffer))
     NDN_THROW(Error("Read error during PKCS #8 conversion"));
 
   return buffer;
 }
 
 ConstBufferPtr
-PrivateKey::rsaDecrypt(const uint8_t* cipherText, size_t cipherLen) const
+PrivateKey::rsaDecrypt(span<const uint8_t> cipherText) const
 {
   detail::EvpPkeyCtx ctx(m_impl->key);
 
@@ -444,11 +445,11 @@
 
   size_t outlen = 0;
   // Determine buffer length
-  if (EVP_PKEY_decrypt(ctx, nullptr, &outlen, cipherText, cipherLen) <= 0)
+  if (EVP_PKEY_decrypt(ctx, nullptr, &outlen, cipherText.data(), cipherText.size()) <= 0)
     NDN_THROW(Error("Failed to estimate output length"));
 
   auto out = make_shared<Buffer>(outlen);
-  if (EVP_PKEY_decrypt(ctx, out->data(), &outlen, cipherText, cipherLen) <= 0)
+  if (EVP_PKEY_decrypt(ctx, out->data(), &outlen, cipherText.data(), cipherText.size()) <= 0)
     NDN_THROW(Error("Failed to decrypt ciphertext"));
 
   out->resize(outlen);
@@ -521,11 +522,11 @@
 PrivateKey::generateHmacKey(uint32_t keySize)
 {
   std::vector<uint8_t> rawKey(keySize / 8);
-  random::generateSecureBytes(rawKey.data(), rawKey.size());
+  random::generateSecureBytes(rawKey);
 
   auto privateKey = make_unique<PrivateKey>();
   try {
-    privateKey->loadRaw(KeyType::HMAC, rawKey.data(), rawKey.size());
+    privateKey->loadRaw(KeyType::HMAC, rawKey);
   }
   catch (const PrivateKey::Error&) {
     NDN_THROW(PrivateKey::Error("Failed to generate HMAC key"));
@@ -539,15 +540,15 @@
 {
   switch (keyParams.getKeyType()) {
     case KeyType::RSA: {
-      const RsaKeyParams& rsaParams = static_cast<const RsaKeyParams&>(keyParams);
+      const auto& rsaParams = static_cast<const RsaKeyParams&>(keyParams);
       return PrivateKey::generateRsaKey(rsaParams.getKeySize());
     }
     case KeyType::EC: {
-      const EcKeyParams& ecParams = static_cast<const EcKeyParams&>(keyParams);
+      const auto& ecParams = static_cast<const EcKeyParams&>(keyParams);
       return PrivateKey::generateEcKey(ecParams.getKeySize());
     }
     case KeyType::HMAC: {
-      const HmacKeyParams& hmacParams = static_cast<const HmacKeyParams&>(keyParams);
+      const auto& hmacParams = static_cast<const HmacKeyParams&>(keyParams);
       return PrivateKey::generateHmacKey(hmacParams.getKeySize());
     }
     default:
diff --git a/ndn-cxx/security/transform/private-key.hpp b/ndn-cxx/security/transform/private-key.hpp
index 85051f3..a435bea 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-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -52,7 +52,7 @@
    * e.g., by prompting for it twice. The callback must return the number of characters
    * in the password or 0 if an error occurred.
    */
-  typedef function<int(char* buf, size_t bufSize, bool shouldConfirm)> PasswordCallback;
+  using PasswordCallback = std::function<int(char* buf, size_t bufSize, bool shouldConfirm)>;
 
 public:
   /**
@@ -90,13 +90,37 @@
    * @note Currently supports only HMAC keys.
    */
   void
-  loadRaw(KeyType type, const uint8_t* buf, size_t size);
+  loadRaw(KeyType type, span<const uint8_t> buf);
+
+  /**
+   * @brief Load a raw private key from a buffer @p buf
+   * @deprecated
+   *
+   * @note Currently supports only HMAC keys.
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  void
+  loadRaw(KeyType type, const uint8_t* buf, size_t size)
+  {
+    loadRaw(type, {buf, size});
+  }
 
   /**
    * @brief Load the private key in PKCS#1 format from a buffer @p buf
    */
   void
-  loadPkcs1(const uint8_t* buf, size_t size);
+  loadPkcs1(span<const uint8_t> buf);
+
+  /**
+   * @brief Load the private key in PKCS#1 format from a buffer @p buf
+   * @deprecated
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  void
+  loadPkcs1(const uint8_t* buf, size_t size)
+  {
+    loadPkcs1({buf, size});
+  }
 
   /**
    * @brief Load the private key in PKCS#1 format from a stream @p is
@@ -108,7 +132,18 @@
    * @brief Load the private key in base64-encoded PKCS#1 format from a buffer @p buf
    */
   void
-  loadPkcs1Base64(const uint8_t* buf, size_t size);
+  loadPkcs1Base64(span<const uint8_t> buf);
+
+  /**
+   * @brief Load the private key in base64-encoded PKCS#1 format from a buffer @p buf
+   * @deprecated
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  void
+  loadPkcs1Base64(const uint8_t* buf, size_t size)
+  {
+    loadPkcs1Base64({buf, size});
+  }
 
   /**
    * @brief Load the private key in base64-encoded PKCS#1 format from a stream @p is
@@ -121,7 +156,7 @@
    * @pre strlen(pw) == pwLen
    */
   void
-  loadPkcs8(const uint8_t* buf, size_t size, const char* pw, size_t pwLen);
+  loadPkcs8(span<const uint8_t> buf, const char* pw, size_t pwLen);
 
   /**
    * @brief Load the private key in encrypted PKCS#8 format from a buffer @p buf with
@@ -130,7 +165,21 @@
    * The default password callback is provided by OpenSSL
    */
   void
-  loadPkcs8(const uint8_t* buf, size_t size, PasswordCallback pwCallback = nullptr);
+  loadPkcs8(span<const uint8_t> buf, PasswordCallback pwCallback = nullptr);
+
+  /**
+   * @brief Load the private key in encrypted PKCS#8 format from a buffer @p buf with
+   *        passphrase obtained from @p pwCallback
+   * @deprecated
+   *
+   * The default password callback is provided by OpenSSL
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  void
+  loadPkcs8(const uint8_t* buf, size_t size, PasswordCallback pwCallback = nullptr)
+  {
+    loadPkcs8({buf, size}, std::move(pwCallback));
+  }
 
   /**
    * @brief Load the private key in encrypted PKCS#8 format from a stream @p is with passphrase @p pw
@@ -154,7 +203,7 @@
    * @pre strlen(pw) == pwLen
    */
   void
-  loadPkcs8Base64(const uint8_t* buf, size_t size, const char* pw, size_t pwLen);
+  loadPkcs8Base64(span<const uint8_t> buf, const char* pw, size_t pwLen);
 
   /**
    * @brief Load the private key in encrypted PKCS#8 format from a buffer @p buf with
@@ -163,7 +212,21 @@
    * The default password callback is provided by OpenSSL
    */
   void
-  loadPkcs8Base64(const uint8_t* buf, size_t size, PasswordCallback pwCallback = nullptr);
+  loadPkcs8Base64(span<const uint8_t> buf, PasswordCallback pwCallback = nullptr);
+
+  /**
+   * @brief Load the private key in encrypted PKCS#8 format from a buffer @p buf with
+   *        passphrase obtained from @p pwCallback
+   * @deprecated
+   *
+   * The default password callback is provided by OpenSSL
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  void
+  loadPkcs8Base64(const uint8_t* buf, size_t size, PasswordCallback pwCallback = nullptr)
+  {
+    loadPkcs8Base64({buf, size}, std::move(pwCallback));
+  }
 
   /**
    * @brief Load the private key in base64-encoded encrypted PKCS#8 format from a stream @p is
@@ -236,7 +299,20 @@
    * Only RSA encryption is supported for now.
    */
   ConstBufferPtr
-  decrypt(const uint8_t* cipherText, size_t cipherLen) const;
+  decrypt(span<const uint8_t> cipherText) const;
+
+  /**
+   * @return Plain text of @p cipherText decrypted using this private key.
+   * @deprecated
+   *
+   * Only RSA encryption is supported for now.
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  ConstBufferPtr
+  decrypt(const uint8_t* cipherText, size_t cipherLen) const
+  {
+    return decrypt({cipherText, cipherLen});
+  }
 
 private:
   friend class SignerFilter;
@@ -261,7 +337,7 @@
   toPkcs8(PasswordCallback pwCallback = nullptr) const;
 
   ConstBufferPtr
-  rsaDecrypt(const uint8_t* cipherText, size_t cipherLen) const;
+  rsaDecrypt(span<const uint8_t> cipherText) const;
 
 private:
   friend unique_ptr<PrivateKey> generatePrivateKey(const KeyParams&);
diff --git a/ndn-cxx/security/transform/public-key.cpp b/ndn-cxx/security/transform/public-key.cpp
index d38b1d7..7312d26 100644
--- a/ndn-cxx/security/transform/public-key.cpp
+++ b/ndn-cxx/security/transform/public-key.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -44,7 +44,7 @@
 namespace security {
 namespace transform {
 
-class PublicKey::Impl
+class PublicKey::Impl : noncopyable
 {
 public:
   Impl() noexcept
@@ -85,11 +85,12 @@
 }
 
 void
-PublicKey::loadPkcs8(const uint8_t* buf, size_t size)
+PublicKey::loadPkcs8(span<const uint8_t> buf)
 {
   ENSURE_PUBLIC_KEY_NOT_LOADED(m_impl->key);
 
-  if (d2i_PUBKEY(&m_impl->key, &buf, static_cast<long>(size)) == nullptr)
+  auto ptr = buf.data();
+  if (d2i_PUBKEY(&m_impl->key, &ptr, static_cast<long>(buf.size())) == nullptr)
     NDN_THROW(Error("Failed to load public key"));
 }
 
@@ -98,15 +99,15 @@
 {
   OBufferStream os;
   streamSource(is) >> streamSink(os);
-  this->loadPkcs8(os.buf()->data(), os.buf()->size());
+  loadPkcs8(*os.buf());
 }
 
 void
-PublicKey::loadPkcs8Base64(const uint8_t* buf, size_t size)
+PublicKey::loadPkcs8Base64(span<const uint8_t> buf)
 {
   OBufferStream os;
-  bufferSource(buf, size) >> base64Decode() >> streamSink(os);
-  this->loadPkcs8(os.buf()->data(), os.buf()->size());
+  bufferSource(buf) >> base64Decode() >> streamSink(os);
+  loadPkcs8(*os.buf());
 }
 
 void
@@ -114,23 +115,23 @@
 {
   OBufferStream os;
   streamSource(is) >> base64Decode() >> streamSink(os);
-  this->loadPkcs8(os.buf()->data(), os.buf()->size());
+  loadPkcs8(*os.buf());
 }
 
 void
 PublicKey::savePkcs8(std::ostream& os) const
 {
-  bufferSource(*this->toPkcs8()) >> streamSink(os);
+  bufferSource(*toPkcs8()) >> streamSink(os);
 }
 
 void
 PublicKey::savePkcs8Base64(std::ostream& os) const
 {
-  bufferSource(*this->toPkcs8()) >> base64Encode() >> streamSink(os);
+  bufferSource(*toPkcs8()) >> base64Encode() >> streamSink(os);
 }
 
 ConstBufferPtr
-PublicKey::encrypt(const uint8_t* plainText, size_t plainLen) const
+PublicKey::encrypt(span<const uint8_t> plainText) const
 {
   ENSURE_PUBLIC_KEY_LOADED(m_impl->key);
 
@@ -139,7 +140,7 @@
     case EVP_PKEY_NONE:
       NDN_THROW(Error("Failed to determine key type"));
     case EVP_PKEY_RSA:
-      return rsaEncrypt(plainText, plainLen);
+      return rsaEncrypt(plainText);
     default:
       NDN_THROW(Error("Encryption is not supported for key type " + to_string(keyType)));
   }
@@ -168,7 +169,7 @@
 }
 
 ConstBufferPtr
-PublicKey::rsaEncrypt(const uint8_t* plainText, size_t plainLen) const
+PublicKey::rsaEncrypt(span<const uint8_t> plainText) const
 {
   detail::EvpPkeyCtx ctx(m_impl->key);
 
@@ -180,11 +181,11 @@
 
   size_t outlen = 0;
   // Determine buffer length
-  if (EVP_PKEY_encrypt(ctx, nullptr, &outlen, plainText, plainLen) <= 0)
+  if (EVP_PKEY_encrypt(ctx, nullptr, &outlen, plainText.data(), plainText.size()) <= 0)
     NDN_THROW(Error("Failed to estimate output length"));
 
   auto out = make_shared<Buffer>(outlen);
-  if (EVP_PKEY_encrypt(ctx, out->data(), &outlen, plainText, plainLen) <= 0)
+  if (EVP_PKEY_encrypt(ctx, out->data(), &outlen, plainText.data(), plainText.size()) <= 0)
     NDN_THROW(Error("Failed to encrypt plaintext"));
 
   out->resize(outlen);
diff --git a/ndn-cxx/security/transform/public-key.hpp b/ndn-cxx/security/transform/public-key.hpp
index 29c584b..bbe7895 100644
--- a/ndn-cxx/security/transform/public-key.hpp
+++ b/ndn-cxx/security/transform/public-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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -61,7 +61,18 @@
    * @brief Load the public key in PKCS#8 format from a buffer @p buf
    */
   void
-  loadPkcs8(const uint8_t* buf, size_t size);
+  loadPkcs8(span<const uint8_t> buf);
+
+  /**
+   * @brief Load the public key in PKCS#8 format from a buffer @p buf
+   * @deprecated
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  void
+  loadPkcs8(const uint8_t* buf, size_t size)
+  {
+    loadPkcs8({buf, size});
+  }
 
   /**
    * @brief Load the public key in PKCS#8 format from a stream @p is
@@ -73,7 +84,18 @@
    * @brief Load the public key in base64-encoded PKCS#8 format from a buffer @p buf
    */
   void
-  loadPkcs8Base64(const uint8_t* buf, size_t size);
+  loadPkcs8Base64(span<const uint8_t> buf);
+
+  /**
+   * @brief Load the public key in base64-encoded PKCS#8 format from a buffer @p buf
+   * @deprecated
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  void
+  loadPkcs8Base64(const uint8_t* buf, size_t size)
+  {
+    loadPkcs8Base64({buf, size});
+  }
 
   /**
    * @brief Load the public key in base64-encoded PKCS#8 format from a stream @p is
@@ -99,7 +121,20 @@
    * Only RSA encryption is supported for now.
    */
   ConstBufferPtr
-  encrypt(const uint8_t* plainText, size_t plainLen) const;
+  encrypt(span<const uint8_t> plainText) const;
+
+  /**
+   * @return Cipher text of @p plainText encrypted using this public key.
+   * @deprecated
+   *
+   * Only RSA encryption is supported for now.
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  ConstBufferPtr
+  encrypt(const uint8_t* plainText, size_t plainLen) const
+  {
+    return encrypt({plainText, plainLen});
+  }
 
 private:
   friend class VerifierFilter;
@@ -117,7 +152,7 @@
   toPkcs8() const;
 
   ConstBufferPtr
-  rsaEncrypt(const uint8_t* plainText, size_t plainLen) const;
+  rsaEncrypt(span<const uint8_t> plainText) const;
 
 private:
   class Impl;
diff --git a/ndn-cxx/security/transform/signer-filter.cpp b/ndn-cxx/security/transform/signer-filter.cpp
index 33f380f..036a16b 100644
--- a/ndn-cxx/security/transform/signer-filter.cpp
+++ b/ndn-cxx/security/transform/signer-filter.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -54,12 +54,12 @@
 SignerFilter::~SignerFilter() = default;
 
 size_t
-SignerFilter::convert(const uint8_t* buf, size_t size)
+SignerFilter::convert(span<const uint8_t> buf)
 {
-  if (EVP_DigestSignUpdate(m_impl->ctx, buf, size) != 1)
+  if (EVP_DigestSignUpdate(m_impl->ctx, buf.data(), buf.size()) != 1)
     NDN_THROW(Error(getIndex(), "Failed to accept more input"));
 
-  return size;
+  return buf.size();
 }
 
 void
diff --git a/ndn-cxx/security/transform/signer-filter.hpp b/ndn-cxx/security/transform/signer-filter.hpp
index 8cb573b..842ba10 100644
--- a/ndn-cxx/security/transform/signer-filter.hpp
+++ b/ndn-cxx/security/transform/signer-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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -34,7 +34,7 @@
 /**
  * @brief The module to sign data.
  */
-class SignerFilter : public Transform
+class SignerFilter final : public Transform
 {
 public:
   /**
@@ -42,7 +42,7 @@
    */
   SignerFilter(DigestAlgorithm algo, const PrivateKey& key);
 
-  ~SignerFilter();
+  ~SignerFilter() final;
 
 private:
   /**
@@ -51,7 +51,7 @@
    * @return The number of bytes that are actually accepted
    */
   size_t
-  convert(const uint8_t* buf, size_t size) final;
+  convert(span<const uint8_t> buf) final;
 
   /**
    * @brief Finalize signing and write the signature into next module.
diff --git a/ndn-cxx/security/transform/step-source.cpp b/ndn-cxx/security/transform/step-source.cpp
index 0ff004b..cfeac7a 100644
--- a/ndn-cxx/security/transform/step-source.cpp
+++ b/ndn-cxx/security/transform/step-source.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -26,9 +26,9 @@
 namespace transform {
 
 size_t
-StepSource::write(const uint8_t* buf, size_t size)
+StepSource::write(span<const uint8_t> buf)
 {
-  return m_next->write(buf, size);
+  return m_next->write(buf);
 }
 
 void
@@ -37,7 +37,6 @@
   m_next->end();
 }
 
-
 void
 StepSource::doPump()
 {
diff --git a/ndn-cxx/security/transform/step-source.hpp b/ndn-cxx/security/transform/step-source.hpp
index a1e88c7..84ab022 100644
--- a/ndn-cxx/security/transform/step-source.hpp
+++ b/ndn-cxx/security/transform/step-source.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -54,25 +54,35 @@
    * @return number of bytes that has been written into next module
    */
   size_t
-  write(const uint8_t* buf, size_t size);
+  write(span<const uint8_t> buf);
 
   /**
-   * @brief Close the input interface and directly notify the next module the end of input
+   * @deprecated
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  size_t
+  write(const uint8_t* buf, size_t size)
+  {
+    return write({buf, size});
+  }
+
+  /**
+   * @brief Close the input interface and directly notify the next module the end of input.
    */
   void
   end();
 
 private:
   /**
-   * @brief This method intentionally does nothing
+   * @brief This method intentionally does nothing.
    *
-   * use write() and end() method explicitly to input data.
+   * Use write() and end() explicitly to submit data.
    */
   void
   doPump() final;
 };
 
-typedef StepSource stepSource;
+using stepSource = StepSource;
 
 } // namespace transform
 } // namespace security
diff --git a/ndn-cxx/security/transform/stream-sink.cpp b/ndn-cxx/security/transform/stream-sink.cpp
index 5eba76a..c35e196 100644
--- a/ndn-cxx/security/transform/stream-sink.cpp
+++ b/ndn-cxx/security/transform/stream-sink.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -33,14 +33,14 @@
 }
 
 size_t
-StreamSink::doWrite(const uint8_t* buf, size_t size)
+StreamSink::doWrite(span<const uint8_t> buf)
 {
-  m_os.write(reinterpret_cast<const char*>(buf), size);
+  m_os.write(reinterpret_cast<const char*>(buf.data()), buf.size());
 
   if (m_os.bad())
     NDN_THROW(Error(getIndex(), "Fail to write data into output stream"));
 
-  return size;
+  return buf.size();
 }
 
 void
@@ -55,7 +55,6 @@
   return make_unique<StreamSink>(os);
 }
 
-
 } // namespace transform
 } // namespace security
 } // namespace ndn
diff --git a/ndn-cxx/security/transform/stream-sink.hpp b/ndn-cxx/security/transform/stream-sink.hpp
index 856c66b..53e5408 100644
--- a/ndn-cxx/security/transform/stream-sink.hpp
+++ b/ndn-cxx/security/transform/stream-sink.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -47,7 +47,7 @@
    * @return number of bytes that have been written into the stream
    */
   size_t
-  doWrite(const uint8_t* buf, size_t size) final;
+  doWrite(span<const uint8_t> buf) final;
 
   /**
    * @brief Finalize sink processing
diff --git a/ndn-cxx/security/transform/stream-source.cpp b/ndn-cxx/security/transform/stream-source.cpp
index 40fb7a4..8acf41e 100644
--- a/ndn-cxx/security/transform/stream-source.cpp
+++ b/ndn-cxx/security/transform/stream-source.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -50,7 +50,7 @@
   while (dataLen > 0 || !m_is.eof()) {
     if (dataLen > 0) {
       // we have some leftover, handle them first
-      size_t nBytesWritten = m_next->write(&buffer[dataOffset], dataLen);
+      size_t nBytesWritten = m_next->write({&buffer[dataOffset], dataLen});
 
       dataOffset += nBytesWritten;
       dataLen -= nBytesWritten;
diff --git a/ndn-cxx/security/transform/strip-space.cpp b/ndn-cxx/security/transform/strip-space.cpp
index 3ce8ead..9465400 100644
--- a/ndn-cxx/security/transform/strip-space.cpp
+++ b/ndn-cxx/security/transform/strip-space.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -35,20 +35,19 @@
 }
 
 size_t
-StripSpace::convert(const uint8_t* buf, size_t buflen)
+StripSpace::convert(span<const uint8_t> data)
 {
   auto buffer = make_unique<OBuffer>();
-  buffer->reserve(buflen);
+  buffer->reserve(data.size());
 
-  for (size_t i = 0; i < buflen; ++i) {
-    uint8_t ch = buf[i];
+  for (auto ch : data) {
     if (!m_isWhitespace[ch]) {
       buffer->push_back(ch);
     }
   }
 
   setOutputBuffer(std::move(buffer));
-  return buflen;
+  return data.size();
 }
 
 unique_ptr<Transform>
diff --git a/ndn-cxx/security/transform/strip-space.hpp b/ndn-cxx/security/transform/strip-space.hpp
index 3329547..b4867c6 100644
--- a/ndn-cxx/security/transform/strip-space.hpp
+++ b/ndn-cxx/security/transform/strip-space.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -31,12 +31,13 @@
 namespace security {
 namespace transform {
 
-/** \brief strip whitespace characters from a stream
+/**
+ * \brief Strip whitespace characters from a stream.
  *
- *  This transform interprets the input as a byte string, and puts all bytes except
- *  whitespace characters on the output.
+ * This transform interprets the input as a byte string, and puts all bytes except
+ * whitespace characters on the output.
  */
-class StripSpace : public Transform
+class StripSpace final : public Transform
 {
 public:
   static const char* const DEFAULT_WHITESPACES;
@@ -46,7 +47,7 @@
 
 private:
   size_t
-  convert(const uint8_t* buf, size_t buflen) final;
+  convert(span<const uint8_t> data) final;
 
 private:
   static constexpr size_t CHARMAP_SIZE = 1 << CHAR_BIT;
diff --git a/ndn-cxx/security/transform/transform-base.cpp b/ndn-cxx/security/transform/transform-base.cpp
index 9bd661d..aa6de28 100644
--- a/ndn-cxx/security/transform/transform-base.cpp
+++ b/ndn-cxx/security/transform/transform-base.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -31,20 +31,14 @@
 {
 }
 
-Downstream::Downstream()
-  : m_isEnd(false)
-  , m_index(0)
-{
-}
-
 size_t
-Downstream::write(const uint8_t* buf, size_t size)
+Downstream::write(span<const uint8_t> buf)
 {
   if (m_isEnd)
     NDN_THROW(Error(getIndex(), "Module is closed, no more input"));
 
-  size_t nBytesWritten = doWrite(buf, size);
-  BOOST_ASSERT(nBytesWritten <= size);
+  size_t nBytesWritten = doWrite(buf);
+  BOOST_ASSERT(nBytesWritten <= buf.size());
   return nBytesWritten;
 }
 
@@ -55,12 +49,7 @@
     return;
 
   m_isEnd = true;
-  return doEnd();
-}
-
-Upstream::Upstream()
-  : m_next(nullptr)
-{
+  doEnd();
 }
 
 void
@@ -75,20 +64,13 @@
   }
 }
 
-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);
+  size_t nWritten = m_next->write(make_span(*m_oBuffer).last(m_oBuffer->size() - m_outputOffset));
   m_outputOffset += nWritten;
 }
 
@@ -111,11 +93,11 @@
 bool
 Transform::isOutputBufferEmpty() const
 {
-  return (m_oBuffer == nullptr || m_oBuffer->size() == m_outputOffset);
+  return m_oBuffer == nullptr || m_oBuffer->size() == m_outputOffset;
 }
 
 size_t
-Transform::doWrite(const uint8_t* data, size_t dataLen)
+Transform::doWrite(span<const uint8_t> data)
 {
   flushOutputBuffer();
   if (!isOutputBufferEmpty())
@@ -126,10 +108,8 @@
   if (!isOutputBufferEmpty())
     return 0;
 
-  size_t nConverted = convert(data, dataLen);
-
+  size_t nConverted = convert(data);
   flushOutputBuffer();
-
   return nConverted;
 }
 
@@ -151,11 +131,6 @@
   flushAllOutput();
 }
 
-Source::Source()
-  : m_nModules(1) // source per se is counted as one module
-{
-}
-
 void
 Source::pump()
 {
@@ -167,7 +142,7 @@
 {
   transform->setIndex(m_nModules);
   m_nModules++;
-  this->appendChain(std::move(transform));
+  appendChain(std::move(transform));
 
   return *this;
 }
@@ -177,9 +152,9 @@
 {
   sink->setIndex(m_nModules);
   m_nModules++;
-  this->appendChain(std::move(sink));
+  appendChain(std::move(sink));
 
-  this->pump();
+  pump();
 }
 
 } // namespace transform
diff --git a/ndn-cxx/security/transform/transform-base.hpp b/ndn-cxx/security/transform/transform-base.hpp
index 3a9ab9c..659b293 100644
--- a/ndn-cxx/security/transform/transform-base.hpp
+++ b/ndn-cxx/security/transform/transform-base.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -23,6 +23,7 @@
 #define NDN_CXX_SECURITY_TRANSFORM_BASE_HPP
 
 #include "ndn-cxx/detail/common.hpp"
+#include "ndn-cxx/util/span.hpp"
 
 #include <vector>
 
@@ -61,11 +62,11 @@
 };
 
 /**
- * @brief The downstream interface of a transformation module
+ * @brief The downstream interface of a transformation module.
  *
- * A module can accept input through this interface
+ * A module can accept input through this interface.
  */
-class Downstream
+class Downstream : noncopyable
 {
 public:
   virtual
@@ -88,7 +89,17 @@
    * @throws Error if this module is closed or transformation error happens.
    */
   size_t
-  write(const uint8_t* buf, size_t size);
+  write(span<const uint8_t> buf);
+
+  /**
+   * @deprecated
+   */
+  [[deprecated("use the overload that takes a span<>")]]
+  size_t
+  write(const uint8_t* buf, size_t size)
+  {
+    return write({buf, size});
+  }
 
   /**
    * @brief Close the input interface of a module.
@@ -129,30 +140,24 @@
   }
 
 protected:
-  Downstream();
+  Downstream() = default;
 
 private:
-  /**
-   * @brief Internal implementation of write method
-   */
   virtual size_t
-  doWrite(const uint8_t* buf, size_t size) = 0;
+  doWrite(span<const uint8_t> buf) = 0;
 
-  /**
-   * @brief Internal implementation of end method
-   */
   virtual void
   doEnd() = 0;
 
 private:
-  bool m_isEnd;
-  size_t m_index;
+  size_t m_index = 0;
+  bool m_isEnd = false;
 };
 
 /**
- * @brief The upstream interface of a transformation module
+ * @brief The upstream interface of a transformation module.
  *
- * A module can construct subsequent transformation chain through this interface.
+ * A module can construct subsequent transformation chains through this interface.
  */
 class Upstream
 {
@@ -161,11 +166,11 @@
   ~Upstream() = default;
 
 protected:
-  Upstream();
+  Upstream() = default;
 
 protected:
   /**
-   * @brief connect to next transformation module
+   * @brief Connect to the next transformation module
    */
   void
   appendChain(unique_ptr<Downstream> tail);
@@ -181,16 +186,15 @@
 };
 
 /**
- * @brief Abstraction of an intermediate transformation module
+ * @brief Abstraction of an intermediate transformation module.
  */
 class Transform : public Upstream,
-                  public Downstream,
-                  noncopyable
+                  public Downstream
 {
 protected:
-  typedef std::vector<uint8_t> OBuffer;
+  using OBuffer = std::vector<uint8_t>;
 
-  Transform();
+  Transform() = default;
 
   /**
    * @brief Read the content from output buffer and write it into next module.
@@ -220,11 +224,8 @@
   isOutputBufferEmpty() const;
 
 private:
-  /**
-   * @brief Abstraction of data processing in an intermediate module
-   */
   size_t
-  doWrite(const uint8_t* data, size_t dataLen) final;
+  doWrite(span<const uint8_t> data) final;
 
   /**
    * @brief Finalize transformation in this module
@@ -237,7 +238,7 @@
   /**
    * @brief Process before transformation.
    *
-   * @pre output buffer is empty.
+   * @pre Output buffer is empty.
    *
    * This method is invoked before every convert(...) invocation.
    *
@@ -254,7 +255,7 @@
    * @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;
+  convert(span<const uint8_t> data) = 0;
 
   /**
    * @brief Finalize the transformation.
@@ -268,26 +269,24 @@
 
 private:
   unique_ptr<OBuffer> m_oBuffer;
-  size_t m_outputOffset;
+  size_t m_outputOffset = 0;
 };
 
 /**
- * @brief Abstraction of the transformation sink module
+ * @brief Abstraction of the transformation sink module.
  *
- * This module does not have next module and can only accept input data
+ * This module does not have a next module and can only accept input data.
  */
-class Sink : public Downstream,
-             noncopyable
+class Sink : public Downstream
 {
 };
 
 /**
- * @brief Abstraction of the transformation source module
+ * @brief Abstraction of the transformation source module.
  *
- * This module can only accept input data from constructor
+ * This module can only accept input data from the constructor.
  */
-class Source : public Upstream,
-               noncopyable
+class Source : public Upstream
 {
 public:
   /**
@@ -305,7 +304,7 @@
   operator>>(unique_ptr<Sink> sink);
 
 protected:
-  Source();
+  Source() = default;
 
   /**
    * @brief Pump all data into next transformation module.
@@ -323,14 +322,11 @@
   }
 
 private:
-  /**
-   * @brief Internal implementation of pump().
-   */
   virtual void
   doPump() = 0;
 
 private:
-  size_t m_nModules; // count of modules in the chain starting from this Source
+  size_t m_nModules = 1; // count of modules in the chain starting from (and including) this Source
 };
 
 } // namespace transform
diff --git a/ndn-cxx/security/transform/verifier-filter.cpp b/ndn-cxx/security/transform/verifier-filter.cpp
index afcfd3d..a78c403 100644
--- a/ndn-cxx/security/transform/verifier-filter.cpp
+++ b/ndn-cxx/security/transform/verifier-filter.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -88,18 +88,18 @@
 }
 
 size_t
-VerifierFilter::convert(const uint8_t* buf, size_t size)
+VerifierFilter::convert(span<const uint8_t> buf)
 {
   int ret;
   if (m_keyType == KeyType::HMAC)
-    ret = EVP_DigestSignUpdate(m_impl->ctx, buf, size);
+    ret = EVP_DigestSignUpdate(m_impl->ctx, buf.data(), buf.size());
   else
-    ret = EVP_DigestVerifyUpdate(m_impl->ctx, buf, size);
+    ret = EVP_DigestVerifyUpdate(m_impl->ctx, buf.data(), buf.size());
 
   if (ret != 1)
     NDN_THROW(Error(getIndex(), "Failed to accept more input"));
 
-  return size;
+  return buf.size();
 }
 
 void
diff --git a/ndn-cxx/security/transform/verifier-filter.hpp b/ndn-cxx/security/transform/verifier-filter.hpp
index deda280..7a64f47 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-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -37,7 +37,7 @@
  *
  * The next module in the chain is usually BoolSink.
  */
-class VerifierFilter : public Transform
+class VerifierFilter final : public Transform
 {
 public:
   /**
@@ -50,7 +50,7 @@
    */
   VerifierFilter(DigestAlgorithm algo, const PrivateKey& key, const uint8_t* sig, size_t sigLen);
 
-  ~VerifierFilter();
+  ~VerifierFilter() final;
 
 private:
   void
@@ -62,7 +62,7 @@
    * @return The number of bytes that are actually written
    */
   size_t
-  convert(const uint8_t* buf, size_t size) final;
+  convert(span<const uint8_t> buf) final;
 
   /**
    * @brief Finalize verification and write the result (single byte) into next module.
diff --git a/ndn-cxx/security/verification-helpers.cpp b/ndn-cxx/security/verification-helpers.cpp
index 44519b4..b996aae 100644
--- a/ndn-cxx/security/verification-helpers.cpp
+++ b/ndn-cxx/security/verification-helpers.cpp
@@ -45,19 +45,17 @@
 public:
   ParseResult() = default;
 
-  ParseResult(SignatureInfo info, InputBuffers bufs, const uint8_t* sig, size_t sigLen)
+  ParseResult(SignatureInfo info, InputBuffers bufs, span<const uint8_t> sig)
     : info(std::move(info))
     , bufs(std::move(bufs))
     , sig(sig)
-    , sigLen(sigLen)
   {
   }
 
 public:
   SignatureInfo info;
   InputBuffers bufs;
-  const uint8_t* sig = nullptr;
-  size_t sigLen = 0;
+  span<const uint8_t> sig;
 };
 
 } // namespace
@@ -85,7 +83,7 @@
 {
   transform::PublicKey pKey;
   try {
-    pKey.loadPkcs8(key, keyLen);
+    pKey.loadPkcs8({key, keyLen});
   }
   catch (const transform::Error&) {
     return false;
@@ -100,8 +98,7 @@
   try {
     return ParseResult(data.getSignatureInfo(),
                        data.extractSignedRanges(),
-                       data.getSignatureValue().value(),
-                       data.getSignatureValue().value_size());
+                       {data.getSignatureValue().value(), data.getSignatureValue().value_size()});
   }
   catch (const tlv::Error&) {
     return ParseResult();
@@ -119,8 +116,7 @@
       Block sigValue = interest.getSignatureValue();
       return ParseResult(*interest.getSignatureInfo(),
                          interest.extractSignedRanges(),
-                         sigValue.value(),
-                         sigValue.value_size());
+                         {sigValue.value(), sigValue.value_size()});
     }
     else {
       // Verify using older Signed Interest semantics
@@ -135,8 +131,8 @@
       return ParseResult(info,
                          {{nameBlock.value(),
                            nameBlock.value_size() - interestName[signed_interest::POS_SIG_VALUE].size()}},
-                         sigValue.value(),
-                         sigValue.value_size());
+                         {sigValue.value(),
+                          sigValue.value_size()});
     }
   }
   catch (const tlv::Error&) {
@@ -147,21 +143,22 @@
 static bool
 verifySignature(const ParseResult& params, const transform::PublicKey& key)
 {
-  return !params.bufs.empty() && verifySignature(params.bufs, params.sig, params.sigLen, key);
+  return !params.bufs.empty() && verifySignature(params.bufs, params.sig.data(), params.sig.size(), key);
 }
 
 static bool
-verifySignature(const ParseResult& params, const uint8_t* key, size_t keyLen)
+verifySignature(const ParseResult& params, span<const uint8_t> key)
 {
-  return !params.bufs.empty() && verifySignature(params.bufs, params.sig, params.sigLen, key, keyLen);
+  return !params.bufs.empty() && verifySignature(params.bufs, params.sig.data(), params.sig.size(),
+                                                 key.data(), key.size());
 }
 
 static bool
 verifySignature(const ParseResult& params, const tpm::Tpm& tpm, const Name& keyName,
                 DigestAlgorithm digestAlgorithm)
 {
-  return !params.bufs.empty() && bool(tpm.verify(params.bufs, params.sig, params.sigLen, keyName,
-                                                 digestAlgorithm));
+  return !params.bufs.empty() && bool(tpm.verify(params.bufs, params.sig.data(), params.sig.size(),
+                                                 keyName, digestAlgorithm));
 }
 
 static bool
@@ -181,24 +178,24 @@
   }
   auto result = os.buf();
 
-  if (result->size() != params.sigLen) {
+  if (result->size() != params.sig.size()) {
     return false;
   }
 
   // constant-time buffer comparison to mitigate timing attacks
-  return CRYPTO_memcmp(result->data(), params.sig, params.sigLen) == 0;
+  return CRYPTO_memcmp(result->data(), params.sig.data(), params.sig.size()) == 0;
 }
 
 bool
 verifySignature(const Data& data, const uint8_t* key, size_t keyLen)
 {
-  return verifySignature(parse(data), key, keyLen);
+  return verifySignature(parse(data), make_span(key, keyLen));
 }
 
 bool
 verifySignature(const Interest& interest, const uint8_t* key, size_t keyLen)
 {
-  return verifySignature(parse(interest), key, keyLen);
+  return verifySignature(parse(interest), make_span(key, keyLen));
 }
 
 bool
@@ -216,13 +213,13 @@
 bool
 verifySignature(const Data& data, const pib::Key& key)
 {
-  return verifySignature(parse(data), key.getPublicKey().data(), key.getPublicKey().size());
+  return verifySignature(parse(data), key.getPublicKey());
 }
 
 bool
 verifySignature(const Interest& interest, const pib::Key& key)
 {
-  return verifySignature(parse(interest), key.getPublicKey().data(), key.getPublicKey().size());
+  return verifySignature(parse(interest), key.getPublicKey());
 }
 
 bool
@@ -230,7 +227,7 @@
 {
   auto parsed = parse(data);
   if (cert) {
-    return verifySignature(parsed, cert->getContent().value(), cert->getContent().value_size());
+    return verifySignature(parsed, make_span(cert->getContent().value(), cert->getContent().value_size()));
   }
   else if (parsed.info.getSignatureType() == tlv::SignatureTypeValue::DigestSha256) {
     return verifyDigest(parsed, DigestAlgorithm::SHA256);
@@ -246,7 +243,7 @@
 {
   auto parsed = parse(interest);
   if (cert) {
-    return verifySignature(parsed, cert->getContent().value(), cert->getContent().value_size());
+    return verifySignature(parsed, make_span(cert->getContent().value(), cert->getContent().value_size()));
   }
   else if (parsed.info.getSignatureType() == tlv::SignatureTypeValue::DigestSha256) {
     return verifyDigest(parsed, DigestAlgorithm::SHA256);
diff --git a/ndn-cxx/signature-info.cpp b/ndn-cxx/signature-info.cpp
index 18db237..7c84ae3 100644
--- a/ndn-cxx/signature-info.cpp
+++ b/ndn-cxx/signature-info.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -238,13 +238,13 @@
 }
 
 SignatureInfo&
-SignatureInfo::setNonce(optional<std::vector<uint8_t>> nonce)
+SignatureInfo::setNonce(optional<span<const uint8_t>> nonce)
 {
   if (!nonce) {
     removeCustomTlv(tlv::SignatureNonce);
   }
   else {
-    addCustomTlv(makeBinaryBlock(tlv::SignatureNonce, nonce->data(), nonce->size()));
+    addCustomTlv(makeBinaryBlock(tlv::SignatureNonce, *nonce));
   }
   return *this;
 }
diff --git a/ndn-cxx/signature-info.hpp b/ndn-cxx/signature-info.hpp
index eabf4cc..b1dfecc 100644
--- a/ndn-cxx/signature-info.hpp
+++ b/ndn-cxx/signature-info.hpp
@@ -169,7 +169,7 @@
    *  Passing `nullopt` will remove the SignatureNonce.
    */
   SignatureInfo&
-  setNonce(optional<std::vector<uint8_t>> nonce);
+  setNonce(optional<span<const uint8_t>> nonce);
 
   /** @brief Get SignatureTime
    *  @retval nullopt SignatureTime is not set
diff --git a/ndn-cxx/util/io.cpp b/ndn-cxx/util/io.cpp
index 0fff144..e3277fe 100644
--- a/ndn-cxx/util/io.cpp
+++ b/ndn-cxx/util/io.cpp
@@ -64,16 +64,17 @@
 {
   namespace t = ndn::security::transform;
 
+  auto src = make_span(buf, size);
   try {
     switch (encoding) {
       case NO_ENCODING:
-        t::bufferSource(buf, size) >> t::streamSink(os);
+        t::bufferSource(src) >> t::streamSink(os);
         return;
       case BASE64:
-        t::bufferSource(buf, size) >> t::base64Encode() >> t::streamSink(os);
+        t::bufferSource(src) >> t::base64Encode() >> t::streamSink(os);
         return;
       case HEX:
-        t::bufferSource(buf, size) >> t::hexEncode(true) >> t::streamSink(os);
+        t::bufferSource(src) >> t::hexEncode(true) >> t::streamSink(os);
         return;
     }
   }
diff --git a/ndn-cxx/util/random.cpp b/ndn-cxx/util/random.cpp
index 5ff643e..a60917b 100644
--- a/ndn-cxx/util/random.cpp
+++ b/ndn-cxx/util/random.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -29,7 +29,7 @@
 generateSecureWord32()
 {
   uint32_t random;
-  generateSecureBytes(reinterpret_cast<uint8_t*>(&random), sizeof(random));
+  generateSecureBytes({reinterpret_cast<uint8_t*>(&random), sizeof(random)});
   return random;
 }
 
@@ -37,14 +37,14 @@
 generateSecureWord64()
 {
   uint64_t random;
-  generateSecureBytes(reinterpret_cast<uint8_t*>(&random), sizeof(random));
+  generateSecureBytes({reinterpret_cast<uint8_t*>(&random), sizeof(random)});
   return random;
 }
 
 void
-generateSecureBytes(uint8_t* bytes, size_t size)
+generateSecureBytes(span<uint8_t> buf)
 {
-  if (RAND_bytes(bytes, size) != 1) {
+  if (RAND_bytes(buf.data(), buf.size()) != 1) {
     NDN_THROW(std::runtime_error("Failed to generate random bytes (error code " +
                                  to_string(ERR_get_error()) + ")"));
   }
diff --git a/ndn-cxx/util/random.hpp b/ndn-cxx/util/random.hpp
index 7061cd1..f7e5027 100644
--- a/ndn-cxx/util/random.hpp
+++ b/ndn-cxx/util/random.hpp
@@ -23,6 +23,7 @@
 #define NDN_CXX_UTIL_RANDOM_HPP
 
 #include "ndn-cxx/detail/common.hpp"
+#include "ndn-cxx/util/span.hpp"
 
 #include <random>
 
@@ -46,12 +47,22 @@
 generateSecureWord64();
 
 /**
- * @brief Fill @p bytes of @p size with cryptographically secure random bytes
+ * @brief Fill @p buffer with cryptographically secure random bytes
  *
  * @throw std::runtime_error if generation fails.
  */
 void
-generateSecureBytes(uint8_t* bytes, size_t size);
+generateSecureBytes(span<uint8_t> buffer);
+
+/**
+ * @deprecated Use generateSecureBytes(span<uint8_t>)
+ */
+[[deprecated("use the overload that takes a span<>")]]
+inline void
+generateSecureBytes(uint8_t* bytes, size_t size)
+{
+  generateSecureBytes({bytes, size});
+}
 
 using RandomNumberEngine = std::mt19937;
 
diff --git a/ndn-cxx/util/sha256.cpp b/ndn-cxx/util/sha256.cpp
index 3575884..3de1b85 100644
--- a/ndn-cxx/util/sha256.cpp
+++ b/ndn-cxx/util/sha256.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -121,7 +121,7 @@
     NDN_THROW(Error("Digest has been already finalized"));
 
   BOOST_ASSERT(m_input != nullptr);
-  m_input->write(buffer, size);
+  m_input->write({buffer, size});
   m_isEmpty = false;
 }
 
diff --git a/ndn-cxx/util/span.hpp b/ndn-cxx/util/span.hpp
new file mode 100644
index 0000000..a4d2ae2
--- /dev/null
+++ b/ndn-cxx/util/span.hpp
@@ -0,0 +1,42 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2021 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_UTIL_SPAN_HPP
+#define NDN_CXX_UTIL_SPAN_HPP
+
+#define span_CONFIG_SELECT_SPAN span_SPAN_NONSTD
+#ifdef NDEBUG
+#define span_CONFIG_CONTRACT_LEVEL_OFF
+#else
+#define span_CONFIG_CONTRACT_LEVEL_ON
+#endif
+#define span_FEATURE_MAKE_SPAN 1
+#include "ndn-cxx/detail/nonstd/span-lite.hpp"
+
+namespace ndn {
+
+using ::nonstd::span;
+using ::nonstd::dynamic_extent;
+using ::nonstd::make_span;
+
+} // namespace ndn
+
+#endif // NDN_CXX_UTIL_SPAN_HPP
diff --git a/ndn-cxx/util/string-helper.cpp b/ndn-cxx/util/string-helper.cpp
index d0afc19..011f967 100644
--- a/ndn-cxx/util/string-helper.cpp
+++ b/ndn-cxx/util/string-helper.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -42,18 +42,17 @@
 }
 
 void
-printHex(std::ostream& os, const uint8_t* buffer, size_t length, bool wantUpperCase)
+printHex(std::ostream& os, span<const uint8_t> buffer, bool wantUpperCase)
 {
   namespace tr = security::transform;
-  BOOST_ASSERT(buffer != nullptr || length == 0);
-  tr::bufferSource(buffer, length) >> tr::hexEncode(wantUpperCase) >> tr::streamSink(os);
+  tr::bufferSource(buffer) >> tr::hexEncode(wantUpperCase) >> tr::streamSink(os);
 }
 
 std::string
-toHex(const uint8_t* buffer, size_t length, bool wantUpperCase)
+toHex(span<const uint8_t> buffer, bool wantUpperCase)
 {
   std::ostringstream result;
-  printHex(result, buffer, length, wantUpperCase);
+  printHex(result, buffer, wantUpperCase);
   return result.str();
 }
 
diff --git a/ndn-cxx/util/string-helper.hpp b/ndn-cxx/util/string-helper.hpp
index 4a1d2a4..29e7d67 100644
--- a/ndn-cxx/util/string-helper.hpp
+++ b/ndn-cxx/util/string-helper.hpp
@@ -23,6 +23,7 @@
 #define NDN_CXX_UTIL_STRING_HELPER_HPP
 
 #include "ndn-cxx/encoding/buffer.hpp"
+#include "ndn-cxx/util/span.hpp"
 
 namespace ndn {
 
@@ -48,6 +49,16 @@
  * @brief Output the hex representation of the bytes in @p buffer to the output stream @p os
  *
  * @param os Output stream
+ * @param buffer Range of bytes to print in hexadecimal format
+ * @param wantUpperCase if true (the default) print uppercase hex chars
+ */
+void
+printHex(std::ostream& os, span<const uint8_t> buffer, bool wantUpperCase = true);
+
+/**
+ * @brief Output the hex representation of the bytes in @p buffer to the output stream @p os
+ *
+ * @param os Output stream
  * @param buffer Pointer to an array of bytes
  * @param length Size of the array
  * @param wantUpperCase if true (the default) print uppercase hex chars
@@ -63,20 +74,10 @@
  *
  * The output string is a continuous sequence of hex characters without any whitespace separators.
  */
-void
-printHex(std::ostream& os, const uint8_t* buffer, size_t length, bool wantUpperCase = true);
-
-/**
- * @brief Output the hex representation of the bytes in @p buffer to the output stream @p os
- *
- * @param os Output stream
- * @param buffer Buffer of bytes to print in hexadecimal format
- * @param wantUpperCase if true (the default) print uppercase hex chars
- */
 inline void
-printHex(std::ostream& os, const Buffer& buffer, bool wantUpperCase = true)
+printHex(std::ostream& os, const uint8_t* buffer, size_t length, bool wantUpperCase = true)
 {
-  return printHex(os, buffer.data(), buffer.size(), wantUpperCase);
+  printHex(os, {buffer, length}, wantUpperCase);
 }
 
 /**
@@ -114,6 +115,15 @@
 /**
  * @brief Return a string containing the hex representation of the bytes in @p buffer
  *
+ * @param buffer Range of bytes to convert to hexadecimal format
+ * @param wantUpperCase if true (the default) use uppercase hex chars
+ */
+NDN_CXX_NODISCARD std::string
+toHex(span<const uint8_t> buffer, bool wantUpperCase = true);
+
+/**
+ * @brief Return a string containing the hex representation of the bytes in @p buffer
+ *
  * @param buffer Pointer to an array of bytes
  * @param length Size of the array
  * @param wantUpperCase if true (the default) use uppercase hex chars
@@ -129,19 +139,10 @@
  *
  * The output string is a continuous sequence of hex characters without any whitespace separators.
  */
-NDN_CXX_NODISCARD std::string
-toHex(const uint8_t* buffer, size_t length, bool wantUpperCase = true);
-
-/**
- * @brief Return a string containing the hex representation of the bytes in @p buffer
- *
- * @param buffer Buffer of bytes to convert to hexadecimal format
- * @param wantUpperCase if true (the default) use uppercase hex chars
- */
 NDN_CXX_NODISCARD inline std::string
-toHex(const Buffer& buffer, bool wantUpperCase = true)
+toHex(const uint8_t* buffer, size_t length, bool wantUpperCase = true)
 {
-  return toHex(buffer.data(), buffer.size(), wantUpperCase);
+  return toHex({buffer, length}, wantUpperCase);
 }
 
 /**
diff --git a/tests/unit/data.t.cpp b/tests/unit/data.t.cpp
index 64adf2f..d6bb6bb 100644
--- a/tests/unit/data.t.cpp
+++ b/tests/unit/data.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -103,9 +103,9 @@
 protected:
   DataSigningKeyFixture()
   {
-    m_privKey.loadPkcs1(PRIVATE_KEY_DER, sizeof(PRIVATE_KEY_DER));
+    m_privKey.loadPkcs1(PRIVATE_KEY_DER);
     auto buf = m_privKey.derivePublicKey();
-    m_pubKey.loadPkcs8(buf->data(), buf->size());
+    m_pubKey.loadPkcs8(*buf);
   }
 
 protected:
@@ -196,10 +196,10 @@
     tr::StepSource input;
     input >> tr::signerFilter(DigestAlgorithm::SHA256, m_privKey) >> tr::streamSink(sig);
 
-    input.write(d.getName().    wireEncode().wire(), d.getName().    wireEncode().size());
-    input.write(d.getMetaInfo().wireEncode().wire(), d.getMetaInfo().wireEncode().size());
-    input.write(d.getContent().              wire(), d.getContent().              size());
-    input.write(signatureInfo.  wireEncode().wire(), signatureInfo.  wireEncode().size());
+    input.write({d.getName().    wireEncode().wire(), d.getName().    wireEncode().size()});
+    input.write({d.getMetaInfo().wireEncode().wire(), d.getMetaInfo().wireEncode().size()});
+    input.write({d.getContent().              wire(), d.getContent().              size()});
+    input.write({signatureInfo.  wireEncode().wire(), signatureInfo.  wireEncode().size()});
     input.end();
   }
   d.setSignatureValue(sig.buf());
@@ -583,7 +583,7 @@
   const Block& wire1 = d1.wireEncode();
   const auto& sigInfoWire1 = wire1.find(tlv::SignatureInfo);
   BOOST_REQUIRE(sigInfoWire1 != wire1.elements_end());
-  BOOST_CHECK_EQUAL_COLLECTIONS(ranges1.front().first, ranges1.front().first + ranges1.front().second,
+  BOOST_CHECK_EQUAL_COLLECTIONS(ranges1.front().begin(), ranges1.front().end(),
                                 wire1.value_begin(), sigInfoWire1->value_end());
 
   // Test with decoded Data and ensure excludes elements after SignatureValue
@@ -600,8 +600,7 @@
   Data d2(wire2);
   auto ranges2 = d2.extractSignedRanges();
   BOOST_REQUIRE_EQUAL(ranges2.size(), 1);
-  BOOST_CHECK_EQUAL_COLLECTIONS(ranges2.front().first, ranges2.front().first + ranges2.front().second,
-                                &WIRE[2], &WIRE[9]);
+  BOOST_CHECK_EQUAL_COLLECTIONS(ranges2.front().begin(), ranges2.front().end(), &WIRE[2], &WIRE[9]);
 }
 
 BOOST_AUTO_TEST_CASE(Equality)
diff --git a/tests/unit/encoding/block-helpers.t.cpp b/tests/unit/encoding/block-helpers.t.cpp
index c44be84..4b26109 100644
--- a/tests/unit/encoding/block-helpers.t.cpp
+++ b/tests/unit/encoding/block-helpers.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -101,19 +101,22 @@
   BOOST_CHECK_THROW(readDouble("64043E800000"_block), tlv::Error);
 }
 
-BOOST_AUTO_TEST_CASE(Data)
+BOOST_AUTO_TEST_CASE(Binary)
 {
   std::string buf1{1, 1, 1, 1};
   const uint8_t buf2[]{1, 1, 1, 1};
   std::list<uint8_t> buf3{1, 1, 1, 1};
 
-  Block b1 = makeBinaryBlock(100, buf1.data(), buf1.size());
-  Block b2 = makeBinaryBlock(100, buf2, sizeof(buf2));
-  Block b3 = makeBinaryBlock(100, buf1.begin(), buf1.end()); // fast encoding (random access iterator)
-  Block b4 = makeBinaryBlock(100, buf3.begin(), buf3.end()); // slow encoding (general iterator)
+  Block b1 = makeBinaryBlock(100, buf1.data(), buf1.size()); // char* overload
+  Block b2 = makeBinaryBlock(100, buf2, sizeof(buf2));       // uint8_t* overload
+  Block b3 = makeBinaryBlock(100, buf2);                     // span overload
+  Block b4 = makeBinaryBlock(100, buf1.begin(), buf1.end()); // fast encoding (random access iterator)
+  Block b5 = makeBinaryBlock(100, buf3.begin(), buf3.end()); // slow encoding (general iterator)
 
   BOOST_CHECK_EQUAL(b1, b2);
   BOOST_CHECK_EQUAL(b1, b3);
+  BOOST_CHECK_EQUAL(b1, b4);
+  BOOST_CHECK_EQUAL(b1, b5);
   BOOST_CHECK_EQUAL(b1.type(), 100);
   BOOST_CHECK_EQUAL(b1.value_size(), buf1.size());
   BOOST_CHECK_EQUAL_COLLECTIONS(b1.value_begin(), b1.value_end(), buf2, buf2 + sizeof(buf2));
diff --git a/tests/unit/interest.t.cpp b/tests/unit/interest.t.cpp
index f119792..b630e64 100644
--- a/tests/unit/interest.t.cpp
+++ b/tests/unit/interest.t.cpp
@@ -1082,12 +1082,12 @@
   const Block& wire1 = i1.wireEncode();
   // Ensure Name range captured properly
   Block nameWithoutDigest1 = i1.getName().getPrefix(-1).wireEncode();
-  BOOST_CHECK_EQUAL_COLLECTIONS(ranges1.front().first, ranges1.front().first + ranges1.front().second,
+  BOOST_CHECK_EQUAL_COLLECTIONS(ranges1.front().begin(), ranges1.front().end(),
                                 nameWithoutDigest1.value_begin(), nameWithoutDigest1.value_end());
   // Ensure parameters range captured properly
   const auto& appParamsWire1 = wire1.find(tlv::ApplicationParameters);
   BOOST_REQUIRE(appParamsWire1 != wire1.elements_end());
-  BOOST_CHECK_EQUAL_COLLECTIONS(ranges1.back().first, ranges1.back().first + ranges1.back().second,
+  BOOST_CHECK_EQUAL_COLLECTIONS(ranges1.back().begin(), ranges1.back().end(),
                                 appParamsWire1->begin(), wire1.end());
 
   // Test with Interest with existing InterestSignatureValue
@@ -1098,14 +1098,14 @@
   const auto& wire2 = i1.wireEncode();
   // Ensure Name range captured properly
   Block nameWithoutDigest2 = i1.getName().getPrefix(-1).wireEncode();
-  BOOST_CHECK_EQUAL_COLLECTIONS(ranges2.front().first, ranges2.front().first + ranges2.front().second,
+  BOOST_CHECK_EQUAL_COLLECTIONS(ranges2.front().begin(), ranges2.front().end(),
                                 nameWithoutDigest2.value_begin(), nameWithoutDigest2.value_end());
   // Ensure parameters range captured properly
   const auto& appParamsWire2 = wire2.find(tlv::ApplicationParameters);
   BOOST_REQUIRE(appParamsWire2 != wire2.elements_end());
   const auto& sigValueWire2 = wire2.find(tlv::InterestSignatureValue);
   BOOST_REQUIRE(sigValueWire2 != wire2.elements_end());
-  BOOST_CHECK_EQUAL_COLLECTIONS(ranges2.back().first, ranges2.back().first + ranges2.back().second,
+  BOOST_CHECK_EQUAL_COLLECTIONS(ranges2.back().begin(), ranges2.back().end(),
                                 appParamsWire2->begin(), sigValueWire2->begin());
 
   // Test with decoded Interest
@@ -1142,11 +1142,9 @@
   auto ranges3 = i2.extractSignedRanges();
   BOOST_REQUIRE_EQUAL(ranges3.size(), 2);
   // Ensure Name range captured properly
-  BOOST_CHECK_EQUAL_COLLECTIONS(ranges3.front().first, ranges3.front().first + ranges3.front().second,
-                                &WIRE[4], &WIRE[16]);
+  BOOST_CHECK_EQUAL_COLLECTIONS(ranges3.front().begin(), ranges3.front().end(), &WIRE[4], &WIRE[16]);
   // Ensure parameters range captured properly
-  BOOST_CHECK_EQUAL_COLLECTIONS(ranges3.back().first, ranges3.back().first + ranges3.back().second,
-                                &WIRE[58], &WIRE[79]);
+  BOOST_CHECK_EQUAL_COLLECTIONS(ranges3.back().begin(), ranges3.back().end(), &WIRE[58], &WIRE[79]);
 
   // Test failure with missing ParametersSha256DigestComponent
   Interest i3("/a");
diff --git a/tests/unit/key-locator.t.cpp b/tests/unit/key-locator.t.cpp
index a94869e..cfcda4d 100644
--- a/tests/unit/key-locator.t.cpp
+++ b/tests/unit/key-locator.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -93,9 +93,11 @@
 
 BOOST_AUTO_TEST_CASE(TypeKeyDigest)
 {
-  std::string digestOctets = "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45";
-  ConstBufferPtr digestBuffer = make_shared<Buffer>(digestOctets.data(), digestOctets.size());
-  Block expectedDigestBlock = makeBinaryBlock(tlv::KeyDigest, digestOctets.data(), digestOctets.size());
+  static const uint8_t digestOctets[] = {
+    0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf1, 0x23, 0x45
+  };
+  ConstBufferPtr digestBuffer = std::make_shared<Buffer>(digestOctets, sizeof(digestOctets));
+  Block expectedDigestBlock = makeBinaryBlock(tlv::KeyDigest, digestOctets);
 
   KeyLocator a;
   a.setKeyDigest(digestBuffer);
diff --git a/tests/unit/name.t.cpp b/tests/unit/name.t.cpp
index 165668b..fccb838 100644
--- a/tests/unit/name.t.cpp
+++ b/tests/unit/name.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -294,12 +294,12 @@
   auto digest = make_shared<Buffer>(32);
 
   Name name("/P");
-  name.appendParametersSha256Digest(digest);
+  name.appendParametersSha256Digest(digest); // ConstBufferPtr overload
   BOOST_CHECK_EQUAL(name.wireEncode(),
                     "0725 080150 02200000000000000000000000000000000000000000000000000000000000000000"_block);
 
   name = "/P";
-  name.appendParametersSha256Digest(digest->data(), digest->size());
+  name.appendParametersSha256Digest(*digest); // span overload
   BOOST_CHECK_EQUAL(name.wireEncode(),
                     "0725 080150 02200000000000000000000000000000000000000000000000000000000000000000"_block);
 
diff --git a/tests/unit/security/key-chain.t.cpp b/tests/unit/security/key-chain.t.cpp
index ee3e28e..ec40fbd 100644
--- a/tests/unit/security/key-chain.t.cpp
+++ b/tests/unit/security/key-chain.t.cpp
@@ -575,10 +575,10 @@
 
 BOOST_FIXTURE_TEST_CASE(ImportPrivateKey, KeyChainFixture)
 {
-  Name keyName("/test/device2");
-  std::string rawKey("nPSNOHyZKsg2WLqHAs7MXGb0sjQb4zCT");
+  const Name keyName("/test/device2");
+  const uint8_t rawKey[] = "nPSNOHyZKsg2WLqHAs7MXGb0sjQb4zCT";
   auto key = make_shared<transform::PrivateKey>();
-  key->loadRaw(KeyType::HMAC, reinterpret_cast<const uint8_t*>(rawKey.data()), rawKey.size());
+  key->loadRaw(KeyType::HMAC, rawKey);
 
   m_keyChain.importPrivateKey(keyName, key);
   BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(keyName), true);
diff --git a/tests/unit/security/pib/impl/identity-impl.t.cpp b/tests/unit/security/pib/impl/identity-impl.t.cpp
index 3890ddc..1b4527f 100644
--- a/tests/unit/security/pib/impl/identity-impl.t.cpp
+++ b/tests/unit/security/pib/impl/identity-impl.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -63,14 +63,15 @@
   BOOST_REQUIRE_THROW(identity1.setDefaultKey(id1Key1Name), Pib::Error);
 
   // add key
-  identity1.addKey(id1Key1.data(), id1Key1.size(), id1Key1Name);
+  identity1.addKey(id1Key1, id1Key1Name);
   BOOST_CHECK_NO_THROW(identity1.getKey(id1Key1Name));
 
   // new key becomes default key when there is no default key
   BOOST_REQUIRE_NO_THROW(identity1.getDefaultKey());
   const Key& defaultKey0 = identity1.getDefaultKey();
   BOOST_CHECK_EQUAL(defaultKey0.getName(), id1Key1Name);
-  BOOST_CHECK(defaultKey0.getPublicKey() == id1Key1);
+  BOOST_CHECK_EQUAL_COLLECTIONS(defaultKey0.getPublicKey().begin(), defaultKey0.getPublicKey().end(),
+                                id1Key1.begin(), id1Key1.end());
 
   // remove key
   identity1.removeKey(id1Key1Name);
@@ -78,17 +79,18 @@
   BOOST_CHECK_THROW(identity1.getDefaultKey(), Pib::Error);
 
   // set default key directly
-  BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key1.data(), id1Key1.size(), id1Key1Name));
+  BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key1, id1Key1Name));
   BOOST_REQUIRE_NO_THROW(identity1.getDefaultKey());
   BOOST_CHECK_NO_THROW(identity1.getKey(id1Key1Name));
 
   // check default key
   const Key& defaultKey1 = identity1.getDefaultKey();
   BOOST_CHECK_EQUAL(defaultKey1.getName(), id1Key1Name);
-  BOOST_CHECK(defaultKey1.getPublicKey() == id1Key1);
+  BOOST_CHECK_EQUAL_COLLECTIONS(defaultKey1.getPublicKey().begin(), defaultKey1.getPublicKey().end(),
+                                id1Key1.begin(), id1Key1.end());
 
   // add another key
-  identity1.addKey(id1Key2.data(), id1Key2.size(), id1Key2Name);
+  identity1.addKey(id1Key2, id1Key2Name);
   BOOST_CHECK_EQUAL(identity1.getKeys().size(), 2);
 
   // set default key through name
@@ -96,7 +98,8 @@
   BOOST_REQUIRE_NO_THROW(identity1.getDefaultKey());
   const Key& defaultKey2 = identity1.getDefaultKey();
   BOOST_CHECK_EQUAL(defaultKey2.getName(), id1Key2Name);
-  BOOST_CHECK(defaultKey2.getPublicKey() == id1Key2);
+  BOOST_CHECK_EQUAL_COLLECTIONS(defaultKey2.getPublicKey().begin(), defaultKey2.getPublicKey().end(),
+                                id1Key2.begin(), id1Key2.end());
 
   // remove key
   identity1.removeKey(id1Key1Name);
@@ -104,10 +107,11 @@
   BOOST_CHECK_EQUAL(identity1.getKeys().size(), 1);
 
   // set default key directly again, change the default setting
-  BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key1.data(), id1Key1.size(), id1Key1Name));
+  BOOST_REQUIRE_NO_THROW(identity1.setDefaultKey(id1Key1, id1Key1Name));
   const Key& defaultKey3 = identity1.getDefaultKey();
   BOOST_CHECK_EQUAL(defaultKey3.getName(), id1Key1Name);
-  BOOST_CHECK(defaultKey3.getPublicKey() == id1Key1);
+  BOOST_CHECK_EQUAL_COLLECTIONS(defaultKey3.getPublicKey().begin(), defaultKey3.getPublicKey().end(),
+                                id1Key1.begin(), id1Key1.end());
   BOOST_CHECK_EQUAL(identity1.getKeys().size(), 2);
 
   // remove all keys
@@ -125,11 +129,15 @@
   auto pibImpl = make_shared<pib::PibMemory>();
   IdentityImpl identity1(id1, pibImpl, true);
 
-  identity1.addKey(id1Key1.data(), id1Key1.size(), id1Key1Name);
-  BOOST_CHECK(identity1.getKey(id1Key1Name).getPublicKey() == id1Key1);
+  identity1.addKey(id1Key1, id1Key1Name);
+  auto k1 = identity1.getKey(id1Key1Name);
+  BOOST_CHECK_EQUAL_COLLECTIONS(k1.getPublicKey().begin(), k1.getPublicKey().end(),
+                                id1Key1.begin(), id1Key1.end());
 
-  identity1.addKey(id1Key2.data(), id1Key2.size(), id1Key1Name); // overwriting key should work
-  BOOST_CHECK(identity1.getKey(id1Key1Name).getPublicKey() == id1Key2);
+  identity1.addKey(id1Key2, id1Key1Name); // overwriting key should work
+  auto k2 = identity1.getKey(id1Key1Name);
+  BOOST_CHECK_EQUAL_COLLECTIONS(k2.getPublicKey().begin(), k2.getPublicKey().end(),
+                                id1Key2.begin(), id1Key2.end());
 }
 
 BOOST_AUTO_TEST_CASE(Errors)
@@ -139,11 +147,11 @@
   BOOST_CHECK_THROW(IdentityImpl(id1, pibImpl, false), Pib::Error);
   IdentityImpl identity1(id1, pibImpl, true);
 
-  identity1.addKey(id1Key1.data(), id1Key1.size(), id1Key1Name);
-  BOOST_CHECK_THROW(identity1.addKey(id2Key1.data(), id2Key1.size(), id2Key1Name), std::invalid_argument);
+  identity1.addKey(id1Key1, id1Key1Name);
+  BOOST_CHECK_THROW(identity1.addKey(id2Key1, id2Key1Name), std::invalid_argument);
   BOOST_CHECK_THROW(identity1.removeKey(id2Key1Name), std::invalid_argument);
   BOOST_CHECK_THROW(identity1.getKey(id2Key1Name), std::invalid_argument);
-  BOOST_CHECK_THROW(identity1.setDefaultKey(id2Key1.data(), id2Key1.size(), id2Key1Name), std::invalid_argument);
+  BOOST_CHECK_THROW(identity1.setDefaultKey(id2Key1, id2Key1Name), std::invalid_argument);
   BOOST_CHECK_THROW(identity1.setDefaultKey(id2Key1Name), std::invalid_argument);
 }
 
diff --git a/tests/unit/security/pib/impl/key-impl.t.cpp b/tests/unit/security/pib/impl/key-impl.t.cpp
index be986a1..c59efb5 100644
--- a/tests/unit/security/pib/impl/key-impl.t.cpp
+++ b/tests/unit/security/pib/impl/key-impl.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -42,24 +42,26 @@
 BOOST_AUTO_TEST_CASE(Basic)
 {
   auto pibImpl = make_shared<pib::PibMemory>();
-  KeyImpl key11(id1Key1Name, id1Key1.data(), id1Key1.size(), pibImpl);
+  KeyImpl key11(id1Key1Name, id1Key1, pibImpl);
 
   BOOST_CHECK_EQUAL(key11.getName(), id1Key1Name);
   BOOST_CHECK_EQUAL(key11.getIdentity(), id1);
   BOOST_CHECK_EQUAL(key11.getKeyType(), KeyType::EC);
-  BOOST_CHECK(key11.getPublicKey() == id1Key1);
+  BOOST_CHECK_EQUAL_COLLECTIONS(key11.getPublicKey().begin(), key11.getPublicKey().end(),
+                                id1Key1.begin(), id1Key1.end());
 
   KeyImpl key11Bak(id1Key1Name, pibImpl);
   BOOST_CHECK_EQUAL(key11Bak.getName(), id1Key1Name);
   BOOST_CHECK_EQUAL(key11Bak.getIdentity(), id1);
   BOOST_CHECK_EQUAL(key11Bak.getKeyType(), KeyType::EC);
-  BOOST_CHECK(key11Bak.getPublicKey() == id1Key1);
+  BOOST_CHECK_EQUAL_COLLECTIONS(key11Bak.getPublicKey().begin(), key11Bak.getPublicKey().end(),
+                                id1Key1.begin(), id1Key1.end());
 }
 
 BOOST_AUTO_TEST_CASE(CertificateOperation)
 {
   auto pibImpl = make_shared<pib::PibMemory>();
-  KeyImpl key11(id1Key1Name, id1Key1.data(), id1Key1.size(), pibImpl);
+  KeyImpl key11(id1Key1Name, id1Key1, pibImpl);
   BOOST_CHECK_NO_THROW(KeyImpl(id1Key1Name, pibImpl));
 
   // key does not have any certificate
@@ -140,14 +142,16 @@
   auto pibImpl = make_shared<pib::PibMemory>();
 
   BOOST_CHECK_THROW(KeyImpl(id1Key1Name, pibImpl), Pib::Error);
-  KeyImpl(id1Key1Name, id1Key1.data(), id1Key1.size(), pibImpl);
+  KeyImpl(id1Key1Name, id1Key1, pibImpl);
   KeyImpl key1(id1Key1Name, pibImpl);
 
-  KeyImpl(id1Key1Name, id1Key2.data(), id1Key2.size(), pibImpl); // overwriting of the key should work
+  KeyImpl(id1Key1Name, id1Key2, pibImpl); // overwriting of the key should work
   KeyImpl key2(id1Key1Name, pibImpl);
 
-  BOOST_CHECK(key1.getPublicKey() != key2.getPublicKey()); // key1 cached the original public key
-  BOOST_CHECK(key2.getPublicKey() == id1Key2);
+  Buffer key1buf(key1.getPublicKey().begin(), key1.getPublicKey().end());
+  Buffer key2buf(key2.getPublicKey().begin(), key2.getPublicKey().end());
+  BOOST_CHECK(key1buf != key2buf); // key1 cached the original public key
+  BOOST_CHECK(key2buf == id1Key2);
 
   key1.addCertificate(id1Key1Cert1);
   BOOST_CHECK_EQUAL(key1.getCertificate(id1Key1Cert1.getName()), id1Key1Cert1);
@@ -172,12 +176,12 @@
   auto pibImpl = make_shared<pib::PibMemory>();
 
   BOOST_CHECK_THROW(KeyImpl(id1Key1Name, pibImpl), Pib::Error);
-  KeyImpl key11(id1Key1Name, id1Key1.data(), id1Key1.size(), pibImpl);
+  KeyImpl key11(id1Key1Name, id1Key1, pibImpl);
 
   BOOST_CHECK_THROW(KeyImpl(Name("/wrong"), pibImpl), std::invalid_argument);
-  BOOST_CHECK_THROW(KeyImpl(Name("/wrong"), id1Key1.data(), id1Key1.size(), pibImpl), std::invalid_argument);
+  BOOST_CHECK_THROW(KeyImpl(Name("/wrong"), id1Key1, pibImpl), std::invalid_argument);
   Buffer wrongKey;
-  BOOST_CHECK_THROW(KeyImpl(id1Key2Name, wrongKey.data(), wrongKey.size(), pibImpl), std::invalid_argument);
+  BOOST_CHECK_THROW(KeyImpl(id1Key2Name, wrongKey, pibImpl), std::invalid_argument);
 
   key11.addCertificate(id1Key1Cert1);
   BOOST_CHECK_THROW(key11.addCertificate(id1Key2Cert1), std::invalid_argument);
diff --git a/tests/unit/security/pib/key-container.t.cpp b/tests/unit/security/pib/key-container.t.cpp
index 1a66573..25188a2 100644
--- a/tests/unit/security/pib/key-container.t.cpp
+++ b/tests/unit/security/pib/key-container.t.cpp
@@ -49,25 +49,28 @@
   BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 0);
 
   // add the first key
-  Key key11 = container.add(id1Key1.data(), id1Key1.size(), id1Key1Name);
+  Key key11 = container.add(id1Key1, id1Key1Name);
   BOOST_CHECK_EQUAL(key11.getName(), id1Key1Name);
-  BOOST_CHECK(key11.getPublicKey() == id1Key1);
+  BOOST_CHECK_EQUAL_COLLECTIONS(key11.getPublicKey().begin(), key11.getPublicKey().end(),
+                                id1Key1.begin(), id1Key1.end());
   BOOST_CHECK_EQUAL(container.size(), 1);
   BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 1);
   BOOST_CHECK(container.find(id1Key1Name) != container.end());
 
   // add the same key again
-  Key key12 = container.add(id1Key1.data(), id1Key1.size(), id1Key1Name);
+  Key key12 = container.add(id1Key1, id1Key1Name);
   BOOST_CHECK_EQUAL(key12.getName(), id1Key1Name);
-  BOOST_CHECK(key12.getPublicKey() == id1Key1);
+  BOOST_CHECK_EQUAL_COLLECTIONS(key12.getPublicKey().begin(), key12.getPublicKey().end(),
+                                id1Key1.begin(), id1Key1.end());
   BOOST_CHECK_EQUAL(container.size(), 1);
   BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 1);
   BOOST_CHECK(container.find(id1Key1Name) != container.end());
 
   // add the second key
-  Key key21 = container.add(id1Key2.data(), id1Key2.size(), id1Key2Name);
+  Key key21 = container.add(id1Key2, id1Key2Name);
   BOOST_CHECK_EQUAL(key21.getName(), id1Key2Name);
-  BOOST_CHECK(key21.getPublicKey() == id1Key2);
+  BOOST_CHECK_EQUAL_COLLECTIONS(key21.getPublicKey().begin(), key21.getPublicKey().end(),
+                                id1Key2.begin(), id1Key2.end());
   BOOST_CHECK_EQUAL(container.size(), 2);
   BOOST_CHECK_EQUAL(container.getLoadedKeys().size(), 2);
   BOOST_CHECK(container.find(id1Key1Name) != container.end());
@@ -83,9 +86,11 @@
   Key key1 = container.get(id1Key1Name);
   Key key2 = container.get(id1Key2Name);
   BOOST_CHECK_EQUAL(key1.getName(), id1Key1Name);
-  BOOST_CHECK(key1.getPublicKey() == id1Key1);
+  BOOST_CHECK_EQUAL_COLLECTIONS(key1.getPublicKey().begin(), key1.getPublicKey().end(),
+                                id1Key1.begin(), id1Key1.end());
   BOOST_CHECK_EQUAL(key2.getName(), id1Key2Name);
-  BOOST_CHECK(key2.getPublicKey() == id1Key2);
+  BOOST_CHECK_EQUAL_COLLECTIONS(key2.getPublicKey().begin(), key2.getPublicKey().end(),
+                                id1Key2.begin(), id1Key2.end());
 
   // create another container from the same PibImpl
   // cache should be empty
@@ -122,7 +127,7 @@
 
   KeyContainer container(id1, pibImpl);
 
-  BOOST_CHECK_THROW(container.add(id2Key1.data(), id2Key1.size(), id2Key1Name), std::invalid_argument);
+  BOOST_CHECK_THROW(container.add(id2Key1, id2Key1Name), std::invalid_argument);
   BOOST_CHECK_THROW(container.remove(id2Key1Name), std::invalid_argument);
   BOOST_CHECK_THROW(container.get(id2Key1Name), std::invalid_argument);
 }
@@ -132,8 +137,8 @@
   auto pibImpl = make_shared<PibMemory>();
   KeyContainer container(id1, pibImpl);
 
-  container.add(id1Key1.data(), id1Key1.size(), id1Key1Name);
-  container.add(id1Key2.data(), id1Key2.size(), id1Key2Name);
+  container.add(id1Key1, id1Key1Name);
+  container.add(id1Key2, id1Key2Name);
 
   std::set<Name> keyNames;
   keyNames.insert(id1Key1Name);
diff --git a/tests/unit/security/pib/key.t.cpp b/tests/unit/security/pib/key.t.cpp
index 544848f..8d0244f 100644
--- a/tests/unit/security/pib/key.t.cpp
+++ b/tests/unit/security/pib/key.t.cpp
@@ -44,8 +44,8 @@
   BOOST_CHECK(!key);
   BOOST_CHECK_EQUAL(static_cast<bool>(key), false);
 
-  auto keyImpl = make_shared<detail::KeyImpl>(id1Key1Name, id1Key1.data(), id1Key1.size(),
-                                              make_shared<pib::PibMemory>());
+  auto keyImpl = std::make_shared<detail::KeyImpl>(id1Key1Name, id1Key1,
+                                                   std::make_shared<pib::PibMemory>());
   key = Key(keyImpl);
   BOOST_CHECK(key);
   BOOST_CHECK_EQUAL(!key, false);
@@ -56,8 +56,8 @@
 // of pib::Key in this test case.
 BOOST_AUTO_TEST_CASE(SharedImpl)
 {
-  auto keyImpl = make_shared<detail::KeyImpl>(id1Key1Name, id1Key1.data(), id1Key1.size(),
-                                              make_shared<pib::PibMemory>());
+  auto keyImpl = std::make_shared<detail::KeyImpl>(id1Key1Name, id1Key1,
+                                                   std::make_shared<pib::PibMemory>());
   Key key1(keyImpl);
   Key key2(keyImpl);
   BOOST_CHECK_EQUAL(key1, key2);
diff --git a/tests/unit/security/pib/pib-data-fixture.cpp b/tests/unit/security/pib/pib-data-fixture.cpp
index b641f31..d27c742 100644
--- a/tests/unit/security/pib/pib-data-fixture.cpp
+++ b/tests/unit/security/pib/pib-data-fixture.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -37,18 +37,13 @@
 // class TestCertDataGenerator
 // {
 // public:
-//   TestCertDataGenerator()
-//     : tpm("test", "test", make_unique<tpm::BackEndMem>())
-//   {
-//   }
-
 //   void
 //   printTestDataForId(const std::string& prefix, const Name& id)
 //   {
-//     for (int keyId : {1, 2}) {
+//     for (auto keyId : {1u, 2u}) {
 //       Name keyName = tpm.createKey(id, EcKeyParams(name::Component::fromNumber(keyId)));
 
-//       for (int certVersion : {1, 2}) {
+//       for (auto certVersion : {1u, 2u}) {
 //         Name certName = keyName;
 //         certName
 //           .append("issuer")
@@ -79,22 +74,16 @@
 //   static void
 //   printBytes(const std::string& name, const Block& block)
 //   {
-//     printBytes(name, block.wire(), block.size());
+//     printBytes(name, make_span(block.wire(), block.size()));
 //   }
 
 //   static void
-//   printBytes(const std::string& name, const Buffer& buffer)
-//   {
-//     printBytes(name, buffer.data(), buffer.size());
-//   }
-
-//   static void
-//   printBytes(const std::string& name, const uint8_t* buf, size_t size)
+//   printBytes(const std::string& name, span<const uint8_t> buf)
 //   {
 //     std::cout << "\nconst uint8_t " << name << "[] = {\n"
 //               << "  ";
 
-//     std::string hex = toHex(buf, size);
+//     std::string hex = toHex(buf);
 
 //     for (size_t i = 0; i < hex.size(); i++) {
 //       if (i > 0 && i % 40 == 0)
@@ -103,7 +92,7 @@
 //       std::cout << "0x" << hex[i];
 //       std::cout << hex[++i];
 
-//       if ((i + 1) != hex.size())
+//       if (i + 1 != hex.size())
 //         std::cout << ", ";
 //     }
 //     std::cout << "\n"
@@ -112,7 +101,7 @@
 
 // private:
 //   pib::PibMemory pib;
-//   Tpm tpm;
+//   Tpm tpm{"test", "test", make_unique<tpm::BackEndMem>()};
 // };
 
 // // The test data can be generated using this test case
diff --git a/tests/unit/security/pib/pib-impl.t.cpp b/tests/unit/security/pib/pib-impl.t.cpp
index 971d995..097b1c0 100644
--- a/tests/unit/security/pib/pib-impl.t.cpp
+++ b/tests/unit/security/pib/pib-impl.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -163,7 +163,7 @@
   BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), false);
 
   // add id1Key1, should be default, id1 should be added implicitly
-  this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1.data(), this->id1Key1.size());
+  this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1);
   BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true);
   BOOST_CHECK_EQUAL(this->pib.hasIdentity(this->id1), true);
   const Buffer& keyBits = this->pib.getKeyBits(this->id1Key1Name);
@@ -172,7 +172,7 @@
   BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key1Name);
 
   // add id1Key2, should not be default
-  this->pib.addKey(this->id1, this->id1Key2Name, this->id1Key2.data(), this->id1Key2.size());
+  this->pib.addKey(this->id1, this->id1Key2Name, this->id1Key2);
   BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key2Name), true);
   BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key1Name);
 
@@ -191,7 +191,7 @@
   BOOST_CHECK_THROW(this->pib.getDefaultKeyOfIdentity(this->id1), Pib::Error);
 
   // add id1Key2 back, should be default
-  this->pib.addKey(this->id1, this->id1Key2Name, this->id1Key2.data(), this->id1Key2.size());
+  this->pib.addKey(this->id1, this->id1Key2Name, this->id1Key2);
   BOOST_CHECK_NO_THROW(this->pib.getKeyBits(this->id1Key2Name));
   BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id1), this->id1Key2Name);
 
@@ -274,11 +274,11 @@
   this->pib.removeIdentity(this->id1);
   BOOST_CHECK_THROW(this->pib.getDefaultIdentity(), Pib::Error);
 
-  this->pib.addKey(this->id2, this->id2Key1Name, this->id2Key1.data(), this->id2Key1.size());
+  this->pib.addKey(this->id2, this->id2Key1Name, this->id2Key1);
   BOOST_CHECK_EQUAL(this->pib.getDefaultIdentity(), this->id2);
   BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id2), this->id2Key1Name);
 
-  this->pib.addKey(this->id2, this->id2Key2Name, this->id2Key2.data(), this->id2Key2.size());
+  this->pib.addKey(this->id2, this->id2Key2Name, this->id2Key2);
   BOOST_CHECK_EQUAL(this->pib.getDefaultKeyOfIdentity(this->id2), this->id2Key1Name);
 
   this->pib.removeKey(this->id2Key1Name);
@@ -305,13 +305,13 @@
   BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), false);
 
   // add id1Key1
-  this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1.data(), this->id1Key1.size());
+  this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1);
   BOOST_CHECK_EQUAL(this->pib.hasKey(this->id1Key1Name), true);
   const Buffer& keyBits = this->pib.getKeyBits(this->id1Key1Name);
   BOOST_CHECK(keyBits == this->id1Key1);
 
   // check overwrite, add a key with the same name.
-  this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key2.data(), this->id1Key2.size());
+  this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key2);
   const Buffer& keyBits2 = this->pib.getKeyBits(this->id1Key1Name);
   BOOST_CHECK(keyBits2 == this->id1Key2);
 
@@ -320,7 +320,7 @@
   BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert1.getName()), false);
 
   // add id1Key1Cert1
-  this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1.data(), this->id1Key1.size());
+  this->pib.addKey(this->id1, this->id1Key1Name, this->id1Key1);
   this->pib.addCertificate(this->id1Key1Cert1);
   BOOST_CHECK_EQUAL(this->pib.hasCertificate(this->id1Key1Cert1.getName()), true);
 
diff --git a/tests/unit/security/safe-bag.t.cpp b/tests/unit/security/safe-bag.t.cpp
index 53f28cf..c3cc7c2 100644
--- a/tests/unit/security/safe-bag.t.cpp
+++ b/tests/unit/security/safe-bag.t.cpp
@@ -72,7 +72,7 @@
           0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
 };
 
-const uint8_t ENCRYPTED_KEY_BAG[] = {
+const uint8_t ENCRYPTED_KEY[] = {
   0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe
 };
 
@@ -121,29 +121,24 @@
 
 BOOST_AUTO_TEST_CASE(Constructor)
 {
-  Block dataBlock(CERT, sizeof(CERT));
-  Data data(dataBlock);
-  SafeBag safeBag1(data, ENCRYPTED_KEY_BAG, sizeof(ENCRYPTED_KEY_BAG));
-
-  Block safeBagBlock(SAFE_BAG, sizeof(SAFE_BAG));
-  SafeBag safeBag2(safeBagBlock);
-
-  Buffer buffer(ENCRYPTED_KEY_BAG, sizeof(ENCRYPTED_KEY_BAG));
-  SafeBag safeBag3(data, buffer);
+  Data data(Block(CERT, sizeof(CERT)));
+  SafeBag safeBag1(data, ENCRYPTED_KEY);
+  SafeBag safeBag2(Block(SAFE_BAG, sizeof(SAFE_BAG)));
+  auto encKey = make_span(ENCRYPTED_KEY);
 
   BOOST_CHECK(safeBag1.getCertificate() == data);
-  BOOST_CHECK(safeBag1.getEncryptedKey() == buffer);
+  BOOST_CHECK_EQUAL_COLLECTIONS(safeBag1.getEncryptedKey().begin(), safeBag1.getEncryptedKey().end(),
+                                encKey.begin(), encKey.end());
   BOOST_CHECK(safeBag2.getCertificate() == data);
-  BOOST_CHECK(safeBag2.getEncryptedKey() == buffer);
-  BOOST_CHECK(safeBag3.getCertificate() == data);
-  BOOST_CHECK(safeBag3.getEncryptedKey() == buffer);
+  BOOST_CHECK_EQUAL_COLLECTIONS(safeBag2.getEncryptedKey().begin(), safeBag2.getEncryptedKey().end(),
+                                encKey.begin(), encKey.end());
 }
 
 BOOST_AUTO_TEST_CASE(EncoderAndDecoder)
 {
   Block dataBlock(CERT, sizeof(CERT));
   Data data(dataBlock);
-  SafeBag safeBag(data, ENCRYPTED_KEY_BAG, sizeof(ENCRYPTED_KEY_BAG));
+  SafeBag safeBag(data, ENCRYPTED_KEY);
 
   // wire encode
   Block wireBlock = safeBag.wireEncode();
@@ -157,8 +152,8 @@
   safeBag2.wireDecode(wireBlock);
 
   // check equal
-  Buffer buffer1 = safeBag2.getEncryptedKey();
-  Buffer buffer2(ENCRYPTED_KEY_BAG, sizeof(ENCRYPTED_KEY_BAG));
+  Buffer buffer1(safeBag2.getEncryptedKey().begin(), safeBag2.getEncryptedKey().end());
+  Buffer buffer2(ENCRYPTED_KEY, sizeof(ENCRYPTED_KEY));
   BOOST_CHECK(buffer1 == buffer2);
 }
 
diff --git a/tests/unit/security/tpm/back-end.t.cpp b/tests/unit/security/tpm/back-end.t.cpp
index 3b08c62..0b22d54 100644
--- a/tests/unit/security/tpm/back-end.t.cpp
+++ b/tests/unit/security/tpm/back-end.t.cpp
@@ -121,37 +121,34 @@
   Name keyName = key->getKeyName();
 
   transform::PublicKey pubKey;
-  ConstBufferPtr pubKeyBits = key->derivePublicKey();
-  pubKey.loadPkcs8(pubKeyBits->data(), pubKeyBits->size());
+  auto pubKeyBits = key->derivePublicKey();
+  pubKey.loadPkcs8(*pubKeyBits);
 
-  // Sign using single buffer API
+  // Sign a single buffer
   const uint8_t content1[] = {0x01, 0x02, 0x03, 0x04};
-  auto sigValueSingle = key->sign(DigestAlgorithm::SHA256, content1, sizeof(content1));
+  auto sigValueSingle = key->sign(DigestAlgorithm::SHA256, {content1});
   BOOST_REQUIRE(sigValueSingle != nullptr);
 
   bool resultSingle;
   {
     using namespace transform;
-    bufferSource(content1, sizeof(content1)) >>
-      verifierFilter(DigestAlgorithm::SHA256, pubKey,
-                     sigValueSingle->data(), sigValueSingle->size()) >>
-      boolSink(resultSingle);
+    bufferSource(content1)
+      >> verifierFilter(DigestAlgorithm::SHA256, pubKey, sigValueSingle->data(), sigValueSingle->size())
+      >> boolSink(resultSingle);
   }
   BOOST_CHECK_EQUAL(resultSingle, true);
 
-  // Sign using vectored API
+  // Sign multiple buffers
   const uint8_t content2[] = {0x05, 0x06, 0x07, 0x08};
-  auto sigValueVector = key->sign(DigestAlgorithm::SHA256, {{content1, sizeof(content1)},
-                                                            {content2, sizeof(content2)}});
+  auto sigValueVector = key->sign(DigestAlgorithm::SHA256, {content1, content2});
   BOOST_REQUIRE(sigValueVector != nullptr);
 
   bool resultVector;
   {
     using namespace transform;
-    bufferSource({{content1, sizeof(content1)}, {content2, sizeof(content2)}}) >>
-      verifierFilter(DigestAlgorithm::SHA256, pubKey,
-                     sigValueVector->data(), sigValueVector->size()) >>
-      boolSink(resultVector);
+    bufferSource(InputBuffers{content1, content2})
+      >> verifierFilter(DigestAlgorithm::SHA256, pubKey, sigValueVector->data(), sigValueVector->size())
+      >> boolSink(resultVector);
   }
   BOOST_CHECK_EQUAL(resultVector, true);
 
@@ -172,11 +169,11 @@
   const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
 
   transform::PublicKey pubKey;
-  ConstBufferPtr pubKeyBits = key->derivePublicKey();
-  pubKey.loadPkcs8(pubKeyBits->data(), pubKeyBits->size());
+  auto pubKeyBits = key->derivePublicKey();
+  pubKey.loadPkcs8(*pubKeyBits);
 
-  ConstBufferPtr cipherText = pubKey.encrypt(content, sizeof(content));
-  ConstBufferPtr plainText = key->decrypt(cipherText->data(), cipherText->size());
+  ConstBufferPtr cipherText = pubKey.encrypt(content);
+  ConstBufferPtr plainText = key->decrypt(*cipherText);
 
   BOOST_CHECK_EQUAL_COLLECTIONS(content, content + sizeof(content),
                                 plainText->begin(), plainText->end());
@@ -196,37 +193,34 @@
   Name ecKeyName = key->getKeyName();
 
   transform::PublicKey pubKey;
-  ConstBufferPtr pubKeyBits = key->derivePublicKey();
-  pubKey.loadPkcs8(pubKeyBits->data(), pubKeyBits->size());
+  auto pubKeyBits = key->derivePublicKey();
+  pubKey.loadPkcs8(*pubKeyBits);
 
-  // Sign using single buffer API
+  // Sign a single buffer
   const uint8_t content1[] = {0x01, 0x02, 0x03, 0x04};
-  auto sigValueSingle = key->sign(DigestAlgorithm::SHA256, content1, sizeof(content1));
+  auto sigValueSingle = key->sign(DigestAlgorithm::SHA256, {content1});
   BOOST_REQUIRE(sigValueSingle != nullptr);
 
   bool resultSingle;
   {
     using namespace transform;
-    bufferSource(content1, sizeof(content1)) >>
-      verifierFilter(DigestAlgorithm::SHA256, pubKey,
-                     sigValueSingle->data(), sigValueSingle->size()) >>
-      boolSink(resultSingle);
+    bufferSource(content1)
+      >> verifierFilter(DigestAlgorithm::SHA256, pubKey, sigValueSingle->data(), sigValueSingle->size())
+      >> boolSink(resultSingle);
   }
   BOOST_CHECK_EQUAL(resultSingle, true);
 
-  // Sign using vectored API
+  // Sign multiple buffers
   const uint8_t content2[] = {0x05, 0x06, 0x07, 0x08};
-  auto sigValueVector = key->sign(DigestAlgorithm::SHA256, {{content1, sizeof(content1)},
-                                                            {content2, sizeof(content2)}});
+  auto sigValueVector = key->sign(DigestAlgorithm::SHA256, {content1, content2});
   BOOST_REQUIRE(sigValueVector != nullptr);
 
   bool resultVector;
   {
     using namespace transform;
-    bufferSource({{content1, sizeof(content1)}, {content2, sizeof(content2)}}) >>
-      verifierFilter(DigestAlgorithm::SHA256, pubKey,
-                     sigValueVector->data(), sigValueVector->size()) >>
-      boolSink(resultVector);
+    bufferSource(InputBuffers{content1, content2})
+      >> verifierFilter(DigestAlgorithm::SHA256, pubKey, sigValueVector->data(), sigValueVector->size())
+      >> boolSink(resultVector);
   }
   BOOST_CHECK_EQUAL(resultVector, true);
 
@@ -245,23 +239,18 @@
   unique_ptr<KeyHandle> key = tpm.createKey(identity, HmacKeyParams());
   Name hmacKeyName = key->getKeyName();
 
-  // Sign and verify using single buffer API
+  // Sign and verify a single buffer
   const uint8_t content1[] = {0x01, 0x02, 0x03, 0x04};
-  auto sigValueSingle = key->sign(DigestAlgorithm::SHA256, content1, sizeof(content1));
+  auto sigValueSingle = key->sign(DigestAlgorithm::SHA256, {content1});
   BOOST_REQUIRE(sigValueSingle != nullptr);
-  bool resultSingle = key->verify(DigestAlgorithm::SHA256, content1, sizeof(content1),
-                                  sigValueSingle->data(), sigValueSingle->size());
+  bool resultSingle = key->verify(DigestAlgorithm::SHA256, {content1}, *sigValueSingle);
   BOOST_CHECK_EQUAL(resultSingle, true);
 
-  // Sign and verify using vectored API
+  // Sign and verify multiple buffers
   const uint8_t content2[] = {0x05, 0x06, 0x07, 0x08};
-  auto sigValueVector = key->sign(DigestAlgorithm::SHA256, {{content1, sizeof(content1)},
-                                                            {content2, sizeof(content2)}});
+  auto sigValueVector = key->sign(DigestAlgorithm::SHA256, {content1, content2});
   BOOST_REQUIRE(sigValueVector != nullptr);
-  bool resultVector = key->verify(DigestAlgorithm::SHA256,
-                                  {{content1, sizeof(content1)},
-                                   {content2, sizeof(content2)}},
-                                  sigValueVector->data(), sigValueVector->size());
+  bool resultVector = key->verify(DigestAlgorithm::SHA256, {content1, content2}, *sigValueVector);
   BOOST_CHECK_EQUAL(resultVector, true);
 
   tpm.deleteKey(hmacKeyName);
@@ -308,22 +297,22 @@
   BOOST_REQUIRE_EQUAL(tpm.hasKey(keyName), false);
 
   transform::PrivateKey sKey;
-  sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privKeyPkcs1.data()), privKeyPkcs1.size());
+  sKey.loadPkcs1Base64({reinterpret_cast<const uint8_t*>(privKeyPkcs1.data()), privKeyPkcs1.size()});
   OBufferStream os;
   sKey.savePkcs8(os, password.data(), password.size());
   auto pkcs8 = os.buf();
 
   // import with wrong password
-  BOOST_CHECK_THROW(tpm.importKey(keyName, pkcs8->data(), pkcs8->size(), wrongPassword.data(), wrongPassword.size()),
+  BOOST_CHECK_THROW(tpm.importKey(keyName, *pkcs8, wrongPassword.data(), wrongPassword.size()),
                     Tpm::Error);
   BOOST_CHECK_EQUAL(tpm.hasKey(keyName), false);
 
   // import with correct password
-  tpm.importKey(keyName, pkcs8->data(), pkcs8->size(), password.data(), password.size());
+  tpm.importKey(keyName, *pkcs8, password.data(), password.size());
   BOOST_CHECK_EQUAL(tpm.hasKey(keyName), true);
 
   // import already present key
-  BOOST_CHECK_THROW(tpm.importKey(keyName, pkcs8->data(), pkcs8->size(), password.data(), password.size()),
+  BOOST_CHECK_THROW(tpm.importKey(keyName, *pkcs8, password.data(), password.size()),
                     Tpm::Error);
 
   // test derivePublicKey with the imported key
@@ -336,7 +325,7 @@
   BOOST_CHECK_EQUAL(tpm.hasKey(keyName), true);
 
   transform::PrivateKey sKey2;
-  sKey2.loadPkcs8(exportedKey->data(), exportedKey->size(), password.data(), password.size());
+  sKey2.loadPkcs8(*exportedKey, password.data(), password.size());
   OBufferStream os2;
   sKey.savePkcs1Base64(os2);
   auto pkcs1 = os2.buf();
diff --git a/tests/unit/security/transform/base64-decode.t.cpp b/tests/unit/security/transform/base64-decode.t.cpp
index 93d09c2..5d89fe6 100644
--- a/tests/unit/security/transform/base64-decode.t.cpp
+++ b/tests/unit/security/transform/base64-decode.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -38,12 +38,11 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  std::string in =
+  const std::string in =
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=\n";
-
-  uint8_t out[] = {
+  const 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,
@@ -71,12 +70,11 @@
 
 BOOST_AUTO_TEST_CASE(NoNewLine)
 {
-  std::string in =
+  const std::string in =
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=";
-
-  uint8_t out[] = {
+  const 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,
@@ -104,7 +102,7 @@
 
 BOOST_AUTO_TEST_CASE(StepByStep)
 {
-  std::string in =
+  const std::string in =
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
@@ -113,8 +111,7 @@
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n";
-
-  uint8_t out[] = {
+  const 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,
@@ -145,17 +142,17 @@
   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.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();
@@ -168,6 +165,7 @@
   StepSource source;
   source >> base64Decode() >> streamSink(os);
   source.end();
+
   BOOST_CHECK_EQUAL(os.buf()->size(), 0);
 }
 
diff --git a/tests/unit/security/transform/base64-encode.t.cpp b/tests/unit/security/transform/base64-encode.t.cpp
index 228f214..7b4aa47 100644
--- a/tests/unit/security/transform/base64-encode.t.cpp
+++ b/tests/unit/security/transform/base64-encode.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -39,7 +39,7 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  uint8_t in[] = {
+  const 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,
@@ -57,14 +57,13 @@
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
   };
-
-  std::string out =
+  const std::string out =
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=\n";
 
   OBufferStream os;
-  bufferSource(in, sizeof(in)) >> base64Encode() >> streamSink(os);
+  bufferSource(in) >> base64Encode() >> streamSink(os);
 
   ConstBufferPtr buf1 = os.buf();
   BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
@@ -72,7 +71,7 @@
 
 BOOST_AUTO_TEST_CASE(NoNewLine)
 {
-  uint8_t in[] = {
+  const 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,
@@ -90,14 +89,13 @@
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
   };
-
-  std::string out =
+  const std::string out =
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8=";
 
   OBufferStream os;
-  BufferSource(in, sizeof(in)) >> base64Encode(false) >> streamSink(os);
+  BufferSource(in) >> base64Encode(false) >> streamSink(os);
 
   ConstBufferPtr buf1 = os.buf();
   BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
@@ -105,7 +103,7 @@
 
 BOOST_AUTO_TEST_CASE(StepByStep)
 {
-  uint8_t in[] = {
+  const 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,
@@ -131,8 +129,7 @@
     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 =
+  const std::string out =
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
     "AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8AAQIDBAUGBwgJCgsMDQ4P\n"
@@ -145,15 +142,15 @@
   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.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();
@@ -166,6 +163,7 @@
   StepSource source;
   source >> base64Encode() >> streamSink(os);
   source.end();
+
   BOOST_CHECK_EQUAL(os.buf()->size(), 0);
 }
 
diff --git a/tests/unit/security/transform/block-cipher.t.cpp b/tests/unit/security/transform/block-cipher.t.cpp
index 12b20bb..60944ad 100644
--- a/tests/unit/security/transform/block-cipher.t.cpp
+++ b/tests/unit/security/transform/block-cipher.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -67,7 +67,7 @@
 
   // encrypt
   OBufferStream os;
-  bufferSource(plainText, sizeof(plainText)) >>
+  bufferSource(plainText) >>
     blockCipher(BlockCipherAlgorithm::AES_CBC, CipherOperator::ENCRYPT,
                 key, sizeof(key), iv, sizeof(iv)) >> streamSink(os);
 
@@ -77,7 +77,7 @@
 
   // decrypt
   OBufferStream os2;
-  bufferSource(cipherText, sizeof(cipherText)) >>
+  bufferSource(cipherText) >>
     blockCipher(BlockCipherAlgorithm::AES_CBC, CipherOperator::DECRYPT,
                 key, sizeof(key), iv, sizeof(iv)) >> streamSink(os2);
 
diff --git a/tests/unit/security/transform/bool-sink.t.cpp b/tests/unit/security/transform/bool-sink.t.cpp
index f287e1c..a7640c6 100644
--- a/tests/unit/security/transform/bool-sink.t.cpp
+++ b/tests/unit/security/transform/bool-sink.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -34,23 +34,23 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  uint8_t in1[] = {0x00, 0x01};
+  const uint8_t in1[] = {0x00, 0x01};
   bool value1 = true;
   BoolSink sink1(value1);
-  BOOST_CHECK_EQUAL(sink1.write(in1, 1), 1);
-  BOOST_CHECK_EQUAL(sink1.write(in1 + 1, 1), 1);
+  BOOST_CHECK_EQUAL(sink1.write({in1, 1}), 1);
+  BOOST_CHECK_EQUAL(sink1.write({in1 + 1, 1}), 1);
   sink1.end();
   BOOST_CHECK_EQUAL(value1, false);
-  BOOST_CHECK_THROW(sink1.write(in1 + 1, 1), transform::Error);
+  BOOST_CHECK_THROW(sink1.write({in1 + 1, 1}), transform::Error);
 
-  uint8_t in2[] = {0x01, 0x00};
+  const uint8_t in2[] = {0x01, 0x00};
   bool value2 = false;
   BoolSink sink2(value2);
-  BOOST_CHECK_EQUAL(sink2.write(in2, 1), 1);
-  BOOST_CHECK_EQUAL(sink2.write(in2 + 1, 1), 1);
+  BOOST_CHECK_EQUAL(sink2.write({in2, 1}), 1);
+  BOOST_CHECK_EQUAL(sink2.write({in2 + 1, 1}), 1);
   sink2.end();
   BOOST_CHECK_EQUAL(value2, true);
-  BOOST_CHECK_THROW(sink2.write(in2 + 1, 1), transform::Error);
+  BOOST_CHECK_THROW(sink2.write({in2 + 1, 1}), transform::Error);
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestBoolSink
diff --git a/tests/unit/security/transform/buffer-source.t.cpp b/tests/unit/security/transform/buffer-source.t.cpp
index 8f1a23e..4c56591 100644
--- a/tests/unit/security/transform/buffer-source.t.cpp
+++ b/tests/unit/security/transform/buffer-source.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -35,17 +35,16 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  uint8_t in[16] = {
+  const uint8_t in[] = {
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
   };
-
   std::ostringstream os1;
-  bufferSource(in, sizeof(in)) >> streamSink(os1);
+  bufferSource(in) >> streamSink(os1);
   std::string out1 = os1.str();
   BOOST_CHECK_EQUAL_COLLECTIONS(out1.begin(), out1.end(), in, in + sizeof(in));
 
-  std::string in2 =
+  const std::string in2 =
     "0123456701234567012345670123456701234567012345670123456701234567"
     "0123456701234567012345670123456701234567012345670123456701234567"
     "0123456701234567012345670123456701234567012345670123456701234567"
@@ -66,27 +65,26 @@
     "0123456701234567012345670123456701234567012345670123456701234567"
     "0123456701234567012345670123456701234567012345670123456701234567"
     "0123456701234567012345670123456701234567012345670123456701234567";
-
   std::ostringstream os2;
   bufferSource(in2) >> streamSink(os2);
   std::string out2 = os2.str();
   BOOST_CHECK_EQUAL_COLLECTIONS(out2.begin(), out2.end(), in2.begin(), in2.end());
 
-  Buffer in3(in, sizeof(in));
+  std::vector<uint8_t> in3(in, in + sizeof(in));
   std::ostringstream os3;
   bufferSource(in3) >> streamSink(os3);
   std::string out3 = os3.str();
   BOOST_CHECK_EQUAL_COLLECTIONS(out3.begin(), out3.end(), in3.begin(), in3.end());
 
-  InputBuffers in4{{in, sizeof(in)}, {reinterpret_cast<const uint8_t*>(in2.data()), in2.size()}};
+  InputBuffers in4{make_span(in), {reinterpret_cast<const uint8_t*>(in2.data()), in2.size()}};
   std::ostringstream os4;
   bufferSource(in4) >> streamSink(os4);
   std::string out4 = os4.str();
   BOOST_CHECK_EQUAL(out4.size(), sizeof(in) + in2.size());
-  BOOST_CHECK_EQUAL_COLLECTIONS(out4.begin(), out4.begin() + in4[0].second,
-                                in4[0].first, in4[0].first + in4[0].second);
-  BOOST_CHECK_EQUAL_COLLECTIONS(out4.begin() + in4[0].second, out4.end(),
-                                in4[1].first, in4[1].first + in4[1].second);
+  BOOST_CHECK_EQUAL_COLLECTIONS(out4.begin(), out4.begin() + sizeof(in),
+                                in4[0].begin(), in4[0].end());
+  BOOST_CHECK_EQUAL_COLLECTIONS(out4.begin() + sizeof(in), out4.end(),
+                                in4[1].begin(), in4[1].end());
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestBufferSource
diff --git a/tests/unit/security/transform/digest-filter.t.cpp b/tests/unit/security/transform/digest-filter.t.cpp
index 984611d..fa109bb 100644
--- a/tests/unit/security/transform/digest-filter.t.cpp
+++ b/tests/unit/security/transform/digest-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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -66,7 +66,7 @@
 BOOST_AUTO_TEST_CASE(BufferInput)
 {
   OBufferStream os;
-  bufferSource(in, sizeof(in)) >> digestFilter(DigestAlgorithm::SHA256) >> streamSink(os);
+  bufferSource(in) >> digestFilter(DigestAlgorithm::SHA256) >> streamSink(os);
   BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
 }
 
@@ -75,12 +75,12 @@
   StepSource source;
   OBufferStream os;
   source >> digestFilter(DigestAlgorithm::SHA256) >> streamSink(os);
-  source.write(in, 32);
-  source.write(in + 32, 1);
-  source.write(in + 33, 2);
-  source.write(in + 35, 3);
-  source.write(in + 38, 26);
-  source.write(in + 64, 64);
+  source.write({in, 32});
+  source.write({in + 32, 1});
+  source.write({in + 33, 2});
+  source.write({in + 35, 3});
+  source.write({in + 38, 26});
+  source.write({in + 64, 64});
   source.end();
   BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), os.buf()->begin(), os.buf()->end());
 }
diff --git a/tests/unit/security/transform/hex-decode.t.cpp b/tests/unit/security/transform/hex-decode.t.cpp
index bd2e880..23ca9aa 100644
--- a/tests/unit/security/transform/hex-decode.t.cpp
+++ b/tests/unit/security/transform/hex-decode.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -39,13 +39,12 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  std::string in =
+  const std::string in =
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
-
-  uint8_t out[] = {
+  const 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,
@@ -73,13 +72,12 @@
 
 BOOST_AUTO_TEST_CASE(UpperCase)
 {
-  std::string in =
+  const std::string in =
     "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
     "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
     "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
     "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F";
-
-  uint8_t out[] = {
+  const 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,
@@ -107,7 +105,7 @@
 
 BOOST_AUTO_TEST_CASE(MixCase)
 {
-  std::string in =
+  const std::string in =
     "000102030405060708090a0b0c0d0e0f"
     "101112131415161718191a1b1c1d1e1f"
     "202122232425262728292a2b2c2d2e2f"
@@ -150,8 +148,7 @@
     "BaBbBcBdBeBfBABBBCBD"
     "CaCbCcCdCeCfCACBCCCD"
     "DaDbDcDdDeDfDADBDCDD";
-
-  uint8_t out[] = {
+  const 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,
@@ -203,10 +200,9 @@
   BOOST_CHECK_EQUAL_COLLECTIONS(out, out + sizeof(out), buf1->begin(), buf1->end());
 }
 
-
 BOOST_AUTO_TEST_CASE(StepByStep)
 {
-  std::string in =
+  const std::string in =
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
@@ -219,8 +215,7 @@
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
-
-  uint8_t out[] = {
+  const 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,
@@ -247,16 +242,16 @@
     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());
+  auto 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.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();
@@ -265,15 +260,13 @@
 
 BOOST_AUTO_TEST_CASE(OddByte)
 {
-  std::string in1 = "0001020304050";
-
+  const std::string in1 = "0001020304050";
   OBufferStream os1;
-  BOOST_REQUIRE_THROW(bufferSource(in1) >> hexDecode() >> streamSink(os1), transform::Error);
+  BOOST_CHECK_THROW(bufferSource(in1) >> hexDecode() >> streamSink(os1), transform::Error);
 
-  std::string in2 = "0001020304xy";
-
+  const std::string in2 = "0001020304xy";
   OBufferStream os2;
-  BOOST_REQUIRE_THROW(bufferSource(in2) >> hexDecode() >> streamSink(os2), transform::Error);
+  BOOST_CHECK_THROW(bufferSource(in2) >> hexDecode() >> streamSink(os2), transform::Error);
 }
 
 BOOST_AUTO_TEST_CASE(EmptyInput)
@@ -282,6 +275,7 @@
   StepSource source;
   source >> hexDecode() >> streamSink(os);
   source.end();
+
   BOOST_CHECK_EQUAL(os.buf()->size(), 0);
 }
 
diff --git a/tests/unit/security/transform/hex-encode.t.cpp b/tests/unit/security/transform/hex-encode.t.cpp
index 791fdd7..8025c37 100644
--- a/tests/unit/security/transform/hex-encode.t.cpp
+++ b/tests/unit/security/transform/hex-encode.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -38,7 +38,7 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  uint8_t in[128] = {
+  const 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,
@@ -56,15 +56,14 @@
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
   };
-
-  std::string out =
+  const std::string out =
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
 
   OBufferStream os;
-  bufferSource(in, sizeof(in)) >> hexEncode() >> streamSink(os);
+  bufferSource(in) >> hexEncode() >> streamSink(os);
 
   ConstBufferPtr buf1 = os.buf();
   BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
@@ -72,7 +71,7 @@
 
 BOOST_AUTO_TEST_CASE(UpperCase)
 {
-  uint8_t in[128] = {
+  const 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,
@@ -90,15 +89,14 @@
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
   };
-
-  std::string out =
+  const std::string out =
     "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
     "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
     "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
     "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F";
 
   OBufferStream os;
-  bufferSource(in, sizeof(in)) >> hexEncode(true) >> streamSink(os);
+  bufferSource(in) >> hexEncode(true) >> streamSink(os);
 
   ConstBufferPtr buf1 = os.buf();
   BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), buf1->begin(), buf1->end());
@@ -106,7 +104,7 @@
 
 BOOST_AUTO_TEST_CASE(StepByStep)
 {
-  uint8_t in[] = {
+  const 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,
@@ -132,8 +130,7 @@
     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 =
+  const std::string out =
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
@@ -150,15 +147,15 @@
   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.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();
@@ -171,6 +168,7 @@
   StepSource source;
   source >> hexEncode() >> streamSink(os);
   source.end();
+
   BOOST_CHECK_EQUAL(os.buf()->size(), 0);
 }
 
diff --git a/tests/unit/security/transform/private-key.t.cpp b/tests/unit/security/transform/private-key.t.cpp
index 042f571..87d39fe 100644
--- a/tests/unit/security/transform/private-key.t.cpp
+++ b/tests/unit/security/transform/private-key.t.cpp
@@ -56,8 +56,7 @@
   BOOST_CHECK_EQUAL(sKey.getKeySize(), 0);
   BOOST_CHECK_THROW(sKey.getKeyDigest(DigestAlgorithm::SHA256), PrivateKey::Error);
   BOOST_CHECK_THROW(sKey.derivePublicKey(), PrivateKey::Error);
-  const uint8_t theAnswer = 42;
-  BOOST_CHECK_THROW(sKey.decrypt(&theAnswer, sizeof(theAnswer)), PrivateKey::Error);
+  BOOST_CHECK_THROW(sKey.decrypt({}), PrivateKey::Error);
   std::ostringstream os;
   BOOST_CHECK_THROW(sKey.savePkcs1(os), PrivateKey::Error);
   std::string passwd("password");
@@ -69,7 +68,7 @@
 {
   const Buffer buf(16);
   PrivateKey sKey;
-  sKey.loadRaw(KeyType::HMAC, buf.data(), buf.size());
+  sKey.loadRaw(KeyType::HMAC, buf);
   auto digest = sKey.getKeyDigest(DigestAlgorithm::SHA256);
 
   const uint8_t expected[] = {
@@ -85,17 +84,17 @@
 {
   const Buffer buf(32);
   PrivateKey sKey;
-  sKey.loadRaw(KeyType::HMAC, buf.data(), buf.size());
+  sKey.loadRaw(KeyType::HMAC, buf);
 #if OPENSSL_VERSION_NUMBER < 0x30000000L // FIXME #5154
   BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::HMAC);
   BOOST_CHECK_EQUAL(sKey.getKeySize(), 256);
 #endif
 
   PrivateKey sKey2;
-  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::NONE, buf.data(), buf.size()), std::invalid_argument);
-  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::RSA, buf.data(), buf.size()), std::invalid_argument);
-  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::EC, buf.data(), buf.size()), std::invalid_argument);
-  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::AES, buf.data(), buf.size()), std::invalid_argument);
+  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::NONE, buf), std::invalid_argument);
+  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::RSA, buf), std::invalid_argument);
+  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::EC, buf), std::invalid_argument);
+  BOOST_CHECK_THROW(sKey2.loadRaw(KeyType::AES, buf), std::invalid_argument);
 }
 
 struct RsaKey_DesEncrypted
@@ -397,7 +396,7 @@
                    const ConstBufferPtr& pkcs1)
 {
   PrivateKey sKey;
-  sKey.loadPkcs8(encoding->data(), encoding->size(), password.data(), password.size());
+  sKey.loadPkcs8(*encoding, password.data(), password.size());
   OBufferStream os;
   sKey.savePkcs1(os);
   BOOST_CHECK_EQUAL_COLLECTIONS(pkcs1->begin(), pkcs1->end(),
@@ -418,17 +417,15 @@
 {
   T dataSet;
 
-  auto sKeyPkcs1Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data());
-  auto sKeyPkcs1Base64Len = dataSet.privateKeyPkcs1.size();
+  auto sKeyPkcs1Base64 = make_span(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
+                                   dataSet.privateKeyPkcs1.size());
   OBufferStream os;
-  bufferSource(sKeyPkcs1Base64, sKeyPkcs1Base64Len) >> base64Decode() >> streamSink(os);
-  ConstBufferPtr sKeyPkcs1Buf = os.buf();
-  const uint8_t* sKeyPkcs1 = sKeyPkcs1Buf->data();
-  size_t sKeyPkcs1Len = sKeyPkcs1Buf->size();
+  bufferSource(sKeyPkcs1Base64) >> base64Decode() >> streamSink(os);
+  auto sKeyPkcs1 = os.buf();
 
   // load key in base64-encoded pkcs1 format
   PrivateKey sKey;
-  BOOST_CHECK_NO_THROW(sKey.loadPkcs1Base64(sKeyPkcs1Base64, sKeyPkcs1Base64Len));
+  BOOST_CHECK_NO_THROW(sKey.loadPkcs1Base64(sKeyPkcs1Base64));
   BOOST_CHECK_EQUAL(sKey.getKeySize(), dataSet.keySize);
 
   std::stringstream ss2(dataSet.privateKeyPkcs1);
@@ -437,32 +434,31 @@
 
   // load key in pkcs1 format
   PrivateKey sKey3;
-  BOOST_CHECK_NO_THROW(sKey3.loadPkcs1(sKeyPkcs1, sKeyPkcs1Len));
+  BOOST_CHECK_NO_THROW(sKey3.loadPkcs1(*sKeyPkcs1));
   BOOST_CHECK_EQUAL(sKey3.getKeySize(), dataSet.keySize);
 
   std::stringstream ss4;
-  ss4.write(reinterpret_cast<const char*>(sKeyPkcs1), sKeyPkcs1Len);
+  ss4.write(reinterpret_cast<const char*>(sKeyPkcs1->data()), sKeyPkcs1->size());
   PrivateKey sKey4;
   BOOST_CHECK_NO_THROW(sKey4.loadPkcs1(ss4));
 
   // save key in base64-encoded pkcs1 format
   OBufferStream os2;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs1Base64(os2));
-  BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1Base64, sKeyPkcs1Base64 + sKeyPkcs1Base64Len,
+  BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1Base64.begin(), sKeyPkcs1Base64.end(),
                                 os2.buf()->begin(), os2.buf()->end());
 
   // save key in pkcs1 format
   OBufferStream os3;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs1(os3));
-  BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1, sKeyPkcs1 + sKeyPkcs1Len,
+  BOOST_CHECK_EQUAL_COLLECTIONS(sKeyPkcs1->begin(), sKeyPkcs1->end(),
                                 os3.buf()->begin(), os3.buf()->end());
 
-  auto sKeyPkcs8Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs8.data());
-  auto sKeyPkcs8Base64Len = dataSet.privateKeyPkcs8.size();
+  auto sKeyPkcs8Base64 = make_span(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs8.data()),
+                                   dataSet.privateKeyPkcs8.size());
   OBufferStream os4;
-  bufferSource(sKeyPkcs8Base64, sKeyPkcs8Base64Len) >> base64Decode() >> streamSink(os4);
-  const uint8_t* sKeyPkcs8 = os4.buf()->data();
-  size_t sKeyPkcs8Len = os4.buf()->size();
+  bufferSource(sKeyPkcs8Base64) >> base64Decode() >> streamSink(os4);
+  auto sKeyPkcs8 = os4.buf();
 
   std::string password("password");
   std::string wrongpw("wrongpw");
@@ -474,12 +470,11 @@
 
   // load key in base64-encoded pkcs8 format
   PrivateKey sKey5;
-  BOOST_CHECK_NO_THROW(sKey5.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len,
-                                             password.data(), password.size()));
+  BOOST_CHECK_NO_THROW(sKey5.loadPkcs8Base64(sKeyPkcs8Base64, password.data(), password.size()));
   BOOST_CHECK_EQUAL(sKey5.getKeySize(), dataSet.keySize);
 
   PrivateKey sKey6;
-  BOOST_CHECK_NO_THROW(sKey6.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len, pwCallback));
+  BOOST_CHECK_NO_THROW(sKey6.loadPkcs8Base64(sKeyPkcs8Base64, pwCallback));
 
   std::stringstream ss7(dataSet.privateKeyPkcs8);
   PrivateKey sKey7;
@@ -491,25 +486,25 @@
 
   // load key in pkcs8 format
   PrivateKey sKey9;
-  BOOST_CHECK_NO_THROW(sKey9.loadPkcs8(sKeyPkcs8, sKeyPkcs8Len, password.data(), password.size()));
+  BOOST_CHECK_NO_THROW(sKey9.loadPkcs8(*sKeyPkcs8, password.data(), password.size()));
   BOOST_CHECK_EQUAL(sKey9.getKeySize(), dataSet.keySize);
 
   PrivateKey sKey10;
-  BOOST_CHECK_NO_THROW(sKey10.loadPkcs8(sKeyPkcs8, sKeyPkcs8Len, pwCallback));
+  BOOST_CHECK_NO_THROW(sKey10.loadPkcs8(*sKeyPkcs8, pwCallback));
 
   std::stringstream ss11;
-  ss11.write(reinterpret_cast<const char*>(sKeyPkcs8), sKeyPkcs8Len);
+  ss11.write(reinterpret_cast<const char*>(sKeyPkcs8->data()), sKeyPkcs8->size());
   PrivateKey sKey11;
   BOOST_CHECK_NO_THROW(sKey11.loadPkcs8(ss11, password.data(), password.size()));
 
   std::stringstream ss12;
-  ss12.write(reinterpret_cast<const char*>(sKeyPkcs8), sKeyPkcs8Len);
+  ss12.write(reinterpret_cast<const char*>(sKeyPkcs8->data()), sKeyPkcs8->size());
   PrivateKey sKey12;
   BOOST_CHECK_NO_THROW(sKey12.loadPkcs8(ss12, pwCallback));
 
   // load key using wrong password, Error is expected
   PrivateKey sKey13;
-  BOOST_CHECK_THROW(sKey13.loadPkcs8Base64(sKeyPkcs8Base64, sKeyPkcs8Base64Len, wrongpw.data(), wrongpw.size()),
+  BOOST_CHECK_THROW(sKey13.loadPkcs8Base64(sKeyPkcs8Base64, wrongpw.data(), wrongpw.size()),
                     PrivateKey::Error);
   BOOST_CHECK_EQUAL(sKey13.getKeyType(), KeyType::NONE);
   BOOST_CHECK_EQUAL(sKey13.getKeySize(), 0);
@@ -517,30 +512,30 @@
   // save key in base64-encoded pkcs8 format
   OBufferStream os14;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs8Base64(os14, password.data(), password.size()));
-  checkPkcs8Base64Encoding(os14.buf(), password, sKeyPkcs1Buf);
+  checkPkcs8Base64Encoding(os14.buf(), password, sKeyPkcs1);
 
   OBufferStream os15;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs8Base64(os15, pwCallback));
-  checkPkcs8Base64Encoding(os15.buf(), password, sKeyPkcs1Buf);
+  checkPkcs8Base64Encoding(os15.buf(), password, sKeyPkcs1);
 
   // save key in pkcs8 format
   OBufferStream os16;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs8(os16, password.data(), password.size()));
-  checkPkcs8Encoding(os16.buf(), password, sKeyPkcs1Buf);
+  checkPkcs8Encoding(os16.buf(), password, sKeyPkcs1);
 
   OBufferStream os17;
   BOOST_REQUIRE_NO_THROW(sKey.savePkcs8(os17, pwCallback));
-  checkPkcs8Encoding(os17.buf(), password, sKeyPkcs1Buf);
+  checkPkcs8Encoding(os17.buf(), password, sKeyPkcs1);
 }
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(DerivePublicKey, T, KeyTestDataSets)
 {
   T dataSet;
 
-  auto sKeyPkcs1Base64 = reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data());
-  auto sKeyPkcs1Base64Len = dataSet.privateKeyPkcs1.size();
+  auto sKeyPkcs1Base64 = make_span(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
+                                   dataSet.privateKeyPkcs1.size());
   PrivateKey sKey;
-  sKey.loadPkcs1Base64(sKeyPkcs1Base64, sKeyPkcs1Base64Len);
+  sKey.loadPkcs1Base64(sKeyPkcs1Base64);
 
   // derive public key and compare
   ConstBufferPtr pKeyBits = sKey.derivePublicKey();
@@ -555,8 +550,8 @@
   RsaKey_Aes256Encrypted dataSet;
 
   PrivateKey sKey;
-  sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
-                       dataSet.privateKeyPkcs1.size());
+  sKey.loadPkcs1Base64({reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
+                        dataSet.privateKeyPkcs1.size()});
   BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::RSA);
 
   const uint8_t plaintext[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
@@ -573,7 +568,7 @@
   OBufferStream os;
   bufferSource(ciphertext) >> base64Decode() >> streamSink(os);
 
-  auto decrypted = sKey.decrypt(os.buf()->data(), os.buf()->size());
+  auto decrypted = sKey.decrypt(*os.buf());
   BOOST_CHECK_EQUAL_COLLECTIONS(plaintext, plaintext + sizeof(plaintext),
                                 decrypted->begin(), decrypted->end());
 }
@@ -583,19 +578,19 @@
   RsaKey_Aes256Encrypted dataSet;
 
   PublicKey pKey;
-  pKey.loadPkcs8Base64(reinterpret_cast<const uint8_t*>(dataSet.publicKey.data()),
-                       dataSet.publicKey.size());
+  pKey.loadPkcs8Base64({reinterpret_cast<const uint8_t*>(dataSet.publicKey.data()),
+                        dataSet.publicKey.size()});
   BOOST_CHECK_EQUAL(pKey.getKeyType(), KeyType::RSA);
 
   PrivateKey sKey;
-  sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
-                       dataSet.privateKeyPkcs1.size());
+  sKey.loadPkcs1Base64({reinterpret_cast<const uint8_t*>(dataSet.privateKeyPkcs1.data()),
+                        dataSet.privateKeyPkcs1.size()});
   BOOST_CHECK_EQUAL(sKey.getKeyType(), KeyType::RSA);
 
   const uint8_t plaintext[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
 
-  auto ciphertext = pKey.encrypt(plaintext, sizeof(plaintext));
-  auto decrypted = sKey.decrypt(ciphertext->data(), ciphertext->size());
+  auto ciphertext = pKey.encrypt(plaintext);
+  auto decrypted = sKey.decrypt(*ciphertext);
   BOOST_CHECK_EQUAL_COLLECTIONS(plaintext, plaintext + sizeof(plaintext),
                                 decrypted->begin(), decrypted->end());
 }
@@ -606,10 +601,10 @@
   bufferSource("Y2lhbyFob2xhIWhlbGxvIQ==") >> base64Decode() >> streamSink(os);
 
   auto ecKey = generatePrivateKey(EcKeyParams());
-  BOOST_CHECK_THROW(ecKey->decrypt(os.buf()->data(), os.buf()->size()), PrivateKey::Error);
+  BOOST_CHECK_THROW(ecKey->decrypt(*os.buf()), PrivateKey::Error);
 
   auto hmacKey = generatePrivateKey(HmacKeyParams());
-  BOOST_CHECK_THROW(hmacKey->decrypt(os.buf()->data(), os.buf()->size()), PrivateKey::Error);
+  BOOST_CHECK_THROW(hmacKey->decrypt(*os.buf()), PrivateKey::Error);
 }
 
 class RsaKeyGenParams
@@ -673,7 +668,7 @@
 
   const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
   OBufferStream os;
-  BOOST_REQUIRE_NO_THROW(bufferSource(data, sizeof(data)) >>
+  BOOST_REQUIRE_NO_THROW(bufferSource(data) >>
                          signerFilter(DigestAlgorithm::SHA256, *sKey) >>
                          streamSink(os));
   auto sig = os.buf();
@@ -684,8 +679,8 @@
     BOOST_REQUIRE(pKeyBits != nullptr);
     T::checkPublicKey(*pKeyBits);
     PublicKey pKey;
-    pKey.loadPkcs8(pKeyBits->data(), pKeyBits->size());
-    BOOST_CHECK_NO_THROW(bufferSource(data, sizeof(data)) >>
+    pKey.loadPkcs8(*pKeyBits);
+    BOOST_CHECK_NO_THROW(bufferSource(data) >>
                          verifierFilter(DigestAlgorithm::SHA256, pKey, sig->data(), sig->size()) >>
                          boolSink(result));
   }
@@ -693,7 +688,7 @@
 #if OPENSSL_VERSION_NUMBER >= 0x1010100fL
     BOOST_CHECK_THROW(sKey->derivePublicKey(), PrivateKey::Error);
 #endif
-    BOOST_CHECK_NO_THROW(bufferSource(data, sizeof(data)) >>
+    BOOST_CHECK_NO_THROW(bufferSource(data) >>
                          verifierFilter(DigestAlgorithm::SHA256, *sKey, sig->data(), sig->size()) >>
                          boolSink(result));
   }
diff --git a/tests/unit/security/transform/public-key.t.cpp b/tests/unit/security/transform/public-key.t.cpp
index ae234b3..d572ecc 100644
--- a/tests/unit/security/transform/public-key.t.cpp
+++ b/tests/unit/security/transform/public-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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,7 +22,9 @@
 #include "ndn-cxx/security/transform/public-key.hpp"
 
 #include "ndn-cxx/encoding/buffer-stream.hpp"
-#include "ndn-cxx/security/transform.hpp"
+#include "ndn-cxx/security/transform/base64-decode.hpp"
+#include "ndn-cxx/security/transform/buffer-source.hpp"
+#include "ndn-cxx/security/transform/stream-sink.hpp"
 
 #include "tests/boost-test.hpp"
 
@@ -69,26 +71,24 @@
 {
   T dataSet;
 
-  const uint8_t* pKeyPkcs8Base64 = reinterpret_cast<const uint8_t*>(dataSet.publicKeyPkcs8.c_str());
+  auto pKeyPkcs8Base64 = reinterpret_cast<const uint8_t*>(dataSet.publicKeyPkcs8.data());
   size_t pKeyPkcs8Base64Len = dataSet.publicKeyPkcs8.size();
   OBufferStream os;
-  bufferSource(pKeyPkcs8Base64, pKeyPkcs8Base64Len) >> base64Decode() >> streamSink(os);
-  ConstBufferPtr pKeyPkcs8Buf = os.buf();
-  const uint8_t* pKeyPkcs8 = pKeyPkcs8Buf->data();
-  size_t pKeyPkcs8Len = pKeyPkcs8Buf->size();
+  bufferSource(make_span(pKeyPkcs8Base64, pKeyPkcs8Base64Len)) >> base64Decode() >> streamSink(os);
+  auto pKeyPkcs8 = os.buf();
 
   PublicKey pKey1;
-  BOOST_CHECK_NO_THROW(pKey1.loadPkcs8Base64(pKeyPkcs8Base64, pKeyPkcs8Base64Len));
+  BOOST_CHECK_NO_THROW(pKey1.loadPkcs8Base64({pKeyPkcs8Base64, pKeyPkcs8Base64Len}));
 
   std::stringstream ss2(dataSet.publicKeyPkcs8);
   PublicKey pKey2;
   BOOST_CHECK_NO_THROW(pKey2.loadPkcs8Base64(ss2));
 
   PublicKey pKey3;
-  BOOST_CHECK_NO_THROW(pKey3.loadPkcs8(pKeyPkcs8, pKeyPkcs8Len));
+  BOOST_CHECK_NO_THROW(pKey3.loadPkcs8(*pKeyPkcs8));
 
   std::stringstream ss4;
-  ss4.write(reinterpret_cast<const char*>(pKeyPkcs8), pKeyPkcs8Len);
+  ss4.write(reinterpret_cast<const char*>(pKeyPkcs8->data()), pKeyPkcs8->size());
   PublicKey pKey4;
   BOOST_CHECK_NO_THROW(pKey4.loadPkcs8(ss4));
 
@@ -99,7 +99,7 @@
 
   OBufferStream os6;
   BOOST_REQUIRE_NO_THROW(pKey1.savePkcs8(os6));
-  BOOST_CHECK_EQUAL_COLLECTIONS(pKeyPkcs8, pKeyPkcs8 + pKeyPkcs8Len,
+  BOOST_CHECK_EQUAL_COLLECTIONS(pKeyPkcs8->begin(), pKeyPkcs8->end(),
                                 os6.buf()->begin(), os6.buf()->end());
 }
 
@@ -113,14 +113,14 @@
   EcKeyTestData dataSet;
 
   PublicKey pKey;
-  pKey.loadPkcs8Base64(reinterpret_cast<const uint8_t*>(dataSet.publicKeyPkcs8.c_str()),
-                       dataSet.publicKeyPkcs8.size());
+  pKey.loadPkcs8Base64({reinterpret_cast<const uint8_t*>(dataSet.publicKeyPkcs8.data()),
+                        dataSet.publicKeyPkcs8.size()});
   BOOST_CHECK_EQUAL(pKey.getKeyType(), KeyType::EC);
 
   OBufferStream os;
   bufferSource("Y2lhbyFob2xhIWhlbGxvIQ==") >> base64Decode() >> streamSink(os);
 
-  BOOST_CHECK_THROW(pKey.encrypt(os.buf()->data(), os.buf()->size()), PublicKey::Error);
+  BOOST_CHECK_THROW(pKey.encrypt(*os.buf()), PublicKey::Error);
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestPublicKey
diff --git a/tests/unit/security/transform/signer-filter.t.cpp b/tests/unit/security/transform/signer-filter.t.cpp
index b2145e6..063e3fc 100644
--- a/tests/unit/security/transform/signer-filter.t.cpp
+++ b/tests/unit/security/transform/signer-filter.t.cpp
@@ -40,8 +40,6 @@
 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 =
@@ -78,21 +76,23 @@
     "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);
   auto pubKey = os1.buf();
 
   PrivateKey sKey;
-  sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()), privateKeyPkcs1.size());
+  sKey.loadPkcs1Base64({reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()),
+                        privateKeyPkcs1.size()});
 
   BOOST_CHECK_THROW(SignerFilter(DigestAlgorithm::NONE, sKey), Error);
 
   OBufferStream os2;
-  bufferSource(DATA, sizeof(DATA)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
+  bufferSource(data) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
   auto sig = os2.buf();
 
-  BOOST_TEST(verifySignature({{DATA, sizeof(DATA)}}, sig->data(), sig->size(), pubKey->data(), pubKey->size()));
+  BOOST_TEST(verifySignature({{data, sizeof(data)}}, sig->data(), sig->size(), pubKey->data(), pubKey->size()));
 }
 
 BOOST_AUTO_TEST_CASE(Ecdsa)
@@ -114,21 +114,23 @@
     "RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA\n"
     "//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABGhuFibgwLdEJBDOLdvSg1Hc\n"
     "5EJTDxq6ls5FoYLfThp8HOjuwGSz0qw8ocMqyku1y0V5peQ4rEPd0bwcpZd9svA=\n";
+  const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
 
   OBufferStream os1;
   bufferSource(publicKeyPkcs8) >> base64Decode() >> streamSink(os1);
   auto pubKey = os1.buf();
 
   PrivateKey sKey;
-  sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()), privateKeyPkcs1.size());
+  sKey.loadPkcs1Base64({reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()),
+                        privateKeyPkcs1.size()});
 
   BOOST_CHECK_THROW(SignerFilter(DigestAlgorithm::NONE, sKey), Error);
 
   OBufferStream os2;
-  bufferSource(DATA, sizeof(DATA)) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
+  bufferSource(data) >> signerFilter(DigestAlgorithm::SHA256, sKey) >> streamSink(os2);
   auto sig = os2.buf();
 
-  BOOST_TEST(verifySignature({{DATA, sizeof(DATA)}}, sig->data(), sig->size(), pubKey->data(), pubKey->size()));
+  BOOST_TEST(verifySignature({{data, sizeof(data)}}, sig->data(), sig->size(), pubKey->data(), pubKey->size()));
 }
 
 BOOST_AUTO_TEST_SUITE(Hmac)
@@ -162,7 +164,7 @@
                                 0x3a, 0x12, 0x68, 0x54};
 
   PrivateKey key;
-  key.loadRaw(KeyType::HMAC, rawKey, sizeof(rawKey));
+  key.loadRaw(KeyType::HMAC, rawKey);
 
   BOOST_CHECK_THROW(SignerFilter(DigestAlgorithm::NONE, key), Error);
 
@@ -198,7 +200,7 @@
                                 0x38, 0x43};
 
   PrivateKey key;
-  key.loadRaw(KeyType::HMAC, reinterpret_cast<const uint8_t*>(rawKey), std::strlen(rawKey));
+  key.loadRaw(KeyType::HMAC, {reinterpret_cast<const uint8_t*>(rawKey), std::strlen(rawKey)});
 
   OBufferStream os256;
   bufferSource(data) >> signerFilter(DigestAlgorithm::SHA256, key) >> streamSink(os256);
@@ -222,10 +224,10 @@
                                 0x65, 0xfe};
 
   PrivateKey key;
-  key.loadRaw(KeyType::HMAC, rawKey, sizeof(rawKey));
+  key.loadRaw(KeyType::HMAC, rawKey);
 
   OBufferStream os256;
-  bufferSource(data, sizeof(data)) >> signerFilter(DigestAlgorithm::SHA256, key) >> streamSink(os256);
+  bufferSource(data) >> signerFilter(DigestAlgorithm::SHA256, key) >> streamSink(os256);
   auto sig = os256.buf();
   BOOST_CHECK_EQUAL_COLLECTIONS(sig->begin(), sig->end(), hmacSha256, hmacSha256 + sizeof(hmacSha256));
 }
diff --git a/tests/unit/security/transform/step-source.t.cpp b/tests/unit/security/transform/step-source.t.cpp
index d8aae47..0179011 100644
--- a/tests/unit/security/transform/step-source.t.cpp
+++ b/tests/unit/security/transform/step-source.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -58,17 +58,18 @@
     "0123456701234567012345670123456701234567012345670123456701234567"
     "0123456701234567012345670123456701234567012345670123456701234567"
     "0123456701234567012345670123456701234567012345670123456701234567";
-  const uint8_t* buf = reinterpret_cast<const uint8_t*>(input.data());
+  auto buf = reinterpret_cast<const uint8_t*>(input.data());
 
   std::ostringstream os;
   StepSource ss;
   ss >> streamSink(os);
-  BOOST_CHECK_EQUAL(ss.write(buf, 320), 320);
-  BOOST_CHECK_EQUAL(ss.write(buf + 320, 320), 320);
-  BOOST_CHECK_EQUAL(ss.write(buf + 640, 320), 320);
-  BOOST_CHECK_EQUAL(ss.write(buf + 960, 320), 320);
+  BOOST_CHECK_EQUAL(ss.write({buf, 320}), 320);
+  BOOST_CHECK_EQUAL(ss.write({buf + 320, 320}), 320);
+  BOOST_CHECK_EQUAL(ss.write({buf + 640, 320}), 320);
+  BOOST_CHECK_EQUAL(ss.write({buf + 960, 320}), 320);
   ss.end();
-  BOOST_CHECK_THROW(ss.write(buf + 960, 320), transform::Error);
+
+  BOOST_CHECK_THROW(ss.write({buf + 960, 320}), transform::Error);
   BOOST_CHECK_EQUAL(os.str(), input);
 }
 
@@ -78,6 +79,7 @@
   StepSource ss;
   ss >> streamSink(os);
   ss.end();
+
   BOOST_CHECK_EQUAL(os.str(), "");
 }
 
diff --git a/tests/unit/security/transform/stream-sink.t.cpp b/tests/unit/security/transform/stream-sink.t.cpp
index 4704b01..f58bece 100644
--- a/tests/unit/security/transform/stream-sink.t.cpp
+++ b/tests/unit/security/transform/stream-sink.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -34,20 +34,21 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  uint8_t in[] = {
+  const uint8_t in[] = {
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    0x20, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+    0x20, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   };
   std::ostringstream os;
   StreamSink sink(os);
-  BOOST_CHECK_EQUAL(sink.write(in, 4), 4);
-  BOOST_CHECK_EQUAL(sink.write(in + 4, 4), 4);
-  BOOST_CHECK_EQUAL(sink.write(in + 8, 4), 4);
-  BOOST_CHECK_EQUAL(sink.write(in + 12, 4), 4);
+  BOOST_CHECK_EQUAL(sink.write({in, 4}), 4);
+  BOOST_CHECK_EQUAL(sink.write({in + 4, 4}), 4);
+  BOOST_CHECK_EQUAL(sink.write({in + 8, 4}), 4);
+  BOOST_CHECK_EQUAL(sink.write({in + 12, 4}), 4);
   sink.end();
+
   std::string out = os.str();
   BOOST_CHECK_EQUAL_COLLECTIONS(in, in + sizeof(in), out.begin(), out.end());
-  BOOST_CHECK_THROW(sink.write(in + 8, 8), transform::Error);
+  BOOST_CHECK_THROW(sink.write({in + 8, 8}), transform::Error);
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestStreamSink
diff --git a/tests/unit/security/transform/strip-space.t.cpp b/tests/unit/security/transform/strip-space.t.cpp
index 29c2e7e..cd73270 100644
--- a/tests/unit/security/transform/strip-space.t.cpp
+++ b/tests/unit/security/transform/strip-space.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-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -46,19 +46,19 @@
     pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
     deserunt mollit anim id est laborum.
   )STR";
-  size_t inputLen = strlen(input);
+  const size_t inputLen = strlen(input);
 
   OBufferStream os;
   StepSource source;
   source >> stripSpace() >> streamSink(os);
 
   for (size_t offset = 0; offset < inputLen; offset += 40) {
-    source.write(reinterpret_cast<const uint8_t*>(input + offset),
-                 std::min<size_t>(40, inputLen - offset));
+    source.write({reinterpret_cast<const uint8_t*>(input + offset),
+                  std::min<size_t>(40, inputLen - offset)});
   }
   source.end();
 
-  std::string expected(
+  const std::string expected(
     "Loremipsumdolorsitamet,consecteturadipiscingelit,seddoeiusmodtemporincididuntutl"
     "aboreetdoloremagnaaliqua.Utenimadminimveniam,quisnostrudexercitationullamcolabor"
     "isnisiutaliquipexeacommodoconsequat.Duisauteiruredolorinreprehenderitinvoluptate"
diff --git a/tests/unit/security/transform/verifier-filter.t.cpp b/tests/unit/security/transform/verifier-filter.t.cpp
index 63fd03e..8feabfc 100644
--- a/tests/unit/security/transform/verifier-filter.t.cpp
+++ b/tests/unit/security/transform/verifier-filter.t.cpp
@@ -88,20 +88,21 @@
   auto pubKey = os1.buf();
 
   PublicKey pKey;
-  pKey.loadPkcs8(pubKey->data(), pubKey->size());
+  pKey.loadPkcs8(*pubKey);
 
   PrivateKey sKey;
-  sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()), privateKeyPkcs1.size());
+  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) >> 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) >>
     verifierFilter(DigestAlgorithm::SHA256, pKey, sig->data(), sig->size()) >>
     boolSink(result);
 
@@ -133,20 +134,21 @@
   auto pubKey = os1.buf();
 
   PublicKey pKey;
-  pKey.loadPkcs8(pubKey->data(), pubKey->size());
+  pKey.loadPkcs8(*pubKey);
 
   PrivateKey sKey;
-  sKey.loadPkcs1Base64(reinterpret_cast<const uint8_t*>(privateKeyPkcs1.data()), privateKeyPkcs1.size());
+  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) >> 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) >>
     verifierFilter(DigestAlgorithm::SHA256, pKey, sig->data(), sig->size()) >>
     boolSink(result);
 
@@ -158,14 +160,14 @@
   auto sKey = generatePrivateKey(HmacKeyParams());
 
   OBufferStream os;
-  bufferSource(DATA, sizeof(DATA)) >> signerFilter(DigestAlgorithm::SHA256, *sKey) >> streamSink(os);
+  bufferSource(DATA) >> signerFilter(DigestAlgorithm::SHA256, *sKey) >> streamSink(os);
   auto sig = os.buf();
 
   BOOST_CHECK_THROW(VerifierFilter(DigestAlgorithm::NONE, *sKey, sig->data(), sig->size()), Error);
 
 #if OPENSSL_VERSION_NUMBER < 0x30000000L // FIXME #5154
   bool result = false;
-  bufferSource(DATA, sizeof(DATA)) >>
+  bufferSource(DATA) >>
     verifierFilter(DigestAlgorithm::SHA256, *sKey, sig->data(), sig->size()) >>
     boolSink(result);
 
diff --git a/tests/unit/security/validation-policy-config.t.cpp b/tests/unit/security/validation-policy-config.t.cpp
index dcd7cb8..83de50e 100644
--- a/tests/unit/security/validation-policy-config.t.cpp
+++ b/tests/unit/security/validation-policy-config.t.cpp
@@ -248,7 +248,7 @@
     {
       using namespace ndn::security::transform;
       const auto& cert = this->identity.getDefaultKey().getDefaultCertificate().wireEncode();
-      bufferSource(cert.wire(), cert.size()) >> base64Encode(false) >> streamSink(os);
+      bufferSource(make_span(cert.wire(), cert.size())) >> base64Encode(false) >> streamSink(os);
     }
 
     this->policy.load(this->baseConfig + R"CONF(
diff --git a/tests/unit/security/verification-helpers.t.cpp b/tests/unit/security/verification-helpers.t.cpp
index 20ffee9..9925bb2 100644
--- a/tests/unit/security/verification-helpers.t.cpp
+++ b/tests/unit/security/verification-helpers.t.cpp
@@ -550,7 +550,7 @@
   Certificate cert(Block(dataset.cert.data(), dataset.cert.size()));
   Buffer keyRaw = cert.getPublicKey();
   transform::PublicKey key;
-  key.loadPkcs8(keyRaw.data(), keyRaw.size());
+  key.loadPkcs8(keyRaw);
   Data data(Block(dataset.goodData.data(), dataset.goodData.size()));
   Data badSigData(Block(dataset.badSigData.data(), dataset.badSigData.size()));
   Interest interest(Block(dataset.goodInterest.data(), dataset.goodInterest.size()));
diff --git a/tests/unit/util/random.t.cpp b/tests/unit/util/random.t.cpp
index c81c09e..bfa486a 100644
--- a/tests/unit/util/random.t.cpp
+++ b/tests/unit/util/random.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -125,7 +125,7 @@
 BOOST_FIXTURE_TEST_CASE(Error, FailRandMethodFixture)
 {
   std::array<uint8_t, 1024> buf;
-  BOOST_CHECK_THROW(random::generateSecureBytes(buf.data(), buf.size()), std::runtime_error);
+  BOOST_CHECK_THROW(random::generateSecureBytes(buf), std::runtime_error);
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestRandom
diff --git a/tools/ndnsec/cert-gen.cpp b/tools/ndnsec/cert-gen.cpp
index 8772062..51ad678 100644
--- a/tools/ndnsec/cert-gen.cpp
+++ b/tools/ndnsec/cert-gen.cpp
@@ -127,9 +127,9 @@
   auto certRequest = loadFromFile<security::Certificate>(requestFile);
 
   // validate that the content is a public key
-  Buffer keyContent = certRequest.getPublicKey();
+  auto keyContent = certRequest.getPublicKey();
   security::transform::PublicKey pubKey;
-  pubKey.loadPkcs8(keyContent.data(), keyContent.size());
+  pubKey.loadPkcs8(keyContent);
 
   Name certName = certRequest.getKeyName();
   certName
@@ -161,7 +161,7 @@
   {
     using namespace security::transform;
     const auto& wire = cert.wireEncode();
-    bufferSource(wire.wire(), wire.size()) >> base64Encode(true) >> streamSink(std::cout);
+    bufferSource(make_span(wire.wire(), wire.size())) >> base64Encode(true) >> streamSink(std::cout);
   }
 
   return 0;