0

I created a CSR file and a private key PEM file used the following command in openSSL

openssl req -new -utf8 -nameopt multiline,utf8 -config rahat.cnf -newkey rsa:2048 -nodes -keyout rahat.key -out rahat.Csr

Then I got the certificate from authorities in the form of a crt file. I converted to cer and then extract the public key with the following command in OpenSSL

openssl x509 -pubkey -noout -in rahat.cer > pubkey.txt

Then I created a p12 file containing the certificate and also both the public and private keys using the following OpenSSL command:

openssl pkcs12 -export -out rahat.p12 -inkey rahat.key -in rahat.cer

I have a physical actual ePass3003Auto token. I imported the p12 file into this Token used ePassManagerAdm_3003.exe application to create a signature. Then extracted the cer file and extracted the public key and compared with the pubkey.txt above and both were identical.

Now the problem:

I used the actual token to sign a "Hello World" string in java. It worked and then I could verify the signed data using certificate and public key again in java.

On the other hand I used contents of the rahat.key file that is actually Base64 private key, and with the following lines in java I signed "Hello World" again.

Suppose PRIVATE_KEY is the private key string.

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.security.cert.Certificate;
import java.security.Provider;
import java.security.Security;
import java.util.Base64;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;


public byte[] signData(byte[] data, String PRIVATE_KEY) throws Exception {

    byte[] encoded = Base64.getDecoder().decode(PRIVATE_KEY);

    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PrivateKey pk = kf.generatePrivate(keySpec);
    
    Signature signature = Signature.getInstance("SHA256withRSA");
    signature.initSign(pk);
    signature.update(data);

    byte[] signedData = signature.sign();

    return signedData;
}`

WHY the result are different? Shouldn't be the resulting signed data from two methods be identical?

Here are the signing code with the actual Token:

    Provider p = Security.getProvider("SunPKCS11");
    p = p.configure("config.cfg");
    Security.addProvider(p);
    KeyStore keyStore = KeyStore.getInstance("PKCS11", p);

    char[] pin = "4321".toCharArray();
    keyStore.load(null, pin);

    java.util.Enumeration<String> aliases = keyStore.aliases();
    String alias = aliases.nextElement();

    PrivateKey pk = (PrivateKey)keyStore.getKey(alias, "4321".toCharArray());
    Certificate[] chain = keyStore.getCertificateChain(alias);
    X509Certificate cert = (X509Certificate)chain[0];

    Signature signature = Signature.getInstance("SHA256withRSA");
    signature.initSign(pk);
    signature.update(data);

    byte[] signedData = signature.sign();

    signature.initVerify(cert.getPublicKey());
    signature.update(data);
    boolean verified = signature.verify(signedData);
    System.out.println("Verified: " + verified);
    return signedData;

Please check the second part of the code "signing with token". What changes should I make?

I can do nothing about the first part of code. What I am concerned is regarding the second part of code when signing with the Token.

Any comment on this matter is appreciated.

RAHAT
  • 1
  • 2
  • Are you sure your token sign with SHA256 and PKCS#1 padding? Java Signature output is PKCS#1 signature. To generate a PKCS#7 signature in Java, you would typically use the CMSSignedData class in the Bouncy Castle library or the SignedData class in the Java Security API. – Ziv Apr 26 '23 at 16:13
  • Yes _that_ signature scheme (RSASSA-PKCS1-v1_5) is deterministic and two signing operations on the same data with the same key(pair) should produce the same signature. (This is not true of many other signature schemes.) Since I obviously can't reproduce the problem, I don't know what else to tell you. PS: rahat.key (like most but not all files used by OpenSSL) is PEM format, which is not _just_ base64, it is base64 with linebreaks and begin/end lines -- those matter; see wikipedia or rfc7468. – dave_thompson_085 Apr 26 '23 at 16:15
  • About rahat.key, yes you are right. I removed all CRs and made a string, I uploaded the public key to a website, and the combincation of both private and public key on the website works fine, and I was able to get some information, especially I could login to the website. The problem is when I use actual TOKEN and sign. That is why I used the two methods on a "Hello World" and I saw the resulting System.out.println(Base64.getEncoder().encodeToString(signedData)); are different. – RAHAT Apr 26 '23 at 22:50
  • Hi @Ziv, thanks for the comment. Would you please explain a little bit more. The PKC8 code , I can't do anything about it. But the code for the Token I can. What is this pkcs#1 padding? – RAHAT May 01 '23 at 09:48

0 Answers0