Pheox - Forums
  [Search] Search   [Recent Topics] Recent Topics   [Hottest Topics] Hottest Topics   [Top Downloads] Top Downloads   [Groups] Back to home page 
[Register] Register /  [Login] Login 

Strange behaviour with Aladdin eToken RSS feed
Forum Index » General Issues
Author Message
adeteran

Visitor

Joined: Nov 29, 2007
Messages: 4
Location: CORPME
Offline
Hi, we are using JCAPI to sing and validate documents from an applet. It's the best proveder we have found at time, to access MSCAPI, so we'll gladly buy a license to use it, when all tests are OK.

Our problem: we sing and validate files, and everithings works fine when certificates and private keys are instaled in local machine.

When we use a certificate in an eToken to sign (production users will only use eToken, and will never install private key in local machine), nothing strange happens (it works, apparently). But when we validate the signature, an exception is thrown, due to an incorrect encripted digest (we use PKCS#7 to exchange signatures, generated and parsed with IAIK).

We have tested the same code using SunMSCAPI provider, from JDK 6, and it works well. Validation only fails when usin JCAPI provider to sign (no matter what provider is used to validate). But SunMSCAPI don't fits our needs, as well as JCAPI.

We have also tested eToken with an ActiveX we are actually using for the same thing (but we want to migrate to Java, to support more browsers), in the same environment, and it works.

So I think we can discard eToken and applet implementation as a cause.

I have make a small test program thas signs a simple text, using both JCAPI and SunMSCAPI, with same algorithm, certificate and eToken. And encrypted digests are different. Code follows:


import java.security.KeyStore;
import java.security.Security;
import java.security.Signature;
import java.security.UnrecoverableEntryException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Enumeration;

import com.pheox.jcapi.JCAPIProperties;
import com.pheox.jcapi.JCAPIProvider;
import com.pheox.jcapi.JCAPIUtil;

public class TestJCAPI {

private final static String CN = "..."; // Put your ceritificate CN

private final static byte[] DATA = "Test".getBytes();

private static byte[] sign(KeyStore keyStore, String cn, byte[] data) throws Exception {
System.out.println("Using " + keyStore.getProvider().getName());

// Search entry by CN
KeyStore.PrivateKeyEntry privateKeyEntry = null;
Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
if (keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
X509Certificate x509Certificate = (X509Certificate) keyStore.getCertificate(alias);
if (x509Certificate.getSubjectX500Principal().getName().indexOf(cn) >= 0) {
try {
privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, null);
} catch (UnrecoverableEntryException e) {
privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection(null));
}
}
}
}
if (privateKeyEntry == null) {
System.out.println("Certificate not found");
return null;
}

// Sign
System.out.println("Signing with " + ((X509Certificate) privateKeyEntry.getCertificate()).getSubjectX500Principal());
Signature signature = Signature.getInstance("SHA1withRSA", keyStore.getProvider());
signature.initSign(privateKeyEntry.getPrivateKey());
signature.update(data);
byte[] encryptedDigest = signature.sign();

System.out.println("Encrypted Digest (" + encryptedDigest.length + "): " + Arrays.toString(encryptedDigest));
return encryptedDigest;
}

public static void main(String[] args) throws Exception {
Security.addProvider(new JCAPIProvider());
JCAPIProperties.setLogging(true);
System.out.println(JCAPIUtil.getEnvironmentInfo());
System.out.println();

KeyStore ksJcapi = KeyStore.getInstance("msks", "JCAPI");
ksJcapi.load(null, null);
JCAPIProperties.getInstance().setMSCertStoreNames(new String[]{"My"});
byte[] encryptedDigestJcapi = sign(ksJcapi, CN, DATA);

System.out.println();

KeyStore ksJdk = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
ksJdk.load(null, null);
byte[] encryptedDigestJdk = sign(ksJdk, CN, DATA);

System.out.println();
System.out.println(Arrays.equals(encryptedDigestJcapi, encryptedDigestJdk));
}
}


We don't have a clue of what's wrong.

Hardware is an USB eToken Pro 32K. Software is eToken Run Time Environment 3.65.
adeteran

Visitor

Joined: Nov 29, 2007
Messages: 4
Location: CORPME
Offline
Hi again. I have discovered the problem, and made a workaround.

As eToken Base Cryptographic Provider is a supported CSP, JCAPI access directly to it, bypassing MSCAPI. If I remove eToken Base Cryptographic Provider support, forcing JCAPI to access it via MSCAPI, things work fine, and encrypted digests using JCAPI and SunMSCAPI are identical.

Removing eToken support is done with:
JCAPIUtil.removePKCS11CSP("eToken Base Cryptographic Provider");


Although this workaround works, it shows that there is some kind of issue with eToken Base Cryptographic Provider support in JCAPI. I hope this information helps to improve it.
tommy

Visitor

Joined: May 30, 2005
Messages: 148
Offline
Hi adeteran,


Hi, we are using JCAPI to sing and validate documents from an applet. It's the best proveder we have found at time, to access MSCAPI, so we'll gladly buy a license to use it, when all tests are OK.

Thank you. Every contribution is step forward of making JCAPI better.

Regarding your problem; I've verified it and you are correct. We have not discovered it ourselves until now since all signatures made through a PKCS#11 CSP have been verified through MS CAPI. That's why the signatures also are successfully validated through both JCAPI and SunMSCAPI providers.

There's nothing wrong with the signatures, but we have to investigate why the signatures are different (which formats) when generated through MS CAPI and PKCS#11.

Regards,
Tommy
tommy

Visitor

Joined: May 30, 2005
Messages: 148
Offline
Hi,

I've looked further into this.
Unfortunately, our PKCS#11 implementation creates a raw signature based on the given hash i.e. the signature is created from hash value + PKCS#1 padding which is then encrypted using the private key stored on the token. The good part is that it is still a valid signature that is correctly verified by MS CAPI. However, the signature should be a valid PKCS#1 signature where the hash (digest) value should be put into a DigestInfo structure which is then padded to block limit and then encrypted (see the RSA PKCS#1 standard for further info).

We'll get a fix on this as soon as possible.

Regards,
Tommy
tommy

Visitor

Joined: May 30, 2005
Messages: 148
Offline
UPDATED INFORMATION!

We have now implemented a DigestInfo ASN.1/DER encoder into JCAPI's PKCS#11 layer. This encoder is now used together with the PKCS#11 providers to generate RSA PKCS#1 compliant signatures.

This fix has been incorporated into JCAPI v1.2.3.

For more info, please see:
http://pheox.com/posts/list/39.page

Regards,
Tommy
 
Forum Index » General Issues
Go to:   
Mobile view
Powered by JForum 2.8.3 © 2023 JForum Team • Maintained by Andowson Chang and Ulf Dittmer