Re: [Pyme-help] verifying signatures
Status: Beta
Brought to you by:
belyi
From: Jérémy M. <mor...@gm...> - 2008-09-14 09:23:26
|
Hi First of all, thanks for this extensive answer ! > Hi Jérémy, > > On Friday 12 September 2008 12:26, Jérémy Morel wrote: >> I am developing a very simple bug tracking app (http://www.naphtaline.net >> ) and currently in the process of a major upgrade. I'd like to allow >> the users to use their mailbox to post comments, change tickets >> properties and create/delete tickets. I did the mail processing part, > > btw, did you have a look at http://roundup.sourceforge.net/? > It seems very close to your goals, you would probably just need to > customize > it, e.g. write a better template. Nope, I didn't. and although it does a lot more that what my project will ever do, I'd like to finish a project on my own (this would be the first project I take to its end). > >> but I now have a bigger issue : how can I be sure that the sender is >> the one he says he is ? I decided to force users to use gnupg / >> enigmail to sign their messages (no encryption needed). >> >> My problem is that I have a lot of projects in my app, each with >> their >> set of users, and of course somebody can use the same address email >> to >> subscribe to two or more different projects. > > Note that this a conceptual problem that you need to solve > and it is independent of the implementation. > (Which means you could also ask on gnupg-users or gnupg-devel > mailinglists > and have a good chance of getting answers.) > > So you want to use OpenPGP signatures to verify that email commands > came from > one specific user. Yes, this can work. Now you have to make sure > that the > signature is valid and was made using the key of the user it claims > to be > from. I chose OpenPGP because it is simple. The intended users for my app do not have a technical background, and are not interested in getting one. My motto is "keep thing really simple, because otherwise their won't be any user". I thought that the enigmail plugin was simple enough to be used by anybody in 5 minutes. > >> I may be wrong, but that >> aspect prevents me from using the gnupg's key manager where you have >> only one key manager for the unix account : it would create bridges >> between the projects. > > I can imagine you using some of gnupg's keymanagement feature, but > there are > probabyl several ways. > >> What I would like to do is the following : >> - store user's public key in a database >> - call a function like verifySignature(msg, senders_email, >> senders_publickey) which would return True or False > > Hmm, how should verifySignature work in detail? No idea about that :) Let me be more precise here. I receive a signed mail from an user. At the highest level, I just want to know if the signature found in the message is coherent with the email address of the sender (extracted from the mail) and the public key this very user gave me (extracted from the database). This is what I want to do. The "how" is the question. > > >> I am not familiar with the gpgme C lib, and my little attempts at >> manipulating data do weird things. > > The key to understand pyme is to read the documentation of the C > gpgme library > (e.g. by "info gpgme" on the command line or "info:gpgme" in KDE's > Konqueror) > Next the examples are very interesting, see my verifydetails.py in > particular. I tried to understand the basics with the examples (and particularly verifydetails.py) but it clearly isn't enough. C documentation, here I come... > > >> Here is a snippet : >> >> from pyme import core > > You must do core.check_version(None) once before. > >> c = core.Context() > > >> file = open('snihf.eml','r') >> rawMail = file.read() >> file.close() >> mail = core.Data(string=rawMail) > > Opening the file is unnecessary, you could directly do > mail = core.Data(file="snihf.eml') > > (Note that a direct email would usually not just verify, usually the > email > needs to be parsed, especially if it uses the PGP/MIME format (as it > should)). That is something I don't really understand : what should I give as an argument ? If not the whole mail, then the mail's body ? Or even less data ? I don't get what the parsed email is in that case. About the PGP/MIME. I guess using standard plugins, like enigmail or the one for mail.app, I can assume that it will always use PGP/MIME, can't I? > > >> plain = core.Data() >> >> c.op_verify(mail, None, plain) > > info gpgme says: > 7.6.2 Verify > -- Function: gpgme_error_t gpgme_op_verify (gpgme_ctx_t CTX, > gpgme_data_t SIG, gpgme_data_t SIGNED_TEXT, > gpgme_data_t PLAIN) > The function `gpgme_op_verify' verifies that the signature in the > data object SIG is a valid signature. If SIG is a detached > signature, then the signed text should be provided in SIGNED_TEXT > and PLAIN should be a null pointer. Otherwise, if SIG is a normal > (or cleartext) signature, SIGNED_TEXT should be a null pointer and > PLAIN should be a writable data object that will contain the > plaintext after successful verification. > > The results of the individual signature verifications can be > retrieved with `gpgme_op_verify_result'. > > The function returns the error code `GPG_ERR_NO_ERROR' if the > operation could be completed successfully, `GPG_ERR_INV_VALUE' if > CTX, SIG or PLAIN is not a valid pointer, `GPG_ERR_NO_DATA' if SIG > does not contain any data to verify, and passes through any errors > that are reported by the crypto engine support routines. > >> result = c.op_verify_result() >> print "mail : " >> print mail.read() >> print "plain : " >> print plain.read() >> >> If I print mail.read() before the op_verify, I get the mail. If I do >> it after, it is empty. > > Sound like correct behaviour, as the buffer was read until the end. > You could try to seek() back to the the beginning. > >> But so is plain.read() ! rawMail is juste a >> signed mail a friend sent me (his public key is not in my gnupg key >> manager though) > > According to the documentation above, this is only filled if "mail" > is a > normal (or cleartext) signature and successfully verified. > So you probably should check the result values (again look at > verifydetails.py). What do you wall a cleartext signature ? > To solve your problem I would compare the key that was used for the > signature > with the key that you had saved for the user. (Maybe comparing key > ids or > finderprints is enough security for you, would makes it a bit easier.) I'll look into it. But since I still have to read doc and learn how the whole thing works, doing it the proper way shouldn't be much more difficult :) Thanks again for the answer, it pointed out a lot of things that are not clear in my head. Jeremy |