Boost C++ Libraries: Ticket #9235: Construction from binary data https://svn.boost.org/trac10/ticket/9235 <p> I didn't find a way to directly construct fixed sized cpp_int from existing binary data (a static array, for example an RSA key hardcoded into a .cpp after being generated with OpenSSL)... I had to resort to either using the from-string constructor or inserting the data byte by byte with 8 bit shifts and or-ing in a loop both of which are ugly and inefficient: <a class="ext-link" href="https://svn.boost.org/trac/boost/ticket/9233"><span class="icon">​</span>https://svn.boost.org/trac/boost/ticket/9233</a> <a class="ext-link" href="https://svn.boost.org/trac/boost/ticket/9234"><span class="icon">​</span>https://svn.boost.org/trac/boost/ticket/9234</a> <a class="ext-link" href="https://svn.boost.org/trac/boost/ticket/9243"><span class="icon">​</span>https://svn.boost.org/trac/boost/ticket/9243</a> ... </p> <p> Ideally it would be possible to create static fixed size numbers as one creates PODs, without a dynamic initializer being created by the compiler.. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/9235 Trac 1.4.3 John Maddock Fri, 11 Oct 2013 16:16:06 GMT <link>https://svn.boost.org/trac10/ticket/9235#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9235#comment:1</guid> <description> <p> This is supported.... but only in C++11 compliant compilers (ie not VC++ I'm afraid at present). See: <a href="http://www.boost.org/doc/libs/1_54_0/libs/multiprecision/doc/html/boost_multiprecision/tut/lits.html">http://www.boost.org/doc/libs/1_54_0/libs/multiprecision/doc/html/boost_multiprecision/tut/lits.html</a> </p> <p> When supported though, the integer is compile-time constructed from the data with no runtime overhead at all. </p> <p> Otherwise I'd strongly recommend you use the "construct from hexadecimal string" method, as that runtime code is well optimized (I hope!). </p> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Fri, 11 Oct 2013 16:16:19 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/9235#comment:2 https://svn.boost.org/trac10/ticket/9235#comment:2 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">wontfix</span> </li> </ul> Ticket Domagoj Šarić Sat, 12 Oct 2013 10:50:01 GMT description changed https://svn.boost.org/trac10/ticket/9235#comment:3 https://svn.boost.org/trac10/ticket/9235#comment:3 <ul> <li><strong>description</strong> modified (<a href="/trac10/ticket/9235?action=diff&amp;version=3">diff</a>) </li> </ul> Ticket Domagoj Šarić Sat, 12 Oct 2013 11:09:11 GMT status changed; resolution deleted https://svn.boost.org/trac10/ticket/9235#comment:4 https://svn.boost.org/trac10/ticket/9235#comment:4 <ul> <li><strong>status</strong> <span class="trac-field-old">closed</span> → <span class="trac-field-new">reopened</span> </li> <li><strong>resolution</strong> <span class="trac-field-deleted">wontfix</span> </li> </ul> <blockquote> <p> 1) you somewhat contradict yourself here WRT to <a class="ext-link" href="https://svn.boost.org/trac/boost/ticket/9234#comment:1"><span class="icon">​</span>https://svn.boost.org/trac/boost/ticket/9234#comment:1</a> where you refer to contruction from a string as something non trivial </p> </blockquote> <p> <br /> </p> <blockquote> <p> 2) regardless, closing this as wontfix (instead of at least postponing until you or someone else finds the time) is lame IMO because this is certainly doable...'of the top of my head': you'd 'just' need to define an underlying POD which could be filled through a macro that'd: </p> </blockquote> <ul><li>fill the raw array that represents the number </li><li>set any aditional/auxiliary members you might have in number&lt;&gt; </li><li>define a fully typeed number&lt;&gt; &amp; bound to the helper underlying POD instance... </li><li>"I know" it is doable because in my code (which I don't have with me now as I'm not at work) I had to do the opposite: retrieve the raw binary data from a cpp_int in order to compare it to an expected signature which I did by reinterpret_casting your number&lt;&gt; to a boost::array&lt;&gt; and calling std::reverse() on it...so this is one more function missing from the interface (retreiving a numbers raw byte representation as opposed to a slow EH littered dynamically allocated std::string conversion) </li></ul><p> <br /> </p> <blockquote> <p> 3) the ticket isn't (only) about static strings but creation from binary data in general (which one may receive or generate at runtime, for example from a different big-int library) so a function that does this (what I currently do with the mentioned loop in the other ticket) is certainly needed </p> </blockquote> <p> <br /> </p> <blockquote> <p> 4 when one uses your lib for cryptography or hash/licence verification storing (private) keys as plain text hex strings is not an option </p> </blockquote> Ticket John Maddock Sat, 12 Oct 2013 16:27:01 GMT type changed https://svn.boost.org/trac10/ticket/9235#comment:5 https://svn.boost.org/trac10/ticket/9235#comment:5 <ul> <li><strong>type</strong> <span class="trac-field-old">Bugs</span> → <span class="trac-field-new">Feature Requests</span> </li> </ul> <p> It's not quite as trivial as you think: the internal data layout is highly platform/compiler dependent. For example a 128-bit integer is represented as 4 32 bit words on MSVC, but as a single 128-bit value on GCC-x64 (which has <code>__int128</code>). </p> <p> Re (1), conversion from a hex string is fast, but decimal string conversion is heavyweight: of course they use the same routine though. Your example(4) is solved by user-defined literals I believe - it's the optimally efficient solution as it's all done at compile-time. For (3) would get_byte/set_byte non-member functions (similar to the existing bit twiddling functions) do the job? Note that these would only be efficient for unsigned types: signed types would require a check for negative values and the associated error handling - and yes that means exceptions. </p> Ticket Domagoj Šarić Thu, 18 Feb 2016 15:22:39 GMT <link>https://svn.boost.org/trac10/ticket/9235#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9235#comment:6</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/9235#comment:5" title="Comment 5">johnmaddock</a>: </p> <p> I've just noticed you've added import/export_bits() :) ...interface-wise this would be enough to close this ticket however I'm not fully happy with the implementation so let's not yet ;-D </p> <blockquote class="citation"> <p> It's not quite as trivial as you think: the internal data layout is highly platform/compiler dependent. For example a 128-bit integer is represented as 4 32 bit words on MSVC, but as a single 128-bit value on GCC-x64 (which has <code>__int128</code>). </p> </blockquote> <p> <br /> This does/should not matter if the endianess of the machine and your internal implementation match, the byte layout will be the same. Except if the 'raw'/binary data is in a different endianess than your internal representation (modeled by the msv_first import/export_bits() parameter) but even then it is a matter of a simple byte reversal. Tried it with both importing and exporting with Boost 1.60 and 'it just works': </p> <pre class="wiki"> template &lt;class Key&gt; void LE_NOTHROW load( Key &amp; key, std::array&lt;std::uint8_t, Constants::rsaKeySizeInBytes&gt; const &amp; keyBytes ) { #if 0 BOOST_VERIFY( &amp;import_bits( key, keyBytes.begin(), keyBytes.end() ) == &amp;key ); #else key.backend().resize( key.backend().internal_limb_count, 0 ); std::reverse_copy( keyBytes.begin(), keyBytes.end(), reinterpret_cast&lt;std::uint8_t *&gt;( key.backend().limbs() ) ); #endif } </pre><p> and looks trivial in the disassembly window ;) </p> <p> ps. first I tried to force key (a fixed unchecked uint) limb count to max by constructing it as Key key( -1 ) but that didn't quite give a picturesque codegen ;D </p> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Fri, 26 Feb 2016 11:59:17 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/9235#comment:7 https://svn.boost.org/trac10/ticket/9235#comment:7 <ul> <li><strong>status</strong> <span class="trac-field-old">reopened</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> Please see <a class="ext-link" href="https://github.com/boostorg/multiprecision/commit/53515e9a960e4e7bdfa8f2e6d05ccb174d66bf4d"><span class="icon">​</span>https://github.com/boostorg/multiprecision/commit/53515e9a960e4e7bdfa8f2e6d05ccb174d66bf4d</a>. </p> <p> Note this is import only, which I think fixes your use case. Export via memcpy to an output iterator is unsafe and not implemented. I could provide a separate interface for that, but I'd like to see a genuine need for high-speed-export first. </p> <p> In any case, use of user-defined-literals (which is all constexpr) is the better solution for your use case, although I accept that's not supported on msvc yet :( </p> Ticket