[Delta] QCA 2
kiko at tempest.com.br
Thu May 27 13:52:47 PDT 2004
-----BEGIN PGP SIGNED MESSAGE-----
> When you have a blocking function, about the only solution is
> to use a thread, at least internally. Otherwise you can't exit
> the call stack, and so the entire chain is blocked.
As you probably know, OpenSSL's key generation routines
(and several others known to take long) have callbacks
precisely report progress. What I did was to hook those
callbacks to a signal dispatch system (some trickery
needed because static callbacks don't have the "this"
pointer). Sure, the stack doesn't unwind -- in fact,
we go even deeper. But it is often enough. In my main
application, I updated a progress bar and called
Qapplication::processEvents() so that the user doesn't
feel like the GUI stuck.
> In a Qt program, the most sensible way of handling a long task
> is by having request functions that return immediately, and
> signals to indicate progress or completion.
That's just what I did, except deeper in the execution stack.
> What I propose is that the provider plugin should create an
> internal thread, invisible to the QCA user. This is how my NDns
> works, and
> means the user doesn't have to worry about thread-safety.
That would be a cleaner idea. I'll try to see how to implement
this in any new code I write.
> True, someone might be using a compiled Qt that does not have
> threading support, but I hope those days are coming to an end.
> Qt 4 plans to make threading a staple feature.
I'm eager to see this working. In the meantime, I used the
callback approach because so much of Qt's documentation says
so many things are not reentrant or not thread safe, I decided
to postpone my dive into threads for a little down the road.
> One challenge with QCA is to strike a balance between
> complexity and simplicity. There are a LOT of crypto details
> out there, but less choice means less confusion. For example,
> when signing with a PrivateKey, QCA2 doesn't have a choice in
> selecting the signing algorithm (ie, EMSA1,2,3,4). Maybe this
> is a bad thing.. I'm not sure yet. In any case, if there are
> multiple choices for something, but most use-cases involve only
> one of them, then we should just go with that one, unless we
> personally have reasons to need more than that.
I do have a need for many choices though, but this is hard to
explain now. It'll become clear later on. The bottom line is that
I'd prefer sensible defaults instead of too many restrictions.
So simple things are kept simple but if you need to do something
nonstandard, you can.
> For RSA, you've added password protected PEM. I have done
> this in QCA2, but I left out the 'algorithm' parameter, and
> just use TripleDES (Botan recommends everyone uses it).
It was easy enough to add and some of my users said they wanted
AES (for no justifiable reason... for pwd encryption 3DES is
great because it's so slow... but my marketroid users want it
for compliance with competing products spec sheets).
> What is RSA::context() ? I hope it has no relation to
> fromNative() (which I've taken out).
For some reason I needed the context for some type conversion,
but I can't remember exactly right now. I'll reread the code and
get back to you.
> What is RSA::toSPKAC() ?
In my app I generate a new keypair that is sent to a Certificate
Authority. This CA accepts the public key in SPKAC (Signed Public
Key and Challenge) format. This is the Netscape-style of generating
keypairs and sending the public key to the CA (this is done with the
<KEYGEN...> tag). IE, on the other hand, uses a whole different and
more complicated approach. To keep things simple in my app, I used
> What is "NON_EVP_BASED_STUFF" ?
> #ifndef NON_EVP_BASED_STUFF
> bool sign(const QByteArray &a, QByteArray *out) const;
> int verify(const QByteArray &a, QByteArray &sig) const;
> bool sign(const QByteArray &a, QByteArray *out, bool
> oaep=false) const;
> bool verify(const QByteArray &a, QByteArray *out, bool
> oaep=false) const;
Ooops, sorry... early tests I forgot to take out. Wipe them.
> Just a comment on RSA components:
> QString modulus();
> QString exponent();
> Thankfully I now have QBigInteger for these things. :)
Great. I imagine we have a way to convert those QBigIntegers
to nicely formatted QStrings that my app needs.
> I am just now getting to improving the Cert stuff, let's see
> what you've got here:
> What is this?
> CertProperties extensions() const;
X.509v3 certificates have those things called extensions that
define how certs are to be used, how to properly chain them up
to their issuers, the policies of their issuer CAs and a whole
lot of sometimes useful, sometimes confusing, information. My
app has to interpret lots of them. Example:
$ openssl x509 -in ricardo-theil.pem -text -noout
Version: 3 (0x2)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=BR, O=ICP-Brasil, CN=SERASA Certificadora Digital
Not Before: Apr 7 13:06:03 2003 GMT
Not After : Apr 6 13:06:03 2006 GMT
Subject: C=BR, O=ICP-Brasil, OU=(em branco), OU=(em
<< some stuff deleted for sake of brevity >>
> X509v3 extensions:
> X509v3 Authority Key Identifier:
> X509v3 Certificate Policies:
> Policy: 18.104.22.168.2.3.3
> X509v3 CRL Distribution Points:
So, this Cert::extensions() method just return those things as
name-value pairs. There's a kludge: extensions also have a flag
to tell them whether they are critical or not. The critical ones
have an "*" appended to their names. Yeah, I know this is ugly.
I planned to fix this later, creating a nice class for it.
> And this?
> int verifyChain(const QPtrList<Cert> &list, int *err=NULL,
> int *depth=NULL)
> My guess is to allow cert validation outside of SSL, which would be
Precisely. Pass it a list of certs and it'll tell you whether the
signature chain, validities, etc., are all ok. Essentially the
same the "openssl verify" command does.
> By the way,
> QString publicKeyAlgorithm() const;
> RSAKey toRSAKey();
> the above functions will be replaced with:
> PublicKey subjectPublicKey() const;
> These are evil, probably:
> void *toPkey();
> void *context();
Again, I needed them for some odd reason.
> Explain these:
> QString signatureAlgorithm() const;
> QString signature() const;
As I said, my app dissects the certificate. There's this dialog that
displays even more info than the "openssl x509" command. Those two
get the name of the signature algorithm used in the certificate
(most commonly sha1WithRSAEncryption or md5WithRSAEncryption) and
the signature block itself (which should be a QBigInteger).
> Finally, what exactly are PKCS7 and PKCS12? At a glance, it
> seems PKCS7 is for generating certs. I didn't think I'd go that
> far, but I don't see a problem with this. :)
PKCS7 is a standardized format for a "bag" that can hold certs,
signatures and messages. For instance, when a CA signs your
certificate, it sends it in a PKCS7 bag along with its own CA
cert. The PKCS7 can assemble and dissasemble those bags from/to
a nice QPtrList<QCA::Cert>, along with saving/reading to/from
disk or memory in PEM (Base64+armor).
PKCS7 can also do S/MIME encryption and signatures. The PKCS7
class can both generate those sigs and verify them. I didn't
implement the encryption/decryption stuff just yet.
PKCS12 is a limited PKCS7 bag + private keys. That's what you
use when you want to move your private key, say from IE to
Mozilla or vice versa. The class uses the OpenSSL "keep it simple"
API to allow importing/exporting of cert chains and private keys.
(Those were two *very* oversimplified explanations of that PKCS7
and 12 are... I hope there aren't any PKI picky pundits in this
I hope I have made things a little bit clearer.
-----BEGIN PGP SIGNATURE-----
Version: PGP 8.0
-----END PGP SIGNATURE-----
More information about the Delta-affinix.com