Convert SSL private key to a string - c

From pkcs12 file, I extracted the private key and cert using the following -
PKCS12_parse(p12, argv[2], &privatekey, &cert, &ca);
Now, I need to use the privatekey and cert to sign an XML using xmlsec libraries.
However, xmlSecCryptoAppKeyLoad() expects the key in const char* format.
How do I do the conversion?
Or, can I use xmlSecCryptoAppKeyLoadMemory() and privatekey without having to do the conversion?

If you use the XMLSEC-OpenSSL interface, the xmlSecOpenSSLEvpKeyAdopt() function loads an xmlsec key object from an OpenSSL EVP_PKEY *, and xmlSecOpenSSLKeyDataX509AdoptKeyCert() loads an OpenSSL X509 certificate.

Related

How can I read an encrypted private key in an sftp producer?

I'm trying to upload a file to an sftp holding a public key. I have the private key in my project I generated through ssh-keygen with a passphrase set. I have tried this:
public void configure() throws Exception {
var connection =
sftpProperties
.getSftpForEntity("target")
.orElseThrow(SftpProperties.noSuchEntity("target"));
var privateKey = ArrayUtils.toObject(Files.readAllBytes(Path.of("src/main/resources/id_rsa")));
from(
file("test")
)
.to(
sftp(connection.getConnectionString("/hello"))
.username(connection.getUser())
.privateKeyPassphrase("pass")
.privateKey(privateKey)
);
}
}
org.apache.camel.component.file.GenericFileOperationFailedException: Cannot connect to sftp://arcapptest#us2.hostedftp.com:22
...
Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B#71068da
It seems like the passphrase isn't being applied. I've also tried this:
.to(
sftp(floridaConnection.getConnectionString("/hello"))
.username(floridaConnection.getUser())
.privateKeyPassphrase("pass")
.privateKeyFile("src/main/resources/id_rsa")
);
with same result.
I've tried using the unencrypted private key, and that works.
The problem was the encryption of the private key. Camel uses JSch to deal with the key, and it needed to be PEM. I converted the key using this: ssh-keygen -p -f /path/to/key -m pem. After, the passphrase could be used to read the key.

OpenSSL: certificate in memory not getting validated properly

I'm hoping someone can help with my OpenSSL(1.1.1k) issue I'm having when trying to validate a certificate on the client against a server. The certificate contents are specified in text and not in a .PEM file on the client side. Some sample code is here:
bool setCert(SSL_CTX* ctx, LPCSTR cert)
{
//cert is the text of the certificate e.g. -----BEGIN CERTIFICATE----- blah -----END CERTIFICATE-----
bool bOk = true;
if (!cert.empty()) // no cert on disk
{
BIO *bioCert = BIO_new_mem_buf((void*)cert, -1);
X509* pCert = PEM_read_bio_X509(bioCert, NULL, 0, NULL);
if (SSL_CTX_use_certificate(ctx, pCert) != 1)
{
//log errror, "Invalid certificate"
bOk = false;
}
BIO_free_all(bioCert);
X509_free(pCert);
}
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3); // other options not used atm SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
return bOk;
}
After this method returns, I create an SSL object based on the context, with SSL_new(ctx).
I then call SSL_Connect(ssl)
The handshake occurs and is accepted even if I pass in an invalid certificate.
My assumption here is that it's doing this because I do not set the verify method like:
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
My understanding is that I cannot use SSL_VERIFY_PEER unless there is a cert / .PEM file on disk on the client side to validate against.
How can I validate the handshake when keeping the certificate contents in memory?
If I change the code to use a PEM file, call SSL_CTX_use_certificate_file instead of SSL_CTX_use_certificate, it works. In that case I did set SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
Any help here is greatly appreciated. Thanks
SSL_CTX_use_certificate is used for setting up the certificate which should be used locally to authenticate against the peer. It needs to be accompanied with a private key, setup with SSL_CTX_use_PrivateKey. But authenticating against a peer, i.e. using a client certificate, is not what you intend to do in your client.
Instead you want to setup a certificate for use as a trusted CA when validating the server certificate. The correct function for this would be X509_STORE_add_cert instead:
X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), pCert);

Getting Subject Alternative Name OpenSSL

I am attempting to retrieve the subject alternative name from my client certificate. By running this command, I can see the SAN:
openssl x509 -noout -text -in certname.cert.pem
...
X509v3 Subject Alternative Name:
IP Address:10.10.10.10
In a C file, I am trying to retrieve the client SAN, so that I can validate it with the server IP. Here is my attempt:
cert = X509_STORE_CTX_get_current_cert(x509Ctx);
int i;
int san_names_nb = -1;
STACK_OF(GENERAL_NAME) *san_names = NULL;
// Try to extract the names within the SAN extension from the certificate
san_names = (GENERAL_NAME*)X509_get_ext_d2i((X509 *) cert, NID_subject_alt_name, NULL, NULL);
if (san_names == NULL)
{
return Error;
}
Right now, my code is returning the error because san_names is NULL. Any guidance would be much appreciated. Thank you!
The OpenSSL command itself gives the SAN as Null
X509v3 Subject Alternative Name: **<BLANK>**
IP Address:10.10.10.10
Can you just open the certificate and see if it contains the SAN. If not you will have to ask the team to add the SAN and create a new certificate again.
You are misusing X509_get_ext_d2i(). Per the OpenSSL documentation for X509_get_ext_d2i() (bolding mine):
If idx is NULL then only one occurrence of an extension is permissible otherwise the first extension after index *idx is returned and *idx updated to the location of the extension.
Depending on the version of OpenSSL you're using, the behavior might be slightly different. The above is the documented behavior for OpenSSL 1.1.0.
Since you are passing NULL as idx, if there's more than one SAN on the cert you'll get NULL from X509_get_ext_d2i().
You can get the OpenSSL error code with ERR_get_error().

Verify private key pass phrase after extracting key from PKCS#12 file

I'm trying to read the PKCS#12 file and extract private key programmatically in C. I've found here solution, but this program automatically decrypts my private key and checks only the PKCS#12 file password. Is there any way to also verify the private key passphrase?

Sign with private key and verify with public

OpenSSL's rsautl allows signing with a private key. This is without a hash. Then recovering the signed file with a public key.
I've looked at CryptCreateHash/CryptSignHash/CryptHashData but I'm not sure how to do it. I believe those functions will only sign the hash of the data, not the data itself.
Is there any way I can sign with the private key and no hash involved?
Edit: Made necessary changes from jww's recommendations.

Resources