Re: Adding functionality into DSA.

Igor Belyi <[email protected]>
Newsgroups gmane.comp.python.cryptography
Message-ID <1082072978.1451.97.camel@leonid>
On Wed, 2004-04-14 at 20:48, Ng Pheng Siong wrote:
> Thanks. I'll fold that into the next release.

It appears that my copy&paste from RSA didn't went far enough. Here's a
patch on top of my previous one.

I also took the liberty and made 'verify' method symmetrical to the
'sign', so that the following command can be used for signature
verification:
assert dsa.verify(data, dsa.sign(data))

If this is inappropriate (somebody depends on the old set of arguments,
for example), just delete the corresponding part of the patch and update
the test_dsa.py.

Cheers,
Igor
m2crypto-0.13.1-DSA-2.patch (text/x-patch, 4.8 KB)
--- m2crypto-0.13/M2Crypto/DSA.py.orig  2004-04-15 16:44:40.000000000 -0400
+++ m2crypto-0.13/M2Crypto/DSA.py       2004-04-15 18:49:22.000000000 -0400
@@ -119,7 +119,7 @@
         assert self.check_key(), 'key is not initialised'
         return m2.dsa_sign(self.dsa, digest)

-    def verify(self, digest, r, s):
+    def verify(self, digest, (r, s)):
         assert self.check_key(), 'key is not initialised'
         return m2.dsa_verify(self.dsa, digest, r, s)

@@ -164,6 +164,10 @@
         return m2.dsa_check_pub_key(self.dsa)


+def dsa_error():
+    raise DSAError, m2.err_reason_error_string(m2.err_get_error())
+
+
 def paramgen_callback(p, n, out=sys.stdout):
     """
     Default callback for gen_params().
@@ -185,7 +189,10 @@
     invoked during parameter generation; it usual purpose
     is to provide visual feedback.
     """
-    return DSA(m2.dsa_generate_parameters(bits, callback), 1)
+    dsa = m2.dsa_generate_parameters(bits, callback)
+    if dsa is None:
+        dsa_error()
+    return DSA(dsa, 1)


 def load_params(file, callback=util.passphrase_callback):
@@ -214,7 +221,10 @@
     'callback' is a Python callback object that will be
     invoked if the DSA parameters are passphrase-protected.
     """
-    return DSA(m2.dsa_read_params(bio._ptr(), callback), 1)
+    dsa = m2.dsa_read_params(bio._ptr(), callback)
+    if dsa is None:
+        dsa_error()
+    return DSA(dsa, 1)


 def load_key(file, callback=util.passphrase_callback):
@@ -241,7 +251,10 @@
     'callback' is a Python callback object that will be invoked
     if the DSA key pair is passphrase-protected.
     """
-    return DSA(m2.dsa_read_key(bio._ptr(), callback), 1)
+    dsa = m2.dsa_read_key(bio._ptr(), callback)
+    if dsa is None:
+        dsa_error()
+    return DSA(dsa, 1)


 def load_pub_key(file):
--- m2crypto-0.13/tests/dsa.pub.pem.orig        1969-12-31 19:00:00.000000000 -0500
+++ m2crypto-0.13/tests/dsa.pub.pem     2004-04-15 19:10:09.000000000 -0400
@@ -0,0 +1,8 @@
+-----BEGIN PUBLIC KEY-----
+MIHxMIGpBgcqhkjOOAQBMIGdAkEA0NGZ0GRXdPLh/0c980Ot8ZbfV/DvJ19ZzsDh
+KXRxNNw36Ms4lb9YZMnJ1CliIDkpHx8sXEak0vkdeB2efGGBPQIVAJY7PF7CiA+j
+j+t3EyHf/sgVagPPAkEApkvDehftx8Kt+3GRsYkEgcKqsU6tue+QQOFOFYsCbMq/
+3rxIEKk0q1PqHfid+BsMiEY4FFmF5BqmgGAf6+V9twNDAAJATbbgPKi/EboVrtBd
+kTM52LSCQHPa/CEcj3220s5Ix1dwojdQaNpq6HhCm6+g9SXPENy9I/PK85YnawI4
+A6w1pQ==
+-----END PUBLIC KEY-----
--- m2crypto-0.13/tests/test_dsa.py.orig        2004-04-15 19:38:49.000000000 -0400
+++ m2crypto-0.13/tests/test_dsa.py     2004-04-15 19:35:24.000000000 -0400
@@ -14,6 +14,7 @@

     errkey = 'rsa.priv.pem'
     privkey = 'dsa.priv.pem'
+    pubkey = 'dsa.pub.pem'
     param = 'dsa.param.pem'

     data = sha.sha('Can you spell subliminal channel?').digest()
@@ -25,12 +26,18 @@
         pass

     def check_loadkey_junk(self):
-        self.assertRaises(ValueError, DSA.load_key, self.errkey)
+        self.assertRaises(DSA.DSAError, DSA.load_key, self.errkey)
+        self.assertRaises(DSA.DSAError, DSA.load_pub_key, self.errkey)
+        self.assertRaises(DSA.DSAError, DSA.load_params, self.errkey)

     def check_loadkey(self):
         dsa = DSA.load_key(self.privkey)
         assert len(dsa) == 512

+    def check_loadpubkey(self):
+        dsa = DSA.load_pub_key(self.pubkey)
+        assert len(dsa) == 512
+
     def check_loadparam(self):
         # XXX more work needed
         dsa = DSA.load_params(self.param)
@@ -39,7 +46,7 @@
     def check_sign(self):
         dsa = DSA.load_key(self.privkey)
         r, s = dsa.sign(self.data)
-        assert dsa.verify(self.data, r, s)
+        assert dsa.verify(self.data, (r, s))

     def check_sign_asn1(self):
         dsa = DSA.load_key(self.privkey)
@@ -51,11 +58,26 @@
         self.assertRaises(AssertionError, dsa.sign, self.data)
         self.assertRaises(AssertionError, dsa.sign_asn1, self.data)

+    def check_sign_with_pubkey(self):
+        dsa = DSA.load_pub_key(self.pubkey)
+        self.assertRaises(DSA.DSAError, dsa.sign, self.data)
+        self.assertRaises(DSA.DSAError, dsa.sign_asn1, self.data)
+
     def check_verify(self):
         dsa = DSA.load_key(self.privkey)
         r, s = dsa.sign(self.data)
+        dsa1 = DSA.load_pub_key(self.pubkey)
+        assert dsa1.verify(self.data, (r, s))
+        dsa2 = DSA.load_params(self.param)
+        self.assertRaises(AssertionError, dsa2.verify, self.data, (r, s))
+
+    def check_verify_asn1(self):
+        dsa = DSA.load_key(self.privkey)
+        blob = dsa.sign_asn1(self.data)
+        dsa1 = DSA.load_pub_key(self.pubkey)
+        assert dsa1.verify_asn1(self.data, blob)
         dsa2 = DSA.load_params(self.param)
-        self.assertRaises(AssertionError, dsa2.verify, self.data, r, s)
+        self.assertRaises(AssertionError, dsa2.verify_asn1, self.data, blob)

     def check_genparam(self):
         dsa = DSA.gen_params(256, self.callback)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.