Hi Igor,
I'm happy to hear that it works for you.
Regarding your questions:
- i have studied the crypted file produced and it is really closed to the ones i create with my applet using BouncyCastle so i would know if you have used BouncyCastle to encapsulate in PKCS7 ?
No, I can guarantee that all code in JCAPI is solely implemented by Pheox with one exception only; the CertFactory plugin is based upon parts of Bouncy Castle. In this case we have been very clear to state this in our documentation and we have also included Bouncy Castle's license file in the plugin JAR file.
The PKCS#7 functionality used in JCAPI is based upon the native PKCS#7 enabled streaming functions provided by MS CAPI and its installed CSPs. This is the reason why the performance is extremely good. I have not done any measurements, but I doubt that Bouncy Castle would reach JCAPI's figures since it's plain byte code processing with help from Hot Spot.
- when i crypt for two recipients (one with private key on a USB token and the other with private key in Windows store), whatever the order of the certificates it always ask me for the PIN code, so do you uncrypt for all the recipients ?
Ah, very interesting. I've not tried it myself, but I believe you. Just to be sure, I did double check my implementation and it's correct i.e. during encoding JCAPI forwards all certificates to MS CAPI in the same order as JCAPI receives them, and during decoding JCAPI iterates the certificates from MS CAPI as given by MS CAPI. This means that MS CAPI (well, the current CSP) do some kind of sorting of the certificates when they are to be stored in the envelope.
JCAPI will iterate through the certificates stored in the envelope and use the first one available whose certificate can be found in the MS CAPI MY system store with an associated private key. When a match is found, the iteration is stopped.
- your new version works very well and is compliant with some tokens which didn't worked with the previous one so do you think that it could be possible to make this new version the default one and become JCE compliant ? (your static methods encryptMessage and decryptMessage could be used to implements wrap and unwrap of the Cipher abstract class)
The new PKCS#7 functionality will be released in JCAPI 1.2.5. But it will remain as it is. The reason is that this is pure PKCS#7 functionality including both symmetric- and asymmetric cryptography plus ASN.1/BER encoding/decoding. The Cipher class is only used for plain symmetric- and asymmetric cryptography operations and it doesn't include the logic of PKCS#7 structures. Unfortunately, SUN has not defined any PKCS#7 APIs in Java, so we're stucked with divergent APIs.
- there's no mean to choose the private key to use for decryption when there are several ones possible so when the PIN code is asked you don't know which one you have to enter (it's dangerous when 5 Pin codes are possible (ie a file crypted with 5 certificates) thinking that most of the cards block after 3 tries.
This behavior is unfortunately not controlled by JCAPI. MS CAPI will display the PIN code dialog when access to a protected private key is required. This problem exists for all other applications as well.
JCAPI supports "certificate aware" PIN code dialogs, but then you have to use PKCS#11, which is out of the question in this case.
To conclude i wanted to tell you that your test program has a little bug : I've launched it as an applet and when the processing is finished but the applet still loaded i can't delete it (in Windows explorer : i've commented your deleteFiles method). This is corrected by closing the FileOutputStream after the BufferedOutputStream, for example :
Sounds like a bug in Java. If you take a look in the Java documentation for method close() in class BufferedInputStream it clearly says:
Closes this input stream and releases any system resources associated with the stream. Once the stream has been closed, further read(), available(), reset(), or skip() invocations will throw an IOException. Closing a previously closed stream has no effect.
This means that BufferedInputStream must call close() on aggregated streams as well i.e. on our FileInputStream instance.
And in your filesAreEqual method you don't close any FileInputStream nor BufferedInputStream.
Admit. That's a bug. Was too quick there. I'll do as Google and call this code BETA until no one complains anymore
I always make such bugs all the time. So don't worry about it.
I never worry
Ok, can we close this case now? It's not possible to get your token to work with CryptDecrypt, but we can circumvent it through the MS CAPI streaming API for PKCS#7.
Regards,
Tommy