【问题标题】:Advantages of SecByteBlock class from Crypto++Crypto++ 中 SecByteBlock 类的优点
【发布时间】:2016-09-28 15:07:15
【问题描述】:

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

使用 SecByteBlock 在堆栈上声明密钥以确保将敏感材料归零。

谁能解释一下SecByteBlock 的内容什么时候会被清除,以及这个类比char* 有什么优势。

提前致谢

【问题讨论】:

    标签: c++ cryptography crypto++


    【解决方案1】:

    [title] Crypto++中SecByteBlock类的优点

    使用SecByteBlock 的优点是您可以通过归零获得托管缓冲区。归零通常是合规项目。例如,FIPS 140-2 要求它,即使在 1 级验证中也是如此。

    第二个不明显的好处是分配器初始化 POD 内存 - 它返回一个原始块。这很有意义,因为您经常初始化一个 0 值,然后用数据覆盖内容。初始化没有意义,还省了很多时间。

    你可以得到SecBlock来提供一个0值的初始化块。以下是如何做到这两点:

    SecByteBlock block1(32);
    SecByteBlock block2(NULL, 32);
    

    block1 大小为 32 字节,未初始化,其内容将是垃圾。

    block2 的大小也是 32 字节,但它使用了 (ptr, size) 重载。重载将复制ptr 指向的块,或者如果它的NULL 将写入0。


    为了完整性和参考,SecByteBlock 只是SecBlock<byte> 的类型定义。 SecBlock<T> 是感兴趣的类,库中经常使用SecBlock<byte>SecBlock<word32>SecBlock<word64> 等。

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


    谁能解释一下SecByteBlock的内容什么时候会被清除...

    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     }
    

    这个类比 char* 有什么优势。

    嗯,SecBlock&lt;byte&gt; 是一个管理缓冲区的类。 char* 只是一种类型,并没有太多的意义。您必须管理char* 指向的缓冲区。

    您可以使用std::string 之类的东西,但您不会进行溢出检测(只需要std::vector 来检查它)并且您不会获得零化。

    话虽如此,你可以做到这两个:

    • typdef SecBlock&lt;char&gt; SecCharBlock
    • typedef std::basic_string&lt;char, std::char_traits&lt;char&gt;, AllocatorWithCleanup&lt;char&gt; &gt; secure_string

    第二个有点酷。您可以这样做,因为secblock.h 提供了与标准库兼容的安全分配器。 SecBlock&lt;T&gt; 在内部使用安全分配器,称为AllocatiorWithCleanup&lt;T&gt;

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

    来自Crypto++ 5.6.4 secblock.h

      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 };
    

    【讨论】:

      猜你喜欢
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多