Adding functionality into DSA.
Igor Belyi <[email protected]>
| Newsgroups | gmane.comp.python.cryptography |
|---|---|
| Message-ID | <1081817615.1495.11.camel@leonid> |
I've added some functionality into DSA so that it can now sign, verify, and save/retrieve public and private keys in/from files. To be honest, it was just copy/paste from the RSA with slight variations. But at least now you can use DSA for some simple security purposes. Patch is on top of m2crypto-0.13.1 Cheers, Igor
m2crypto-0.13.1-DSA.patch
(text/x-patch, 5.9 KB)
diff -ur m2crypto-0.13.orig/M2Crypto/DSA.py m2crypto-0.13/M2Crypto/DSA.py
--- m2crypto-0.13.orig/M2Crypto/DSA.py 2004-04-12 20:19:46.000000000 -0400
+++ m2crypto-0.13/M2Crypto/DSA.py 2004-04-12 20:34:41.000000000 -0400
@@ -58,11 +58,62 @@
assert m2.dsa_type_check(self.dsa), "'dsa' type error"
m2.dsa_gen_key(self.dsa)
- def save_key(self, file, callback=util.passphrase_callback):
- pass
+ def save_key_bio(self, bio, cipher='des_ede3_cbc', callback=util.passphrase_callback):
+ """
+ Save the key pair to an M2Crypto.BIO object in PEM format.
+
+ _bio_ is the target M2Crypto.BIO object.
+
+ _cipher_ is a symmetric cipher to protect the key. The
+ default cipher is 'des_ede3_cbc', i.e., three-key triple-DES
+ in cipher block chaining mode. If _cipher_ is None, then the key
+ is saved in the clear.
+
+ _callback_ is a Python callable object that is invoked
+ to acquire a passphrase with which to protect the key.
+ """
+ if cipher is None:
+ return m2.dsa_write_key_no_cipher(self.dsa, bio._ptr(), callback)
+ else:
+ ciph = getattr(m2, cipher, None)
+ if ciph is None:
+ raise DSAError, 'not such cipher %s' % cipher
+ else:
+ ciph = ciph()
+ return m2.dsa_write_key(self.dsa, bio._ptr(), ciph, callback)
+
+ def save_key(self, file, cipher='des_ede3_cbc', callback=util.passphrase_callback):
+ """
+ Save the key pair to filename _file_ in PEM format.
+ """
+ bio = BIO.openfile(file, 'wb')
+ return self.save_key_bio(bio, cipher, callback)
+
+ def save_pub_key_bio(self, bio):
+ """
+ Save the public key to the M2Crypto.BIO object _bio_ in PEM format.
+ """
+ return m2.dsa_write_pub_key(self.dsa, bio._ptr())
+
+ def save_pub_key(self, file):
+ """
+ Save the public key to filename _file_ in PEM format.
+ """
+ bio = BIO.openfile(file, 'wb')
+ return self.save_pub_key_bio(bio)
+
+ def save_params_bio(self, bio):
+ """
+ Save DSA parameters to the M2Crypto.BIO object _bio_ in PEM format.
+ """
+ return m2.dsa_write_params(self.dsa, bio._ptr())
def save_params(self, file):
- pass
+ """
+ Save DSA parameters to filename _file_ in PEM format.
+ """
+ bio = BIO.openfile(file, 'wb')
+ return self.save_params_bio(bio)
def sign(self, digest):
assert self.check_key(), 'key is not initialised'
@@ -76,9 +127,9 @@
assert self.check_key(), 'key is not initialised'
return m2.dsa_sign_asn1(self.dsa, digest)
- def verify_asn1(self, digest, blob):
+ def verify_asn1(self, digest, sign):
assert self.check_key(), 'key is not initialised'
- return m2.dsa_verify_asn1(self.dsa, digest, blob)
+ return m2.dsa_verify_asn1(self.dsa, digest, sign)
def check_key(self):
assert m2.dsa_type_check(self.dsa), "'dsa' type error"
@@ -92,8 +143,25 @@
Object interface to a DSA public key.
"""
- def __init__(self, *args):
- raise NotImplementedError
+ def __setattr__(self, name, value):
+ if name in ['p', 'q', 'g', 'priv', 'pub']:
+ raise DSAError, \
+ 'DSA_pub object can not change its parameters'
+ else:
+ self.__dict__[name] = value
+
+ def sign(self, digest):
+ raise DSAError, 'DSA_pub object can not be used for signing'
+
+ def sign_asn1(self, digest):
+ raise DSAError, 'DSA_pub object can not be used for signing'
+
+ save_key = DSA.save_pub_key
+
+ save_key_bio = DSA.save_pub_key_bio
+
+ def check_key(self):
+ return m2.dsa_check_pub_key(self.dsa)
def paramgen_callback(p, n, out=sys.stdout):
@@ -175,3 +243,27 @@
"""
return DSA(m2.dsa_read_key(bio._ptr(), callback), 1)
+
+def load_pub_key(file):
+ """
+ Factory function that instantiates an DSA_pub object.
+
+ The argument 'file' contains the PEM representation of the DSA public key.
+ """
+ bio = BIO.openfile(file)
+ return load_pub_key_bio(bio)
+
+
+def load_pub_key_bio(bio):
+ """
+ Factory function that instantiates an DSA_pub object.
+
+ The argument 'bio' is an M2Crypto.BIO object that contains the PEM
+ representation of the DSA public key.
+ """
+ dsa = m2.dsa_read_pub_key(bio._ptr())
+ if dsa is None:
+ dsa_error()
+ return DSA_pub(dsa, 1)
+
+
diff -ur m2crypto-0.13.orig/SWIG/_dsa.i m2crypto-0.13/SWIG/_dsa.i
--- m2crypto-0.13.orig/SWIG/_dsa.i 2003-06-22 13:30:52.000000000 -0400
+++ m2crypto-0.13/SWIG/_dsa.i 2004-04-12 20:31:36.000000000 -0400
@@ -183,6 +183,10 @@
return ret;
}
+int dsa_write_params(DSA *dsa, BIO *f) {
+ return PEM_write_bio_DSAparams(f, dsa);
+}
+
DSA *dsa_read_key(BIO *f, PyObject *pyfunc) {
DSA *ret;
@@ -192,6 +196,34 @@
return ret;
}
+int dsa_write_key(DSA *dsa, BIO *f, EVP_CIPHER *cipher, PyObject *pyfunc) {
+ int ret;
+
+ Py_INCREF(pyfunc);
+ ret = PEM_write_bio_DSAPrivateKey(f, dsa, cipher, NULL, 0,
+ passphrase_callback, (void *)pyfunc);
+ Py_DECREF(pyfunc);
+ return ret;
+}
+
+int dsa_write_key_no_cipher(DSA *dsa, BIO *f, PyObject *pyfunc) {
+ int ret;
+
+ Py_INCREF(pyfunc);
+ ret = PEM_write_bio_DSAPrivateKey(f, dsa, NULL, NULL, 0,
+ passphrase_callback, (void *)pyfunc);
+ Py_DECREF(pyfunc);
+ return ret;
+}
+
+DSA *dsa_read_pub_key(BIO *f) {
+ return PEM_read_bio_DSA_PUBKEY(f, NULL, NULL, NULL);
+}
+
+int dsa_write_pub_key(DSA *dsa, BIO *f) {
+ return PEM_write_bio_DSA_PUBKEY(f, dsa);
+}
+
/* Deprecated.
PyObject *dsa_sign(DSA *dsa, Blob *digest) {
PyObject *pytuple;
@@ -377,6 +409,10 @@
return (dsa->pub_key) && (dsa->priv_key);
}
+int dsa_check_pub_key(DSA *dsa) {
+ return dsa->pub_key;
+}
+
int dsa_keylen(DSA *dsa) {
return BN_num_bits(dsa->p);
}