[pycrypto] Verify DSA bytestring signature

Legrandin helderijs at gmail.com
Mon Apr 7 04:50:26 PDT 2014


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).

If your goal is to sign the hash, the Python code should actually read:

>> return pubkey.verify(SHA1.new(zipfile_digest).digest(), signature)

If your goal is to sign only the archive, the openssl code should be:

>> | openssl dgst -dss1 -sign "$DSA_PRIVKEY"  < "$RELEASE_ARCHIVE" \
>> | openssl enc -base64

2014-04-07 0:49 GMT+02:00 Winston Weinert <winston at ml1.net>:

> The signature is created using the openssl(1) command-line tool like this:
>
> openssl dgst -sha1 -binary < "$RELEASE_ARCHIVE" \
> | openssl dgst -dss1 -sign "$DSA_PRIVKEY" \
> | openssl enc -base64
>
> It verifies correctly using this command-line:
>
> echo "$SIGNATURE" | openssl enc -base64 -d > /tmp/decoded_signature
> openssl dgst -sha1 -binary < "$RELEASE_ARCHIVE" > /tmp/release_archive_sha1
> openssl dgst -dss1 -verify "$DSA_PUBKEY" -signature /tmp/decoded_signature
> /tmp/release_archive_sha1
>
> After I wrote my email, I dug around for awhile. After a lot of research I
> learned
> about ASN.1 DER's usage in Dss-Sig-Value (
> http://www.ietf.org/rfc/rfc2459.txt). I
> wrote this code that appeared to decode my Base64 encoded signature
> correctly (I
> checked against http://lapo.it/asn1js/):
>
> def decode_DSA_signature(signature):
>     raw_signature = base64.b64decode(signature)
>     der = DerSequence()
>     der.decode(raw_signature)
>     return (der[0], der[1])
>
> Unfortunately .verify() returns False on correctly verified signature and
> hash
> pairs. I am using this new function like so:
>
>
> def validate(dsa_pubkey, signature, zipfile):
>     with open(dsa_pubkey, 'rb') as f:
>         pubkey = DSA.importKey(f.read())
>     with open(zipfile, 'rb') as f:
>         h = SHA1.new()
>         h.update(f.read())
>         zipfile_digest = h.digest()
>     signature = decode_DSA_signature(signature)
>
>     return pubkey.verify(zipfile_digest, signature)
>
> Maybe there is a problem with PyCrypto DSA and my environment?
> >>> sys.version
> '2.7.6 (default, Feb  7 2014, 12:51:34) \n[GCC 4.2.1 Compatible Apple LLVM
> 5.0 (clang-500.2.79)]'
>
> For the time being I'm invoking openssl(1) for this task.
>
> Thank you for the reply!
> Winston Weinert
>
>
> On Apr 6, 2014, at 4:50, Legrandin <helderijs at gmail.com> wrote:
>
> > How was the signature created exactly?
> >
> > 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.
> >
> > FYI, there is a long standing pull request I created to add a saner DSA
> API:
> >
> > https://github.com/dlitz/pycrypto/pull/53
> >
> > The verification method accepts DER or big-endian encoded signatures.
> >
> >
> >
> > 2014-04-05 21:03 GMT+02:00 Winston Weinert <winston at ml1.net>:
> > Hello,
> >
> > I noticed in Git there is a "verify" method on Crypto.PublicKey.DSA. How
> do
> > I go about using this method? It wants a tuple, but unsure how to create
> > the appropriate tuple from my bytestring (which is decoded base64 text).
> > This is git revision 2d1aecd. The relevant code and error:
> >
> > Code:
> >
> > def validate(dsa_pubkey, signature, zipfile):
> >     with open(dsa_pubkey, 'rb') as f:
> >         pubkey = DSA.importKey(f.read())
> >     with open(zipfile, 'rb') as f:
> >         h = SHA1.new()
> >         h.update(f.read())
> >         zipfile_digest = h.digest()
> >     decoded_signature = base64.b64decode(signature)
> >
> >     return pubkey.verify(zipfile_digest, decoded_signature)
> >
> > Error:
> >
> > Traceback (most recent call last):
> >   File "sparkle_tool.py", line 67, in <module>
> >     validate_files(appcast, dsa_pubkey)
> >   File "sparkle_tool.py", line 55, in validate_files
> >     if validate(dsa_pubkey, signature, local_file):
> >   File "sparkle_tool.py", line 33, in validate
> >     return pubkey.verify(zipfile_digest, decoded_signature)
> >   File
> "/home/winston/jobber/venv/local/lib/python2.7/site-packages/Crypto/PublicKey/DSA.py",
> line 222, in verify
> >     return pubkey.pubkey.verify(self, M, signature)
> >   File
> "/home/winston/jobber/venv/local/lib/python2.7/site-packages/Crypto/PublicKey/pubkey.py",
> line 126, in verify
> >     return self._verify(M, signature)
> >   File
> "/home/winston/jobber/venv/local/lib/python2.7/site-packages/Crypto/PublicKey/DSA.py",
> line 240, in _verify
> >     (r, s) = sig
> > ValueError: too many values to unpack
> >
> > Thanks a bunch!
> > --
> > Winston Weinert
> > winston at ml1.net
> > _______________________________________________
> > pycrypto mailing list
> > pycrypto at lists.dlitz.net
> > http://lists.dlitz.net/cgi-bin/mailman/listinfo/pycrypto
> >
> > _______________________________________________
> > pycrypto mailing list
> > pycrypto at lists.dlitz.net
> > http://lists.dlitz.net/cgi-bin/mailman/listinfo/pycrypto
>
> _______________________________________________
> pycrypto mailing list
> pycrypto at lists.dlitz.net
> http://lists.dlitz.net/cgi-bin/mailman/listinfo/pycrypto
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.dlitz.net/pipermail/pycrypto/attachments/20140407/b61f21b3/attachment.html>


More information about the pycrypto mailing list