Certmgr - Self-signed certificate without private key is not updated - c++

I am working with self-signed certificates and certificate manager of Windows OS.
First of all, I have created a self-signed certificate "RootCA" which has a private/public key pair assigned, nevertheless I have destroyed private key of this certificate with the next certutil.exe command succesfully:
certutil -user -delkey "RootCA"
Also, I have check refreshing and exporting private key and it is not possible, because it has been destroyed.
The problem is when I visualize "RootCA" in Certificate Manager after destroying private key, "General" tab indicates that "You have a private key that corresponds to this certificate.":
My question is:
Are there any way to update/remove previous certificate information? And if yes, is it possible to do it programmatically?

With Microsoft CryptoAPI setting pvData parameter of CertSetCertificateContextProperty function to NULL solves the problem.

Related

How to point to/access a cert file `CertCreateCertificateContext` function? (wincrypt api)

A little new to windows programming/C++. I'm trying to install a .p7b root certificate file to the Trusted Root Certificate Store. I want to use the Windows Wincrypt library. Specifically, these are the suggested steps that I got from an old forum:
Call CertCreateCertificateContext using your certificate content bytes
in order to obtain a PCCERT_CONTEXT
Call CertOpenSystemStore with szSubsystemProtocol set to "ROOT" in
order to obtain a HCERTSTORE
Call CertAddCertificateContextToStore using the above HCERTSTORE and
PCCERT_CONTEXT.
[Here's] the api documentation for CertCreateCertificateContext. Not sure how to just point pbCertEncoded to my actual cert file. Should I just point it to the path? Do I have to load the cert in? What should the type be?
From Simon Rozman's answer in this post: We have to use CertOpenStore() instead of
CertCreateCertificateContext(), which supports one certificate only, whereas PKCS #7 file can contain many.
After the certificate store is open, you can use CertEnumCertificatesInStore() to retrieve certificate context of individual certificates from store.
So from my original steps to successfully install a p7b into the root store:
Call CertOpenStore() for the root store and for the actual certificate itself. This will give you two HCERTSTORE handles.
Have a while loop that will add the certificate contexts to the opened root store (using CertAddCertificateContextToStore()) as long as the certificate context exists (check using CertEnumCertificatesInStore() on the opened certificate store).

Look up leaf certificate from issuer’s thumbprint?

I have a leaf certificate installed on my machine, which was issued by a Certificate Authority (CA); this CA is not present on the system.
If I am given the thumbprint (i.e. the SHA-1 hash) of the CA, can I look up and thereby retrieve the installed leaf signers issued by this CA? If I am able to, then what are the required Windows function calls for accomplishing this?
I have been examining a leaf certificate and I only see the standard string representation name of the CA and not a thumbprint. This string name is not unique, hence why I am utilizing the thumbprint (SHA-1’s poor security here is not a problem as it is only used for looking up a proper signer). Microsoft has the CertGetIssuerCertificateFromStore function, but this requires having the CA in memory.
No, it is not possible to look up an issued leaf signer using only the issuer's CA's thumbprint. You first have to install the CA on the machine and then use the entirety of the CA to find its issued leaf signers. The CA's thumbprint is not stored in the leaf signers it issues from what it appears.
All in all, the first operation that needs to be done is installing the CA on the machine you want to find its issued leaf signers on.

How to do "Client Authentification" if I'm not able to provide private key

I want to set up my local server to communicate with my client. They build TLS connection using Openssl. I try to implement double side authentication, like server would verify client and client also needs to verify server.
When I use certificates generated by my self, everything works fine. The code is as following. It's C++ code in client. I set up client cert, private key and intermediate cert. In server side I saved a CA cert.
The relationship is: CA signs intermediate cert, intermediate cert signs client cert.
As we know, the reason that we need to provide client private key is the client will signature a "challenge" then send to server. Server could get client public key by certificate chain and use it to decode the encrypt "challenge" to see if they matched. You could see this link for detailed process:
https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake
However in my scenario, I have no permission to get the private key. I only have an API to call, which takes the digest or anything we want to encode as input and return a string encoded by client private key.
Therefore I'm not able to pass any "ClientPrivateKeyFileTest" to TLS.
I searched openssl source code but all handshakes were done in this function: SSL_do_handshake() and I'm not allowed to modify this function.
// load client-side cert and key
SSL_CTX_use_certificate_file(m_ctx, ClientCertificateFileTest, SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(m_ctx, ClientPrivateKeyFileTest, SSL_FILETYPE_PEM);
// load intermediate cert
X509* chaincert = X509_new();
BIO* bio_cert = BIO_new_file(SignerCertificateFileTest, "rb");
PEM_read_bio_X509(bio_cert, &chaincert, NULL, NULL);
SSL_CTX_add1_chain_cert(m_ctx, chaincert)
m_ssl = SSL_new(m_ctx);
// get_seocket is my own API
m_sock = get_socket();
SSL_set_fd(m_ssl, m_sock)
// doing handshake and build connection
auto r = SSL_connect(m_ssl);
I think all handshake processes would be done after I call SSL_connect(). So I wonder is there other way I can do to complete the client-authentication?
For example, I could skip adding private key step but set up a callback function somewhere which can handle all cases when SSL needs to use private key to calculate something.
PS: The API is a black box in the client machine.
One more thing, these days I found that openssl engine may help this problem. But does anybody know what kind of engine is useful for this problem? The EC sign, verification or others?
Final update: I implemented a OpenSSL engine to reload EC_KEY_METHOD so that I'm able to use my own sign function.
Thanks a lot!

What's the best way to store token signing certificate for an AWS web app?

I am using IdentityServer4 with .NET Core 2.0 on AWS's ElasticBeanstalk. I have a certificate for signing tokens. What's the best way to store this certificate and retrieve it from the application? Should I just stick it with the application files? Throw it in an environment variable somehow?
Edit: just to be clear, this is a token signing certificate, not an SSL certificate.
I don't really like the term 'token signing certificate' because it sounds so benign. What you have is a private key (as part of the certificate), and everyone knows you should secure your private keys!
I wouldn't store this in your application files. If someone gets your source code, they shouldn't also get the keys to your sensitive data (if someone has your signing cert, they can generate any token they like and pretend to be any of your users).
I would consider storing the certificate in AWS parameter store. You could paste the certificate into a parameter, which can be encrypted at rest. You then lock down the parameter with an AWS policy so only admins and the application can get the cert - your naughty Devs dont need it! Your application would pull the parameter string when needed and turn it into your certificate object.
This is how I store secrets in my application. I can provide more examples/details if required.
Edit -- This was the final result from Stu's guidance
The project needs 2 AWS packages from Nuget to the project
AWSSDK.Extensions.NETCORE.Setup
AWSSDK.SimpleSystemsManagement
Create 2 parameters in the AWS SSM Parameter Store like:
A plain string named /MyApp/Staging/SigningCertificate and the value is a Base64 encoded .pfx file
An encrypted string /MyApp/Staging/SigningCertificateSecret and the value is the password to the above .pfx file
This is the relevant code:
// In Startup class
private X509Certificate2 GetSigningCertificate()
{
// Configuration is the IConfiguration built by the WebHost in my Program.cs and injected into the Startup constructor
var awsOptions = Configuration.GetAWSOptions();
var ssmClient = awsOptions.CreateServiceClient<IAmazonSimpleSystemsManagement>();
// This is blocking because this is called during synchronous startup operations of the WebHost-- Startup.ConfigureServices()
var res = ssmClient.GetParametersByPathAsync(new Amazon.SimpleSystemsManagement.Model.GetParametersByPathRequest()
{
Path = "/MyApp/Staging",
WithDecryption = true
}).GetAwaiter().GetResult();
// Decode the certificate
var base64EncodedCert = res.Parameters.Find(p => p.Name == "/MyApp/Staging/SigningCertificate")?.Value;
var certificatePassword = res.Parameters.Find(p => p.Name == "/MyApp/Staging/SigningCertificateSecret")?.Value;
byte[] decodedPfxBytes = Convert.FromBase64String(base64EncodedCert);
return new X509Certificate2(decodedPfxBytes, certificatePassword);
}
public void ConfigureServices(IServiceCollection servies)
{
// ...
var identityServerBuilder = services.AddIdentityServer();
var signingCertificate = GetSigningCertificate();
identityServerBuilder.AddSigningCredential(signingCertificate);
//...
}
Last, you may need to set an IAM role and/or policy to your EC2 instance(s) that gives access to these SSM parameters.
Edit: I have been moving my web application SSL termination from my load balancer to my elastic beanstalk instance this week. This requires storing my private key in S3. Details from AWS here: Storing Private Keys Securely in Amazon S3

AWS EC2 keep refusing my private SSH 2 key

Already looked for a solution but nothing seems to be helpfull, I'm doing everything that is meant to be made and my instance keeps returning me the message "Server refused our key".
Here's what I've been doing:
1) Create Instance;
2) Download the .pem key;
3) PuttyGen to transform it in a private .ppk (SSH-2 RSA);
4) Associate an Elastic IP to the Instance;
5) Connect through 22 with the correct auth key generated on the 3rd step;
6) Server asks for username, insert "ubuntu" (using 12.04.1 LTS);
7) Server returns "Server refused our key".
Tried to reboot a hundred times, tried SSH-1 RSA, tried public key instead of private key, tried keys with passphrase, tried everything.
Someone else is experiencing this?
Edit:
Thought it might be a security problem, here are my rules if that helps:
http://i.stack.imgur.com/Y3I2s.png
Just got into the same issue. AWS instance recognize only the key which was specified during the instance creation. All later changes to the key list will not affect already created instance.
Edit: actually, here problem was in incorrect export to .ppk file using Puttygen. See comments below.