我正在使用Crypto++库在CBC模式下使用AES算法解密文件。我在AES的sample code中遇到了SecByteBlock类,它说



有人可以解释一下SecByteBlock的内容何时被清除,以及此类比char*更具优势的情况。

提前致谢

最佳答案



使用SecByteBlock的好处是您可以获得带零位化的托管缓冲区。归零通常是合规性项目。例如,即使在1级验证下,FIPS 140-2也需要它。

第二个不明显的好处是分配器初始化POD内存-它返回原始块。这很有意义,因为您通常将0值初始化,然后用数据覆盖内容。初始化它没有任何意义,并且可以节省大量时间。

您可以获取SecBlock以提供一个0值的初始化块。这是两种方法的结合:

SecByteBlock block1(32);
SecByteBlock block2(NULL, 32);
block1的大小为32字节,未初始化,其内容将为垃圾内容。
block2的大小也为32字节,但它使用了(ptr, size)重载。重载将复制到ptr指向的块中,或者如果其NULL写入0。

为了完整和引用,SecByteBlock只是SecBlock<byte>的typedef。 SecBlock<T>是感兴趣的类,并且库经常使用SecBlock<byte>SecBlock<word32>SecBlock<word64>等。

这是Doxygen为SecBlock生成的手册页:SecBlock< T, A > Class Template Reference。这是secblock.h的头文件(仅头实现)。



在明显的对象破坏情况下,会清除SecByteBlock的内容。也就是说,当析构函数运行时,分配给SecBlock的内存将以0的模式清除。

有一个不明显的情况,那就是resize被调用来缩小一个。在这种情况下,也将擦除返回操作系统的多余空间。

您可以在源代码中看到擦除。例如,从Crypto++ 5.6.4 secblock.h:

  187     //! \brief Deallocates a block of memory
  188     //! \param ptr the pointer for the allocation
  189     //! \param size the size of the allocation, in elements
  190     //! \details Internally, SecureWipeArray() is called before deallocating the memory.
  191     //!   Once the memory block is wiped or zeroized, AlignedDeallocate() or
  192     //!   UnalignedDeallocate() is called.
  193     //! \details AlignedDeallocate() is used if T_Align16 is true.
  194     //!   UnalignedDeallocate() used if T_Align16 is false.
  195     void deallocate(void *ptr, size_type size)
  196     {
  197         CRYPTOPP_ASSERT((ptr && size) || !(ptr || size));
  198         SecureWipeArray((pointer)ptr, size);
  199
  200 #if CRYPTOPP_BOOL_ALIGN16
  201         if (T_Align16 && size*sizeof(T) >= 16)
  202             return AlignedDeallocate(ptr);
  203 #endif
  204
  205         UnalignedDeallocate(ptr);
  206     }



好吧,SecBlock<byte>是管理缓冲区的类。 char*只是一种类型,没有太多内容。您必须管理char*指向的缓冲区。

您可以使用类似std::string的方法,但是您将不会进行溢出检测(只需使用std::vector进行检查即可),并且也不会清零。

话虽如此,您可以同时执行以下两项操作:
  • typdef SecBlock<char> SecCharBlock
  • typedef std::basic_string<char, std::char_traits<char>, AllocatorWithCleanup<char> > secure_string

  • 第二个很酷。您可以这样做,因为secblock.h提供了与标准库兼容的安全分配器。 SecBlock<T>在内部使用安全分配器,其称为AllocatiorWithCleanup<T>

    odt_a上的OpenSSL Wiki页面在其示例中使用了类似的分配器来提供secure_string类。 OpenSS:的zallocator调用EVP Symmetric Encryption and Decryption | C++ Progams

    OpenSSL_cleanse :

      141 //! \class AllocatorWithCleanup
      142 //! \brief Allocates a block of memory with cleanup
      143 //! \tparam T class or type
      144 //! \tparam T_Align16 boolean that determines whether allocations should be aligned on 16-byte boundaries
      145 //! \details If T_Align16 is true, then AllocatorWithCleanup calls AlignedAllocate()
      146 //!    for memory allocations. If T_Align16 is false, then AllocatorWithCleanup() calls
      147 //!    UnalignedAllocate() for memory allocations.
      148 //! \details Template parameter T_Align16 is effectively controlled by cryptlib.h and mirrors
      149 //!    CRYPTOPP_BOOL_ALIGN16. CRYPTOPP_BOOL_ALIGN16 is often used as the template parameter.
      150 template <class T, bool T_Align16 = false>
      151 class AllocatorWithCleanup : public AllocatorBase<T>
      152 {
      153 public:
      154     CRYPTOPP_INHERIT_ALLOCATOR_TYPES
      155
      156     //! \brief Allocates a block of memory
      157     //! \param ptr the size of the allocation
      158     //! \param size the size of the allocation, in elements
      159     //! \returns a memory block
      160     //! \throws InvalidArgument
      161     //! \details allocate() first checks the size of the request. If it is non-0
      162     //!   and less than max_size(), then an attempt is made to fulfill the request
      163     //!   using either AlignedAllocate() or UnalignedAllocate().
      164     //! \details AlignedAllocate() is used if T_Align16 is true.
      165     //!   UnalignedAllocate() used if T_Align16 is false.
      166     //! \details This is the C++ *Placement New* operator. ptr is not used, and the function
      167     //!   CRYPTOPP_ASSERTs in Debug builds if ptr is non-NULL.
      168     //! \sa CallNewHandler() for the methods used to recover from a failed
      169     //!   allocation attempt.
      170     //! \note size is the count of elements, and not the number of bytes
      171     pointer allocate(size_type size, const void *ptr = NULL)
      172     {
      173         CRYPTOPP_UNUSED(ptr); CRYPTOPP_ASSERT(ptr == NULL);
      174         this->CheckSize(size);
      175         if (size == 0)
      176             return NULL;
      177
      178 #if CRYPTOPP_BOOL_ALIGN16
      179         // TODO: should this need the test 'size*sizeof(T) >= 16'?
      180         if (T_Align16 && size*sizeof(T) >= 16)
      181             return (pointer)AlignedAllocate(size*sizeof(T));
      182 #endif
      183
      184         return (pointer)UnalignedAllocate(size*sizeof(T));
      185     }
      186     ...
      241 };
    

    关于c++ - Crypto++的SecByteBlock类的优点,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39751312/

    10-11 18:01