<div dir="ltr">Hi Alex,<div><br></div><div>Thanks a bunch for the tip!</div><div><br></div><div>I managed to get the signature verification step to work. Here is my code:</div><div><br></div><div><div> signature = ... # 64 bytes in P1363 format.</div><div><br></div><div> # Load signature from Microsoft's raw format to the DER-encoded</div><div> # format expected by cryptography.</div><div> #</div><div> # Conversion steps:</div><div> # - decode public numbers as 2 big-endian octet stream;</div><div> # - DER-encode public numbers.</div><div> def _bin2int(backend, x):</div><div> backend = backend._backends[0]</div><div> i = backend._lib.BN_bin2bn(x, len(x), backend._ffi.NULL)</div><div> return backend._bn_to_int(i)</div><div> signature = encode_dss_signature(</div><div> _bin2int(backend, signature[:32]),</div><div> _bin2int(backend, signature[32:]),</div><div> )</div></div><div><br></div><div>I also managed to get the CGN API-based signature verification step to work when using a Cryptography-based server to sign the payload using this piece of code:</div><div><br></div><div> signature = ... # ASN.1</div><div><br></div><div> # Convert signature from the DER-encoded format used by</div><div> # OpenSSL into Microsoft's raw format</div><div> #</div><div> # Conversion steps:</div><div> # - DER-decode numbers;</div><div> # - encode numbers as 2 big-endian octet streams.</div><div> def int2bin(backend, i):</div><div> backend = backend._backends[0]</div><div> i = backend._int_to_bn(i)</div><div> x = backend._ffi.new(</div><div> "unsigned char[]", backend._lib.BN_num_bytes(i)</div><div> )</div><div> n = backend._lib.BN_bn2bin(i, x)</div><div> i = backend._ffi.buffer(x)[:n]</div><div> return i</div><div> r, s = decode_dss_signature(<wbr>signature)</div><div> signature = int2bin(backend, r) + int2bin(backend, s)</div><div><br></div><div>(I updated my gist with the C++ client & server and the Python client & server if you want to look at the rest.)</div><div><br></div><div>I also have related snippets that allow me to convert public & private keys to and from Microsoft's format. <br></div><div><br></div><div>Now, i have full interop: I can generate a keypair, share the public key, sign and verify using both Python and C++ (both directions).</div><div><br></div><div>However, I'm relying on cryptography internals to do this, which is definitely not desirable in the medium-long term. Know of a better way to do these conversions by relying only on public APIs?</div><div><br></div><div>Also, I guess I'm not the only person that's going to be running into this. Any interest in adding built-in support for this in cryptography? If so, I'd be willing to put some effort into a PR.</div><div><br></div><div>Thanks,</div><div><br></div><div>André</div><div> </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Aug 12, 2016 at 7:41 AM, Alex Gaynor <span dir="ltr"><<a href="mailto:alex.gaynor@gmail.com" target="_blank">alex.gaynor@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><a href="https://stackoverflow.com/questions/20992760/understanding-bcryptsignhash-output-signature" target="_blank">https://stackoverflow.com/<wbr>questions/20992760/<wbr>understanding-bcryptsignhash-<wbr>output-signature</a> matches your intuition: the format out of Microsoft's function is just the two numbers concatenated together, perhaps they are little endian instead of big endian though?<br><div><br></div><div>Alex</div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Thu, Aug 11, 2016 at 1:38 PM, André Caron <span dir="ltr"><<a href="mailto:andre.l.caron@gmail.com" target="_blank">andre.l.caron@gmail.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><div dir="ltr">Hi all,<div><br></div><div>I'm dealing with a C++ client & server pair that uses ECDSA to verify the server's identity. I'm trying to write a new Python client that will exchange with the server without making any changes to the server. I've gotten quite a bit of this in place with cryptography (the Python package :-), but I'm incapable of getting the Python client to verify the signature sent by the server and I'd like to see if you can help me out.</div><div><br></div><div>One of the problems here is that the serialization formats seem to be internal to Microsoft's CNG API. For example, the public key is the raw output of BCryptExportKey() and the signature is the raw output of BCryptSignHash(). These are Microsoft APIs, so... needless to say cryptography doesn't "just work" with these formats.</div><div><br></div><div>I'm pretty sure I managed to nail the key format conversion as Microsoft makes an obscure reference to the format[1], but I'm still having trouble with signatures. The blob I get as output from BCryptSignHash() has 64 bytes, but signatures for the same algorithm using cryptography are usually 70-72 bytes, so I'm confused. Cryptography's ECC signature computation clearly documents the format: "The signature is formatted as DER-encoded bytes, as specified in RFC 3279." However, Microsoft doesn't seem to output record an equivalent anywhere. They're usually pretty consistent with their APIs and storage formats, so I assume some sort of storage similar to the keys where we have two 32-byte octet streams in big endian format containing the values for R and S, but I haven't had any luck with this. I also know that the DER encoding for two integer fields will normally add 6 bytes of overhead, which gets us up to 70, but there is still the occasional extra 1 or 2 bytes, so I'm obviously missing something and may not be on the right track.</div><div><br></div><div>[1] :<a href="https://msdn.microsoft.com/library/aa375520.aspx" target="_blank">https://msdn.microsoft.com/li<wbr>brary/aa375520.aspx</a></div><div><br></div><div>Anyways, I managed to extract the BCrypt* function calls from the server and client into a pair of C++ program the contain only the signing and signature verification code to reproduce the flow. The total is ~30 lines of C++ code on each side, plus ~400 lines wrappers for BCrypt* calls (resource management, error handling and links to CNG API docs).</div><div><br></div><div>I've also written a small cryptography-based Python program that tries to mimic the C++ client and I cannot get that part to run.</div><div><br></div><div>If anyone has a few minutes to spare to give my Python code a second pair of eyeballs, I'd really appreciate it.</div><div><br></div><div>I've saved up all of that on this Gist: <a href="https://gist.github.com/AndreLouisCaron/ab5ee411d0722a0981feceddbf5cb3d9" target="_blank">https://gist.github.com/<wbr>AndreLouisCaron/ab5ee411d0722a<wbr>0981feceddbf5cb3d9</a></div><div><br></div><div>The gist contents are as follows:</div><div>- genkeys.py: generate a public/private key pair, write to disk in Microsoft's format;</div><div>- server.cpp: load secret key, compute signature, save payload & signature to disk;</div><div>- client.cpp: load public key, payload & signature from disk, verify signature;</div><div>- common.h: stuff shared by client.cpp & server.cpp;</div><div>- client.py: same as client.cpp, but using cryptography.</div><div><br></div><div>I also have an alternate C++ client based on OpenSSL which might be a better source of inspiration. I'll see if I can extract pars of that too as a reference since it might be easier to map to cryptography's internals.</div><div><br></div><div>Thanks in advance,</div><div><br></div><div>André</div></div>
<br></div></div>______________________________<wbr>_________________<br>
Cryptography-dev mailing list<br>
<a href="mailto:Cryptography-dev@python.org" target="_blank">Cryptography-dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/cryptography-dev" rel="noreferrer" target="_blank">https://mail.python.org/mailma<wbr>n/listinfo/cryptography-dev</a><br>
<br></blockquote></div><span class="HOEnZb"><font color="#888888"><br><br clear="all"><div><br></div>-- <br><div data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr">"I disapprove of what you say, but I will defend to the death your right to say it." -- Evelyn Beatrice Hall (summarizing Voltaire)<br>"The people's good is the highest law." -- Cicero</div><div dir="ltr">GPG Key fingerprint: D1B3 ADC0 E023 8CA6<br><div><br></div></div></div></div></div>
</font></span></div>
<br>______________________________<wbr>_________________<br>
Cryptography-dev mailing list<br>
<a href="mailto:Cryptography-dev@python.org">Cryptography-dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/cryptography-dev" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/cryptography-<wbr>dev</a><br>
<br></blockquote></div><br></div>