Certreq New INF File - iis

I want to creat a Certificate Request with the Certreq.exe Command.
To start a new request I need the mandatory inf file.
There is my problem, I need a inf file which creates, except the normal Variables (CN, O, OU, Provider, length ...) exact the same as if I would create the Cert Crequest over the IIS GUI.
My Question therefor, is there a way to find out what the "standard" key arguments that MS uses are or can I get this from an already create certificate (I know the Cert Details, there arent all infos need)?
Thanks

If you want to get information about existing IIS SSL certificate you can do that by using command
certutil -v -store my
This will show (probably all) information that you need to make inf file for certreq like Subject, SubjectAlternativeName, extensions, exportable flag and CSP name.
Inf file would then look like (taken from here)
[Version]
Signature="$Windows NT$"
[NewRequest]
;Change to your,country code, company name and common name
Subject = "C=US, O=Example Co, CN=something.example.com"
KeySpec = 1
KeyLength = 2048
Exportable = TRUE
MachineKeySet = TRUE
SMIME = False
PrivateKeyArchive = FALSE
UserProtected = FALSE
UseExistingKeySet = FALSE
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
KeyUsage = 0xa0
[EnhancedKeyUsageExtension]
OID=1.3.6.1.5.5.7.3.1 ; this is for Server Authentication / Token Signing
To generate the request you would then run command
certreq -new request.inf request.csr
and send request.csr to a CA to issuing a certificate. CA may use all information in your certificate request but does not have to, i.e. it might change extensions like enhanced key usage and add bot Client Authentication and Server Authentication.

Related

Node TLS Error: ca md too weak, when making request with Axios

I have a problem when I am making a request with Axios in node getting Error: ca md too weak.
I am sending .pfx file and password for the pfx certificate file.
I can easily access API using Postman and sending pfx certificate and password, but making a request with Axios in node js (v. 18.0) I get Error: ca md too weak.
I don't want to downgrade Node version and using: process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; also doesn't help.
Also to connect to the server I have to use VPN and this error pops up even if I haven't turned on VPN.
Is it possible to bypass this check, so I can send a request as I do in the Postman?
Here is a code example:
agent = new https.Agent({
pfx: fs.readFileSync((process.cwd() + "\\src\\sources\\KIISWSClient.pfx")),
passphrase: 'password',
rejectUnauthorized: false,
});
userKiisData = axios.post('https://ws-kiis.hlk.hr/AdeoMembersPublicService.svc/WSPublic/BasicData', {
Username: "myusername",
Role: "role"
}, {
auth: {
username: "user",
password: "mypassword"
},
httpsAgent: agent
}
return userKiisData
Here is the error:
Error: ca md too weak
at configSecureContext (node:internal/tls/secure-context:278:15)
at Object.createSecureContext (node:_tls_common:113:3)
at Object.connect (node:_tls_wrap:1622:48)
at Agent.createConnection (node:https:142:22)
at Agent.createSocket (node:_http_agent:343:26)
at Agent.addRequest (node:_http_agent:294:10)
at new ClientRequest (node:_http_client:311:16)
at Object.request (node:https:352:10)
TLDR: jump to end if you don't care about understanding
rejectUnauthorized directs nodejs to accept (some) invalid certs used by the server instead of aborting the connection, but this error is occurring on your own client cert/chain not that of the server. (That's why it can occur even without the VPN you need for an actual connection.) The "CA_MD_TOO_WEAK" check occurs in modern versions of OpenSSL (1.1.0 up) but can vary depending on how the OpenSSL was built, thus for nodejs it also depends whether your nodejs was built to use its own embedded OpenSSL (usual on Windows) or one already provided on the system where it is installed (usual on Linux).
You can look at the signature algorithms(s) used in your cert chain with openssl if you have (or get) it on this machine or you (may, can, and do) copy the pfx to a machine where ditto. First do
openssl pkcs12 -in yourpfxfile -nokeys >temp0
and look at temp0; it should contain one or more blocks each consisting of a subject= line, an issuer= line, a -----BEGIN CERTIFICATE----- line, several lines of base64, and an -----END CERTIFICATE----- line. (Likely there are also Bag Attributes: lines optionally followed by indented lines; ignore those.)
If there is only one block and it has the same value for subject and issuer, then your error should not have happened, because the cert is selfsigned and OpenSSL should not be checking signature strength on selfsigned cert. Otherwise, do
openssl x509 -in temp0 -noout -text -certopt no_pubkey,no_sigdump,no_extensions
and you should get a few lines of output that includes signatureAlgorithm: x where x is of the form {hash}withRSAEncryption ecdsa_with_{hash} dsa-with-{hash} or dsaWith{hash}. If {hash} is MD5, the signature on your certificate is weak and doesn't provide the security it claims -- although in your situation, if the server accepts it in spite of this weakness, it's probably not your problem.
If the first (leaf) cert is not selfsigned (subject not same as issuer) and its signature algorithm does not use MD5, either
the OpenSSL used by your nodejs is set to a higher than usual 'security level' -- this is not likely for a nodejs that has embedded OpenSSL but more plausible for a system-provided one, especially on security-focussed systems like RedHat 8; or
the problem is with a cert other than the first one (i.e. a CA cert), but this shouldn't occur if your cert(s) are from a properly-run CA because such a CA should never have a higher CA cert signed with a weaker key or signature algorithm than the leaf cert, except the selfsigned root whose signature doesn't matter, and isn't checked so it wouldn't cause your error. However, if you want, break each block other than the first into a separate file, and repeat the openssl x509 procedure above on each except if the last one has subject and issuer the same don't check it because it is the selfsigned root cert.
Anyway, workaround: add to your https-Agent options ciphers: "DEFAULT:#SECLEVEL=0". This should turn off several checks designed to prevent insecure SSL/TLS connections, including the one relevant here; as a result, if you use this code to process data of any importance, it may be at higher risk depending on what the server does.

How do I get client certificates working in CF10 for HTTPS. IIS 7.5

I'm trying to get client certificate verification working with ColdFusion10 http requests. Currently, all I'm getting back is a 403.7. I believe ColdFusion isn't picking up my client certificate. Below is the steps I've currently taken to install and get it set up.
What I've done:
Created a self-signed SSL certificate and installed it to my default website on IIS 7.5.
Installed the SSL cert into CF store.
Tested HTTPS request, everything works fine.
Followed this guide for CA and Client Certs. https://ondrej.wordpress.com/2010/01/24/iis-7-and-client-certificates/
Installed the CA cert to server and client (through MMC). Installed client cert (.pfx) on client.
Tested in local browser, everything is working as it should up to this point.
Created another client cert for CF10 (.cer, .pvk, .pfx).
Added the CA cert into CF store.
Tested, HTTPS rejected with 403.7.
Added CA cert, client .pfx and .cer through MMC under CF10.
Tested, rejected again with 403.7 still.
I've seen that there has been issues with CFHTTP and client certs before, but I haven't found an solution yet.
If anyone can help me with this, it would be great.
EDIT:
After doing what Miguel-F suggested, I skimmed through the log files and found that my CA was imported inside the ColdFusion trust store, but my client certificate wasn't there. I assume this is the reason for the 403.7.
However, I can't add my client certificate(.pfx) to the trust store using certman or keytool through cmd. I created the .pfx by merging my .cer and .pvk together, so I have both of those also.
How can I add my .pfx to the trust store so that Coldfusion picks it up and validates my https?
EDIT #2:
After following this to add my .pfx to the keystore, I can now see my client cert along with my CA being added as 'trusted cert' during the https request.
However, I'm still getting the 403.7 - Forbidden error.
Edit #3:
The handshake in ssl debug info after adding my .pfx (see edit #2) is:
'Is initial handshake: true'
'catalina-exec-3, WRITE: TLSv1 Handshake, length = 181' (Several of these in 1 request)
Edit #4 (More Debug Info):
The last section above where it returns 403 in the debug info looks like HTML content for the error page returned by the server. Just above that however is this:
catalina-exec-3, READ: TLSv1 Application Data, length = 5808
Padded plaintext after DECRYPTION: len = 5808
0000: 48 54 54 50 2F 31 2E 31 20 34 30 33 20 46 6F 72 HTTP/1.1 403 For (Example of the HTML error content)
Edit #5:
I can see my client cert being added as a trusted cert during the start of the request... It's just not using it.
adding as trusted cert:
Subject: CN=George CF10
Issuer: CN=MyPersonalCA
Algorithm: RSA; Serial number: 0x-431b7d9911f9856cb0adf94d50bb1479
Valid from Fri Apr 01 00:00:00 BST 2016 until Wed Apr 01 00:00:00 BST 2020
Edit #6:
After adding setClientCert(path to my .pfx) and setClientCertPassword(client cert password) to my https request, I'm seeing this error:
Error while trying to get the SSL client certificate:
java.security.UnrecoverableKeyException: Could not decrypt key: Could not decode key from BER. (Invalid encoding: expected tag not there.).
Check that the certificate path and password are correct and the file is in PKCS#12 format.
Too long for comment
Are you sure that you added the certificate to the correct JVM keystore? If you have upgraded Java on your ColdFusion server then it may not be in the default location. The ColdFusion administrator system information page will tell you the path in use under the "Java Home" label.
In order to turn on debugging information, add these lines to your ColdFusion server's jvm.config file located under this directory C:\ColdFusion10\cfusion\bin (by default) and restart the ColdFusion service:
-Djavax.net.ssl=debug
-Djavax.net.debug=all
This should add some more information to the coldfusion-out.log log file on your server. Post that information back here into your question for further analysis.
Adding the certificate to the Windows server using MMC is not needed and does not help your cfhttp calls from ColdFusion. It uses the Java keystore.
Response for EDIT 1 and 2
Follow the steps from this other answer on how to convert a .pfx file to the keystore.
Response for EDIT 3, 4 and 5
If you still have the ssl debug switch turned on you should see the handshake info in the log file. What does it show now that you have the certificate installed?
Have you tried using the clientCert and clientCertPassword attributes of the cfhttp tag? Note that it will require the full path to a PKCS12 format file that contains the client certificate for the request. See the docs here.
Response for EDIT 6
Take a look at this page - CFHTTP and client certificates regarding the error message you are getting: Could not decode key from BER. Excerpt from that page:
The client certificate appeared to be a normal client certificate with private key in PKCS#12 format, but from a different certificate chain then the server format. So I first had the client double-check that the chain was correctly installed on the server. Unfortunately it wasn’t that easy. I will spare you the details of what I tried, but in the end it turned out to be that the certificate was incorrectly encoded. These are the actual conversion steps I took to convert the certificate to a working state:
import the certificate in the Windows Certificate store through the MMC;
export the certificate with private key, whole chain and without strong encryption in PFX formet;
convert the PFX encoded certificate to PEM using OpenSSL:openssl pkcs12 -in raw.pfx -out intermediate.pem -nodes
re-order the certificates inside the PEM file to the following order: > - Identity certificate
Intermediate certificate
Root certificate
Private Key
convert the PEM encoded certificate to PKCS#12 using OpenSSL:openssl pkcs12 -export -out final.pkcs -in final.pem
It is probably possible to skip / merge a few of these steps (you probably just need to convert to PEM, reorder and convert back), but I really didn’t have time to explore that, I just know that this worked for me.
Solved by following this link.
I used the new .pkcs format file inside setClientCert of the HTTP request and it is now working.
import the certificate in the Windows Certificate store through the MMC;
export the certificate with private key, whole chain and without strong encryption in PFX formet;
convert the PFX encoded certificate to PEM using OpenSSL:
openssl pkcs12 -in raw.pfx -out intermediate.pem -nodes
re-order the certificates inside the PEM file to the following order:
Identity certificate
Intermediate certificate
Root certificate
Private Key
convert the PEM encoded certificate to PKCS#12 using OpenSSL: openssl pkcs12 -export -out final.pkcs -in final.pem
It is probably possible to skip / merge a few of these steps (you probably just need to convert to PEM, reorder and convert back), but I really didn’t have time to explore that, I just know that this worked for me.

Listing the certificate chain provided by a server on SSL_connect

I'm new to security so some of the terms might be used incorrectly:
When I create a socket connection using SSL_connect, the server should send back the entire certificate chain so that the authenticity of the server can be verified.
For this to happen, the server needs to be configured accordingly.
If the server doesn't send back the entire certificate chain and the intermediate certificate isn't in the client certificate store, the authenticity can't be verified. This results in the behavior experienced here in which FireFox regards a website as unsafe.
I've also read that some browsers are able to attain the intermediate certificate automatically. However, OpenSSL doesn't behavior like this, at least by default.
I've also been told that some (maybe all) intermediate certificates have been installed in Windows certificate stores since some Windows update was rolled out a few years ago.
I would like to view the certificates returned by the server to verify that I'm getting back the entire certificate chain. Here's what I've tried:
I'm using SSLv3_method.
SSL_CTX_set_verify is set using SSL_VERIFY_NONE.
After SSL_connect I use SSL_get_peer_cert_chain to get access to the certificate chain.
Consider:
STACK_OF(X509)* certificateChain = SSL_get_peer_cert_chain(ssl);
while (char* stackCertificate = sk_pop(certificateChain))
{
X509* certificate = (X509*)stackCertificate;
}
Is this the correct way to get the certificate chain? Is my understanding of the situation correct? Is there perhaps a better way to do this?
Thank you for your time and contribution.
The following code snippet is based off code in s_client:
SSL* ssl = ...;
STACK_OF(X509)* certCollection = SSL_get_peer_cert_chain(ssl);
for (size_t i = 0; i < sk_X509_num(certCollection); i++)
{
X509* cert = sk_X509_value(certCollection, i);
...
}
As far as I understand, an SSL session must have been created otherwise SSL_get_peer_cert_chain will return null. Additionally I haven't found any evidence to contradict the list I noted in my question.
Perhaps an easier alternative would be to use the command line tool (downloaded from here):
openssl s_client -connect {server}:{port} -ssl3

Node.js Using SSL Wildcard Breaks on Mobile

I've got a Node.js server that runs on sub.domain.com, using SSL. It's been working perfectly for months on desktop browsers, but I just noticed that it doesn't work on mobile browsers.
I've done a bit of research and there's a lot of people suggesting that there is something wrong with my certificate chain. I've changed my code to look like there's but still no luck.
Here's my code:
var httpsOptions = {
ca: [fs.readFileSync("certrequest.csr")],
key: fs.readFileSync("privatekey.pem"),
cert: fs.readFileSync("certificate.pem")
};
var app = http.createServer(httpsOptions, function(req, res) {
log.cnsl.write("HTTP Request received from " + req.connection.remoteAddress);
//Do stuff
});
I'm running this command to view some debug information (my server runs on port 5673):
openssl s_client -connect sub.domain.com:5673 -showcerts | grep "^ "
Below is the important part of that output
depth=0 O = *.domain.com, OU = Domain Control Validated, CN = *.domain.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 O = *.domain.com, OU = Domain Control Validated, CN = *.domain.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 O = *.domain.com, OU = Domain Control Validated, CN = *domain.com
verify error:num=21:unable to verify the first certificate
verify return:1
It sounds rather weird that you've put your certificate request file "certrequest.csr" as the CA.
The CA field should contain the certificate chain from your personal certificate to th root certificate. In my configuration, it contains 2 entries. One as the root certificate itself and the second one as the intermediate one because my issuer offers multiple levels of certifications.
By the way, your certification company most certainly provides you with such informations in their FAQ for example.
As an example, here is an extract of my configuration :
var httpsOptions = {
key:fs.readFileSync('/etc/ssl/private/ssl-main.key'),
cert:fs.readFileSync('/etc/ssl/private/ssl-main.crt'),
ca:[fs.readFileSync('/etc/ssl/private/ca.pem'),
fs.readFileSync('/etc/ssl/private/sub.class2.server.ca.pem')]
};
Anyway, this does not explain why It works for non mobile browsers. My only guess is that they my embed themselves a part of the chain while the mobiles wont't for disk space reasons.
Hope this helps.

How do I add a CRL address to a self-signed CA certificate?

This is an extension question to:
how-do-i-create-a-self-signed-certificate-for-code-signing-on-windows
To take this further, if I have created a CA cert, and have create a set of SPC certs, how do I go about creating revocation lists and distributing them? (note: I have no knowledge about how CRLs work, how they are distributed etc) If I were to GUESS how it all worked, I would hope that the CA cert defined some HTTP address where CRLs could be downloaded, and windows would contact that address the first time a cert chain was queried, and every time the current CRL expires... Then all I would have to do is create a signed web address that distributes certificate serial numbers...?
EDIT: SELF ANSWERED
For anyone else who is interested, Bouncy Castle is a Java+C# library providing a massive set of PKI Crypto APIs, including certificate generation.
Their sample code (in their downloads) demonstrates how to generate a chained set of CA, Intermediate, and 'Personal' certificates.
What it doesnt show, is how to correctly assign an HTTP based CRL - you can do so with this code:
GeneralName gn = new GeneralName(new DerIA5String("http://localhost/revocationlist.crl"), 6);
GeneralNames gns = new GeneralNames(gn);
DistributionPointName dpn = new DistributionPointName(gns);
DistributionPoint distp = new DistributionPoint(dpn, null, null);
DerSequence seq = new DerSequence(distp);
v3CertGen.AddExtension(X509Extensions.CrlDistributionPoints, false, seq);
As of crypto-147 the supplied code has changed to
GeneralName gn = new GeneralName(GeneralName.uniformResourceIdentifier, new DERIA5String(crlUrl));
GeneralNames gns = new GeneralNames(gn);
DistributionPointName dpn = new DistributionPointName(gns);
DistributionPoint distp = new DistributionPoint(dpn, null, null);
DERSequence seq = new DERSequence(distp);
certGen.addExtension(Extension.cRLDistributionPoints, false, seq);
Suppose you have a CA certificate and some set of certificates, signed by that CA certificate. Then you can create a CRL, which would (potentially) contain IDs of revoked certificates, which were previously signed using CA certificate. Indeed you add the URL of the CRL to the CA certificate itself via the corresponding certificate extension (CRLDistributionPoint).
As you have not specified, what tools or libraries you use to generate the certificates, I can't say how the extension can be added.
PS: I'd recommend that you learn about technology before trying to use it. Especially when it comes to implementing security. Otherwise you will end up in situation, worse than the one of Comodo, whose sub-CAs have issued fake certs for google, yahoo and more just recently.

Resources