1

The original goal is:

Generate a https url where one of parameters is PKCS7 detached signature (RSA, SHA-256, UTF-8, BASE64).

What do I have:

  1. private key (.key file begin with "-----BEGIN RSA PRIVATE KEY-----", end like this "kIng0BFt5cjuur81oQqGJgvU+dC4vQio+hVc+eAQTGmNQJV56vAHcq4v -----END RSA PRIVATE KEY-----")
  2. self signed certificate (.cer file begin with "-----BEGIN CERTIFICATE-----", end like this "xwRtGsSkfOFL4ehKn/K7mgQEc1ZVPrxTC7C/g+7grbKufvqNmsYW4w== -----END CERTIFICATE-----")
  3. data to sign

I found a java code that do almost what I need.

Method signature:

 public static String sign(PrivateKey privateKey,
                           X509Certificate certificate,
                           String data);

Now I'm stuck on how to get PrivateKey and X509Certficiate classes from given files.

I looked at many examples and got confused by these moments:

1.

KeyStore ks = KeyStore.getInstance("pkcs12");

or

PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);

Didn't find alternatives for PKCS7 standard.

  1. A snippet of method that builds PrivateKey using bouncycastle library:

        inputStream = Files.newInputStream(privateKeyFile.toPath());
        reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
        pemParser = new PEMParser(reader);
        PEMDecryptorProvider decryptorProvider = new JcePEMDecryptorProviderBuilder()
                .setProvider(PROVIDER)
                .build(privateKeyPassword.toCharArray());
        PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair) pemParser.readObject();
        PEMKeyPair keyPair = encryptedKeyPair.decryptKeyPair(decryptorProvider);
        ...
    

In this example I have to provide some privateKeyPassword to PEMDecryptorProvider. What is the point of this password and where can I get it?

From keyPair value I can get both privateKey and publicKey.

What is the connection between publicKey from PEMKeyPair and my certificate ? Are they the same?

Any help will be appreciated, thanks!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Egor Stepanov
  • 745
  • 5
  • 7
  • Try ```Key RSAKey = KeyFactory.getInstance("RSA"). generatePrivate(new X509EncodedKeySpec(keyBytes));``` – zhh Aug 12 '18 at 21:07
  • 1
    @zhh: you can't generate a private key from an X509EncodedKeySpec. – President James K. Polk Aug 12 '18 at 21:18
  • 1
    The file extensions `.key`.and `.cer` are not particularly meaningful. What matters is the format of the contents of these files, not the file extensions themselves. Is the private key encrypted? Is it base-64 encoded? Does the `.key` file start out like `-----BEGIN `? Does the `.cer` file start out that way also? – President James K. Polk Aug 12 '18 at 21:19
  • @JamesKPolk, Hey! I updated the post, yes the private key and certificate is base-64 encoded, both start out like ---- BEGING . – Egor Stepanov Aug 13 '18 at 08:14
  • @JamesKPolk: >> "Is the private key encrypted?" I don't really know. How to figure it out? I added the last line of the key's body. – Egor Stepanov Aug 13 '18 at 08:18
  • run `openssl rsa -in private.key`. If the command asks you for a password then the file is encrypted. If it completes successfully without asking for a password then it's *not* encrypted. – President James K. Polk Aug 13 '18 at 17:17
  • It's not really clear what you are trying to accomplish here. [This answer](https://stackoverflow.com/a/41953072/238704) shows how to read in your private key. – President James K. Polk Aug 13 '18 at 18:34

1 Answers1

3

You don't need bouncycastle to read in the public key as Java's CertificateFactory directly supports the format of your .cer file.

The private key appears to be in a PKCS1 format that openssl can produce. If you wish to keep that format this answer shows how to extract the private key. Combining the two, here is a short snippet to read in a certificate and a private key.

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

import java.io.FileInputStream;
import java.io.FileReader;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

public class Main {

    private static PrivateKey readPrivateKey(String filename) throws Exception {
        PEMParser pemParser = new PEMParser(new FileReader(filename));
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
        PEMKeyPair pemKeyPair = (PEMKeyPair) pemParser.readObject();
        KeyPair kp = converter.getKeyPair(pemKeyPair);
        return kp.getPrivate();
    }

    private static X509Certificate readCertificate(String filename) throws Exception {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        return (X509Certificate) certificateFactory.generateCertificate(new FileInputStream(filename));
    }

    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        PrivateKey privateKey = readPrivateKey("myKey.priv");
        X509Certificate cert = readCertificate("mycert.cer");
    }
}
President James K. Polk
  • 40,516
  • 21
  • 95
  • 125