<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div>Thank you for your patience.</div><div><br></div><div>Unbeknownst to me what I wanted is indeed the sha1 digest of the zipfile’s sha1 digest. (So the first suggestion you wrote is what I needed.) It sounds funny, though is is how the library (the Sparkle Update Framework) I’m writing tools for does it.</div><div><br></div><div>Is it worthwhile for me to open a pull request enabling DSA.verify() to accept a base64 or the ASN.1 DER bytestring instead of the (r, s) tuple?</div><div><br></div><div>--</div><div>Winston</div><div><br></div><br><div><div>On Apr 7, 2014, at 6:50, Legrandin <<a href="mailto:helderijs@gmail.com">helderijs@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr"><div>The openssl code is using SHA-1 twice: once to create the digest of the archive (dgst -sha1) and a second time when computing the DSA signature (dgst -dss1).<br><br></div>If your goal is to sign the hash, the Python code should actually read:<br>
<br>>> return pubkey.verify(SHA1.new(zipfile_digest).digest(), signature)<br><br><div><div class="gmail_extra">If your goal is to sign only the archive, the openssl code should be:<br><br>>> | openssl dgst -dss1 -sign "$DSA_PRIVKEY" < "$RELEASE_ARCHIVE" \<br>
>> | openssl enc -base64<br>
<br><div class="gmail_quote">2014-04-07 0:49 GMT+02:00 Winston Weinert <span dir="ltr"><<a href="mailto:winston@ml1.net" target="_blank">winston@ml1.net</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
The signature is created using the openssl(1) command-line tool like this:<br>
<br>
openssl dgst -sha1 -binary < "$RELEASE_ARCHIVE" \<br>
| openssl dgst -dss1 -sign "$DSA_PRIVKEY" \<br>
| openssl enc -base64<br>
<br>
It verifies correctly using this command-line:<br>
<br>
echo "$SIGNATURE” | openssl enc -base64 -d > /tmp/decoded_signature<br>
openssl dgst -sha1 -binary < "$RELEASE_ARCHIVE" > /tmp/release_archive_sha1<br>
openssl dgst -dss1 -verify "$DSA_PUBKEY" -signature /tmp/decoded_signature /tmp/release_archive_sha1<br>
<br>
After I wrote my email, I dug around for awhile. After a lot of research I learned<br>
about ASN.1 DER’s usage in Dss-Sig-Value (<a href="http://www.ietf.org/rfc/rfc2459.txt" target="_blank">http://www.ietf.org/rfc/rfc2459.txt</a>). I<br>
wrote this code that appeared to decode my Base64 encoded signature correctly (I<br>
checked against <a href="http://lapo.it/asn1js/" target="_blank">http://lapo.it/asn1js/</a>):<br>
<br>
def decode_DSA_signature(signature):<br>
raw_signature = base64.b64decode(signature)<br>
der = DerSequence()<br>
der.decode(raw_signature)<br>
return (der[0], der[1])<br>
<br>
Unfortunately .verify() returns False on correctly verified signature and hash<br>
pairs. I am using this new function like so:<br>
<div class=""><br>
<br>
def validate(dsa_pubkey, signature, zipfile):<br>
with open(dsa_pubkey, 'rb') as f:<br>
pubkey = DSA.importKey(f.read())<br>
with open(zipfile, 'rb') as f:<br>
h = SHA1.new()<br>
h.update(f.read())<br>
zipfile_digest = h.digest()<br>
</div> signature = decode_DSA_signature(signature)<br>
<br>
return pubkey.verify(zipfile_digest, signature)<br>
<br>
Maybe there is a problem with PyCrypto DSA and my environment?<br>
>>> sys.version<br>
'2.7.6 (default, Feb 7 2014, 12:51:34) \n[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)]'<br>
<br>
For the time being I’m invoking openssl(1) for this task.<br>
<br>
Thank you for the reply!<br>
<span class=""><font color="#888888">Winston Weinert<br>
</font></span><div class=""><div class="h5"><br>
<br>
On Apr 6, 2014, at 4:50, Legrandin <<a href="mailto:helderijs@gmail.com">helderijs@gmail.com</a>> wrote:<br>
<br>
> How was the signature created exactly?<br>
><br>
> The .verify() method of a DSA object requires two integers, and there are several ways to encode them into a bytestring. It's very hard to guess the correct one for your case.<br>
><br>
> FYI, there is a long standing pull request I created to add a saner DSA API:<br>
><br>
> <a href="https://github.com/dlitz/pycrypto/pull/53" target="_blank">https://github.com/dlitz/pycrypto/pull/53</a><br>
><br>
> The verification method accepts DER or big-endian encoded signatures.<br>
><br>
><br>
><br>
> 2014-04-05 21:03 GMT+02:00 Winston Weinert <<a href="mailto:winston@ml1.net">winston@ml1.net</a>>:<br>
> Hello,<br>
><br>
> I noticed in Git there is a “verify” method on Crypto.PublicKey.DSA. How do<br>
> I go about using this method? It wants a tuple, but unsure how to create<br>
> the appropriate tuple from my bytestring (which is decoded base64 text).<br>
> This is git revision 2d1aecd. The relevant code and error:<br>
><br>
> Code:<br>
><br>
> def validate(dsa_pubkey, signature, zipfile):<br>
> with open(dsa_pubkey, 'rb') as f:<br>
> pubkey = DSA.importKey(f.read())<br>
> with open(zipfile, 'rb') as f:<br>
> h = SHA1.new()<br>
> h.update(f.read())<br>
> zipfile_digest = h.digest()<br>
> decoded_signature = base64.b64decode(signature)<br>
><br>
> return pubkey.verify(zipfile_digest, decoded_signature)<br>
><br>
> Error:<br>
><br>
> Traceback (most recent call last):<br>
> File "sparkle_tool.py", line 67, in <module><br>
> validate_files(appcast, dsa_pubkey)<br>
> File "sparkle_tool.py", line 55, in validate_files<br>
> if validate(dsa_pubkey, signature, local_file):<br>
> File "sparkle_tool.py", line 33, in validate<br>
> return pubkey.verify(zipfile_digest, decoded_signature)<br>
> File "/home/winston/jobber/venv/local/lib/python2.7/site-packages/Crypto/PublicKey/DSA.py", line 222, in verify<br>
> return pubkey.pubkey.verify(self, M, signature)<br>
> File "/home/winston/jobber/venv/local/lib/python2.7/site-packages/Crypto/PublicKey/pubkey.py", line 126, in verify<br>
> return self._verify(M, signature)<br>
> File "/home/winston/jobber/venv/local/lib/python2.7/site-packages/Crypto/PublicKey/DSA.py", line 240, in _verify<br>
> (r, s) = sig<br>
> ValueError: too many values to unpack<br>
><br>
> Thanks a bunch!<br>
> —<br>
> Winston Weinert<br>
> <a href="mailto:winston@ml1.net">winston@ml1.net</a><br>
> _______________________________________________<br>
> pycrypto mailing list<br>
> <a href="mailto:pycrypto@lists.dlitz.net">pycrypto@lists.dlitz.net</a><br>
> <a href="http://lists.dlitz.net/cgi-bin/mailman/listinfo/pycrypto" target="_blank">http://lists.dlitz.net/cgi-bin/mailman/listinfo/pycrypto</a><br>
><br>
> _______________________________________________<br>
> pycrypto mailing list<br>
> <a href="mailto:pycrypto@lists.dlitz.net">pycrypto@lists.dlitz.net</a><br>
> <a href="http://lists.dlitz.net/cgi-bin/mailman/listinfo/pycrypto" target="_blank">http://lists.dlitz.net/cgi-bin/mailman/listinfo/pycrypto</a><br>
<br>
_______________________________________________<br>
pycrypto mailing list<br>
<a href="mailto:pycrypto@lists.dlitz.net">pycrypto@lists.dlitz.net</a><br>
<a href="http://lists.dlitz.net/cgi-bin/mailman/listinfo/pycrypto" target="_blank">http://lists.dlitz.net/cgi-bin/mailman/listinfo/pycrypto</a><br>
</div></div></blockquote></div><br></div></div></div>
_______________________________________________<br>pycrypto mailing list<br><a href="mailto:pycrypto@lists.dlitz.net">pycrypto@lists.dlitz.net</a><br>http://lists.dlitz.net/cgi-bin/mailman/listinfo/pycrypto<br></blockquote></div><br></body></html>