How to re-encrypt the private key of a certificate in AES? - java

Tried to read the private key (test.key.pem) of the certificate
str = private key without -----BEGIN ENCRYPTED PRIVATE KEY----- and -----END ENCRYPTED PRIVATE KEY-----
byte[] bytes = Base64.getDecoder().decode(str);
EncryptedPrivateKeyInfo epk = new EncryptedPrivateKeyInfo(bytes);
But I'm getting an error
PBE parameter parsing error: expecting the object identifier for AES cipher
After I experienced making rsa aes certificate in openssl:
rsa -aes-256-cbc -in Z:\40000214_test.key -out Z:\file.txt.enc
But I catch completely different errors.
For example this:
java.io.IOException: DerInputStream.getLength(): lengthTag=5, too big.
also instead of "rsa" command I used "enc" and the result was also erroneous
as a result, I was able to achieve re-encryption of the private key. openssl
pkcs8 -v1 PBE-SHA1-3DES -topk8 -in so_privatekey_secret.pem -out so_privatekey_3des_secret.pem
But the problems did not leave me and when sending the request I received the following exception
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
The certificate is expired there, but requests go through postman and also with a new private key
I disabled all certificate checks in Java Control Panel but it didn't help, I also imported the certificate into jvm

Related

How to convert Curl SSL requests into Java code

Curl allows making 2-way SSL requests by specifying the certificate and private key files like the two curl requests below
First get an access token:
$ curl https://connect2.server.com/auth/token
-H "Authorization: Basic $BASIC_AUTH"
--cert ~/certs/certpath/fullchain.pem
--key ~/certs/certpath/privkey.pem
Then use the token to access the API:
$ curl https://connect2.server.com/api/public/preview1/orgs/$ORGUUID/API
-H "Authorization: Bearer $ACCESS_TOKEN"
--cert ~/certs/certpath/fullchain.pem
--key ~/certs/certpath/privkey.pem
Question:
How to implement the above requests in Java? What libraries are required? Java seems to use p12 file, however, we have .pem files.
‌1. You can convert PEM privatekey plus chain to a PKCS12 file using openssl pkcs12 -export. That is not programming or development and no longer ontopic here, but there are dozens of Qs about this here going back many years when topicality was broader, as well as in other Stacks (security.SX, serverfault, superuser, maybe more).
‌2. If you don't have or dislike OpenSSL, you can read those files (among others) into any kind of Java keystore (JCEKS, JKS, PKCS12, and several BouncyCastle variants you probably don't want) using the software from https://www.keystore-explorer.org . That's also offtopic, and I've seen some existing Qs mention it but not many.
‌3. If you want to do this with your own code, which is ontopic, and assuming your curl uses OpenSSL or at least those files are OpenSSL formats:
3.0 Java can read PEM cert sequence with CertificateFactory.getInstance("X.509") then generateCertificates(InputStream) (note s) -- the doc is a bit sketchy but this method actually can handle separate certs as DER or PEM (which you apparently have), or PKCS7 containing certs as a single blob (commonly called p7b or p7c) ditto.
3.1 if that privkey file is PKCS8-unencrypted, i.e. if the PEM labels are BEGIN/END PRIVATE KEY with no other word between, that case can be handled by standard Java, assuming you know what algorithm it is for (which if necessary you can determine from the first=leaf certificate). Delete the BEGIN/END lines and decode the rest from base64 to binary either ignoring linebreaks (with Base64.getMimeDecoder()) or with .getDecoder() after deleting the linebreaks. Put the result in PKCS8EncodedKeySpec and feed it to generatePrivate in a KeyFactory instance for the correct algorithm.
3.2 BouncyCastle (bcpkix+bcprov) can read all the PEM formats for privatekey used by OpenSSL with PEMParser and JcaPEMKeyConverter and if applicable a DecryptorBuilder. There are many existing Qs on this that you can find with that fairly-unique classname. This does mean a dependency on Bouncy.
3.3 if you don't have or don't want Bouncy and have a format other than PKCS8-unencrypted, life gets harder. You could avoid this by using OpenSSL to convert the privkey file to PKCS8-unencrypted putting you back in #3.1, but if you do that you might as well go way back to #1 and use OpenSSL to convert the lot to PKCS12 in one foop.
if you have an OpenSSL 'traditional' algorithm-specific format like BEGIN/END RSA PRIVATE KEY or BEGIN/END EC PRIVATE KEY, and the first two lines after BEGIN are NOT Proc-type: 4 and DEK-info, you can base64-decode the body and convert it to PKCS8 by adding a (DER) prefix in front that specifies the algorithm and 'wraps' the algorithm-specific part. I think there are dupes for this but I can't presently find any; if this case applies and you identify the algorithm I'll add it.
if you have a 'traditional' format that does have Proc-type: 4 and DEK-info, or you have BEGIN/END ENCRYPTED PRIVATE KEY, those are encrypted. Making sense of them with only standard Java is a fair bit of work which I'll do only if you can't use the other options and specify exactly what case you have.
Following are the steps & code to add SSL certificates into HTTP Post request.
STEP 1. CONVERT PEM CERTIFICATE TO P12 FORMAT
openssl pkcs12 -export -out cacert.p12 -inkey /etc/letsencrypt/archive/server/privkey21.pem -in /etc/letsencrypt/archive/server/cert21.pem -certfile /etc/letsencrypt/archive/server/chain21.pem -passin pass:PWD -passout pass:PWD
STEP 2. (OPTIONAL NOT REQUIRED) CONVERT CERTIFICATE P12 TO JKS FORMAT
keytool -importkeystore -srckeystore cacert.p12 -srcstoretype pkcs12 -destkeystore cacert.jks
STEP 3. ADD CERTIFICATE TO HTTP POST REQUEST THROUGH SSLSocketFactory
/**
* This function is responsible to create createSSLSocketFactory with SSL certificate
* #return
*/
public static SSLSocketFactory createSSLSocketFactory(){
try
{
FileInputStream f5 = new FileInputStream(new File("/etc/letsencrypt/archive/server/cacert21.p12"));
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore ks1 = KeyStore.getInstance(KeyStore.getDefaultType());
ks1.load(f5, "PWD".toCharArray());
kmf.init(ks1, "PWD".toCharArray());
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), null, null);
f5.close();
return sslContext.getSocketFactory();
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}

Convert java cipher decrypt to python equivalent

I'm trying to convert the below java code to python:
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
serverCertificate = (X509Certificate) certFactory.generateCertificate(new FileInputStream(certFile));
Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT_MODE, serverCertificate.getPublicKey());
byte[] decryptedClientChallengeBytes = decryptCipher.doFinal(encryptedClientChallengeBytes);
The first part I think it's resolved with this:
from cryptography import x509
from cryptography.hazmat.backends import default_backend
cert = x509.load_pem_x509_certificate(key,default_backend())
cert = cert.public_key()
But I can't convert the decrypt part. I´ve tried various methods like PKCS1_v1_5.
I'm trying to implement this https://docs.oracle.com/en/cloud/saas/marketing/responsys-rest-api/RequestUserAuthorization.html
And the step i'm stacked says: "You should receive the following response from the server. Decrypt (using the RSA algorithm) the encrypted clientChallenge using server certificate's public key (which you should have downloaded and stored on your system)."
The clientChallenge received is like this:
"hc8w8gElQJQa45WGofZwsOAi4wwEIaFClI1A2PvvCw4YUc4rbnOpedkBgrNsr0FpZ6DVV_vnZNsAGg_ph75VqeKD-R-cy_RkQIdvn0W_nb0RvPGZI7zA98_t9-rJTiTSsrJ6j8KzlWV_MLydUcBBR1iotL6kXXuFKuXtTAniPx_b6do4D5p9iI7yhTfxp9knRRG6XoItgNGJwm8AnGsThIoZw9lSgUm3Dy9yzYvhXQDYKAUNc3tqd8WcSswlb5coN18Gc-We2E0xE7xehq15Ns4QNwX6WdRrfehSgOObdckUYAx7MyLT-vyfJ-APVEVrZmC18wo-Qr2A-n1NT0ARVQ"
And the server certificate is a .CER with this format:
-----BEGIN CERTIFICATE-----
.....
-----END CERTIFICATE-----
Any help would be awesome!

How can i match a CERTIFICATE against CSR in JAVA

I don't have idea how to achieve this. I refereed this link where i can match my csr with certificate.
In this tool they are getting the hash from certificate and csr and matching them.
So I also tried to get hash but i am not able to get proper value.
Here is my implementation:
BufferedInputStream bufferedIS = new BufferedInputStream(mulitpartFile.getInputStream());
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Certificate certificate = certificateFactory.generateCertificate(bufferedIS);
X509Certificate x509Certificate = (X509Certificate) certificate;
String thumbprint = DigestUtils.sha512Hex(x509Certificate.getEncoded());
But i am not getting the exact value what i am getting in there tool.
Here is my CSR and CERTIFICATE.
CSR
-----BEGIN NEW CERTIFICATE REQUEST-----
MIIC/jCCAeYCAQAwdDENMAsGA1UEAxMEMkdSSTEMMAoGA1UECxMDQUlCMRAwDgYD
VQQLEwdEZXZpY2VzMTYwNAYDVQQKEy1FdXJvcGVhbiBBZXJvbmF1dGljIERlZmVu
Y2UgYW5kIFNwYWNlIENvbXBhbnkxCzAJBgNVBAYTAkRFMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA8yh1MlHMF4Q8WJAUDjaQ6pnEKEUdl85Dhyg/STF2
uxHnasR9aBavd5he20IVmzHX3X8rG2RM3lN2QP/3j0zObpPTPHvNhp/CuTFw6qrX
JovktZv0VNIZhAWbZHl4Ar+2zX44c0VbuHOZDbrYlteREdbg0x9hNj3AObQe37TQ
33rA4jABbMEODtGlPprMSsSzUCiHJ6KRSVGGuIUAIHjgIqciLOvqfgICD6mgHi58
yeM1hi3MfXIm8BAlIFMCJZgO+IDDBFkfvCPAdDmnTy9O8e6eXFQ2etFlAgYN2l16
3NqBQw5cJ5Oyg8By4xPcreRDgmqzz2YoIZnqJGW0Y46tCwIDAQABoEUwQwYJKoZI
hvcNAQkOMTYwNDAOBgNVHQ8BAf8EBAMCBsAwIgYDVR0RAQH/BBgwFogOKwYBBAHr
EIZKAv8wLg+HBMLOFp4wDQYJKoZIhvcNAQELBQADggEBALN3kYMVHlrPWO/8yv3n
imKEgXZZRPK9rVnPtkxVKJFAnnLwMFLx8rRCxHO72FwaO+O/IXXrsUSzpOsw+QOa
+PmKDDoxNwrv66ZjKtmUItBcmT4nJHRQZzvtW1vX6m7OjB68tKeDuqoWNpbObcJv
D3TMK9XWW9NqS1sCcGF8l/xjvsWYvEOv9M3eZzq+quWb6gROQT6oFajjjpLAsfDU
/yh9Ax2bHqIjpPa8WGXkST+2Eq06SUZOBsuUae3USoEmCPNJ6pAGpIeU+HTNygmS
s9UYyMMEo8dX+CYsRk+U65PfYbXvyi0LfPAhWeEucgAcxfOVtePsSaVLDMG+4Ysi
e2M=
-----END NEW CERTIFICATE REQUEST-----
CERTIFICATE
-----BEGIN CERTIFICATE-----
MIIDyTCCArGgAwIBAgIUewyWehvM8zXxeNHiCw6jnGNj+hQwDQYJKoZIhvcNAQEL
BQAwdDENMAsGA1UEAxMEMkdSSTEMMAoGA1UECxMDQUlCMRAwDgYDVQQLEwdEZXZp
Y2VzMTYwNAYDVQQKEy1FdXJvcGVhbiBBZXJvbmF1dGljIERlZmVuY2UgYW5kIFNw
YWNlIENvbXBhbnkxCzAJBgNVBAYTAkRFMB4XDTE5MDMyMDA1NDIzOVoXDTIwMDMx
OTA1NDIzOVowdDENMAsGA1UEAxMEMkdSSTEMMAoGA1UECxMDQUlCMRAwDgYDVQQL
EwdEZXZpY2VzMTYwNAYDVQQKEy1FdXJvcGVhbiBBZXJvbmF1dGljIERlZmVuY2Ug
YW5kIFNwYWNlIENvbXBhbnkxCzAJBgNVBAYTAkRFMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA8yh1MlHMF4Q8WJAUDjaQ6pnEKEUdl85Dhyg/STF2uxHn
asR9aBavd5he20IVmzHX3X8rG2RM3lN2QP/3j0zObpPTPHvNhp/CuTFw6qrXJovk
tZv0VNIZhAWbZHl4Ar+2zX44c0VbuHOZDbrYlteREdbg0x9hNj3AObQe37TQ33rA
4jABbMEODtGlPprMSsSzUCiHJ6KRSVGGuIUAIHjgIqciLOvqfgICD6mgHi58yeM1
hi3MfXIm8BAlIFMCJZgO+IDDBFkfvCPAdDmnTy9O8e6eXFQ2etFlAgYN2l163NqB
Qw5cJ5Oyg8By4xPcreRDgmqzz2YoIZnqJGW0Y46tCwIDAQABo1MwUTAdBgNVHQ4E
FgQUXMHQnnIrkSavE10n8wS/ZD9yz8wwHwYDVR0jBBgwFoAUXMHQnnIrkSavE10n
8wS/ZD9yz8wwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAujxz
tDjgy5XIJLSbBdBQorwYa51rWaA1zlRwDW9j690JncoIsNeiuWA1MzlpcWFEwcYz
KYciJcUZSwtpao9mioGrTDrChPkfeJrpaKhUNQkQbc59YpiKyShE05KKpFjSZJzZ
p5K8mQfq6OHlee4khxVJA/VirtoWlmtzzV5XyqbCDLIBZhOj005D1eu8KBq+qN09
KKiiUC16Lgj6UdBAfQWf79yN6ymxH9mex5T2HAJQir4rdx1nc5nFpC2V1pJpS8fW
EJNQgipn6CsufB58j4eWu1QAfceRvq7C7k3MbQk3wlW67m/LVQWSu49S6MmRb0EW
a9FacTxnmJFElBO5Gg==
-----END CERTIFICATE-----
Anyone having idea to achieve this please help me.
Your code creates the hash from the complete certificate x509Certificate.getEncoded() and not the public key.

Create x.509 certificate using bouncycastle with certificate path (cert chain)

Hy Guys! I'm trying to create x.509 certificate using bouncycastle, which should be signed by another certificate and store it PEM base 64 format.
I've already have self-signed certificate (public and private key). Now I want to create new one and sign it with existing self-signed certificate.
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
keyPairGenerator.initialize(1024, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
X500Principal dnName = new X500Principal("CN=Sergey");
certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
certGen.setSubjectDN(dnName);
certGen.setIssuerDN(caCert.getSubjectX500Principal());
certGen.setNotBefore(validityBeginDate);
certGen.setNotAfter(validityEndDate);
certGen.setPublicKey(keyPair.getPublic());
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert));
certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(keyPair.getPublic()));
X509Certificate cert = certGen.generate(caCertPrivateKey, "BC");
Verification passed without exceptions, which means from my point of view that it was successfully signed by caCert:
cert.verify(caCert.getPublicKey());
Then I decode it to the PEM base 64:
PEMWriter pemWriter = new PEMWriter(new PrintWriter(System.out));
pemWriter.writeObject(cert);
pemWriter.flush();
I get something like this in the output:
-----BEGIN CERTIFICATE-----
MIIDDjCCAnegAwIBAgIBFDAN........
-----END CERTIFICATE-----
When I open it, I see the next:
Why there is no certification chain if it was successfully signed by caCert?
What need to be changed in my code to see certification chain as I expected?
I was able to find solution. Actually code works as expected. I didn't see chain of certificates because my caRoot certificate wasn't added to the trusted store. After I add my sel-signed certificate to the trusted root certified centers I see the whole certification chain as I expected.

Digital signature: sample code for verification and for extracting certification information

I use a third party tool to verify signature and to get certificate detail(like serial number, CA etc..) from signature. The problem with this utility is it is licensed and works on certain machines only.
Can i validate the signature against the data using simple java or .net code?(instead of using paid application). I dont have private key to extract certificate information from signed data.
Or if someone can suggest sample code in java or .net to extract certificate detail if i have pfx file. Of from signed data.
Data is signed with asymmetric encryption.
To extract detail from certificate:
Make a string which keeps certificate data. Just ensure it has -----BEGIN CERTIFICATE----- in starting and -----END CERTIFICATE----- in end.
Now use the following code in Java to extract certificate detail.
InputStream inStream = new ByteArrayInputStream(certString.toString().getBytes("UTF-8"));
BufferedInputStream bis = new BufferedInputStream(inStream);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(bis);
X509Certificate xCert = (X509Certificate)cert;
System.out.println("Certificate Type: "+cert.getType());
System.out.println("Public Key: \n"+cert.getPublicKey());
try{
System.out.println("Signature Algorithm"+xCert.getSigAlgName());
System.out.println("IssuerDN : "+xCert.getIssuerDN());
System.out.println("Serial Number : "+xCert.getSerialNumber());
System.out.println("SubjectDN : "+xCert.getSubjectDN());
}catch(Exception exp){
:
}
If you are having the PFX file, then that may contain the public key certificate which will be required to verify the signature.
Alternatively, if your signature is a PKCS#7 signature, then the signature itself will hold the data, signature and the certificate. Assuming PKCS#7 is not detached.
You need to ask your signer, how is he transferring his certificate for validation.

Categories