The certificate authority is invalid or incorrect - rest

Have called many restful services from asp before - but this one has me stumped.
First my func looks like
Set objHTTP = Server.CreateObject("MSXML2.ServerXMLHTTP")
with objHTTP
.open "post", x_posturl, False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.send x_xmlstr
end with
and the error returned is
msxml3.dll error '80072f0d' The certificate authority is invalid or
incorrect
so, googled a bit and suggestion was to add line
.setOption 2, 13056
this gives error
msxml3.dll error '80072f0c' A certificate is required to complete
client authentication
I then contacted service supplier and they suggested
Click on the certificate error next to the address bar, view the
certificate, select Details, select Copy to File, and download it to a
file. Install that into your trusted certificates on your server to
stop the error appearing when trying to submit data.
So, tried that using instructions here - but still no joy, any help appreciated

It seems like the server located at x_posturl has a certificate that is misconfigured, or that your client computer doesn't contain/recognize the certificate's root authority (most likely). There are a few options to fix:
Have them fix their certificate if it's misconfigured.
If their certificate is valid, but with a root authority your machine doesn't recognize, then you need to install the root authority certificate locally.
Instruct MSXML2.ServerXMLHTTP to ignore certificate errors, which appears to be answered here: VBA ServerXMLHTTP https request with self signed certificate
Change x_posturl to start with http:// instead of https://— if it's supported by the provider. Would not recommend this in a production scenario though.
Can you share specifically what x_posturl is? We should be able to debug by looking at the SSL handshake.

I was able to find the solution by passing in a param.
objHTTP.SetOption 2, objHTTP.GetOption(2)
Dim objHTTP
Set objHTTP = Server.CreateObject("MSXML2.ServerXMLHTTP")
objHTTP.SetOption 2, objHTTP.GetOption(2)
objHTTP.Open "post", x_posturl, False
objHTTP.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
objHTTP.Send x_xmlstr

Related

Is there a way to check if a certificate is client cert or server cert?

I received a new keystore .jks file for ssl connection to replace an old, but working, .jks keystore file, but I got "unexpected handshake message: serve_hello" error. I was told to make sure the keystore contains a client cert, so I used keytool to export its cert to a pem file, then use openssl to check the purpose. The result shows
Certificate purposes:
SSL client : No
SSL client CA : No
SSL server : Yes
SSL server CA : No
...
However when I applied the same process to check the old but working jks file I got the same result. Wonder if this is the right way to verify the certificate? And how to troubleshooting this handshake error with the new jks file?
Thanks!
The extended key usage extension contains OIDs which define the purpose:
id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
-- TLS WWW server authentication
-- Key usage bits that may be consistent: digitalSignature,
-- keyEncipherment or keyAgreement
id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
-- TLS WWW client authentication
-- Key usage bits that may be consistent: digitalSignature
-- and/or keyAgreement
https://datatracker.ietf.org/doc/html/rfc5280 Page 44
See: https://oidref.com/1.3.6.1.5.5.7.3.1 and https://oidref.com/1.3.6.1.5.5.7.3.2
When opening a certificate on Windows you can see the extension here:

Dart Add SSL certificate and key to HttpClient

I'm trying to secure a REST API using TLS/SSL, to do so I needed to update my client to use the public key and certificate.
The client is written in dart and here's how I implemented the SecurityContext :
SecurityContext clientContext = SecurityContext.defaultContext;
var certificate = (await rootBundle.load("assets/ssl/coastr.crt")).buffer.asInt8List();
print(certificate.toString());
clientContext.setTrustedCertificatesBytes(certificate);
/*var authorities = (await rootBundle.load('assets/ssl/coastr.ca-bundle')).buffer.asUint8List();
print(authorities.toString());
clientContext.setClientAuthoritiesBytes(authorities);*/
var key = (await rootBundle.load("assets/ssl/coastr_public.key")).buffer.asInt8List();
print(key.toString());
clientContext.usePrivateKeyBytes(key);
HttpClient client = HttpClient(context: clientContext);
HttpClientRequest request = await client.getUrl(Uri.parse(url));
HttpClientResponse response = await request.close();
The certificate (.crt file) is added without issue to the clientContext but adding the key to it returns me this error :
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception:
TlsException: Failure in usePrivateKeyBytes (OS Error:
BAD_PKCS12_DATA(pkcs8_x509.c:606)
passed a null parameter(ssl_privkey.cc:375), errno = 0)
The files I'm using are :
coastr.crt with this as a header : -----BEGIN CERTIFICATE-----
coastr_public.key with header : -----BEGIN PUBLIC KEY-----
I have no idea if I'm providing the wrong files to the client or if the error comes from elsewhere.
The files where generated using openssl.
Thank you for your help.
In general, you shouldn't have to add anything to the client to allow it to connect to a correctly configured HTTPS server. Hopefully, the server has a signed server side certificate. If that certificate is signed by a reputable CA, the client should automatically trust it. If it is signed by an in house CA, or self signed, you need to do some work. You need to provide the client with the signing certificate. In the former case that would be the root CA's certificate. In the latter case, supplying the server's certificate may work, though it's probably easier to disable the client check altogether.
The signing certificate is likely to be in CRT form as you've found. And you need to supply that exactly as you are doing. There's no need to supply any public keys as the are distributed in the certificates sent with the server hello.
Unless you want to use a client side certificate, there's no need to supply a private key, so you can skip the step that is failing. And supplying a public key to it is definitely not going to work, anyway.

OpenXPKI with JSCEP to request CRL

I am trying to obtain the CRL from an OpenXPKI server (the default configuration is used). Requesting and polling of a certificate is possible.
On the OpenXPKI server, I revoked some certificate, created the CRL and published the list. To obtain the CRL I tried different approaches.
First approach:
X509CRL crl = client.getRevocationList(jscepCertificate, jscepKeyPair.getPrivate(),
certificate.getIssuerX500Principal(), certificate.getSerialNumber());
Second approach:
X509CRL crl = client.getRevocationList(jscepCertificate, jscepKeyPair.getPrivate(),
crlIssuer, crlSerialNumber);
On the server my CRL has the following information:
CRL Serial: 511
CRL Issuer: CN=CA ONE,OU=Test CA,DC=OpenXPKI,DC=ORG
Items: 25
When I try the above code examples (and also some other) I get following error on the CRL requester:
org.jscep.transaction.OperationFailureException: Operation failed due
to badCertId
And on the OpenXPKI server I get the following error:
openxpki.application.ERROR:12156 [OpenXPKI::Service::SCEP::Command::PKIOperation
(/usr/lib/x86_64-linux-gnu/perl5/5.20/OpenXPKI/Service/SCEP/Command/PKIOperation.pm:255);
scep-server-1()#f68c] SCEP getcrl - no issuer found for serial 511 and
issuer DC=ORG,DC=OpenXPKI,OU=Test CA,CN=CA ONE
Always no issuer found for serial XXX and issuer YYY (XXX and YYY depend on the send information of the CRL request).
Please, could anyone help me or give me some advice? - Thanks in advance!
I solved the problem with the help of the JSCEP and OpenXPKI communities. The problem is that the DN of the issuer is reversed, this means e.g. CN=CA,OU=Test CA,DC=OpenXPKI,DC=ORG is changed to DC=ORG,DC=OpenXPKI,OU=Test CA,CN=CA ONE and the getCRL from the OpenXPKI has no entry for the reversed issuer.
An easy fix is to reverse the issuer for the getCRL request (check OpenXPKI fix) by changing the code from the get_getcrl_issuer_serial.pm file. Add the following code in line 107:
$issuer = join ",", reverse split (/,/, $issuer);
A solution for the future would be to make the getCRL logic requester independent and to order the issuer on the request.

Bearer was not authenticated: Signature validation failed

I am using Identity Server 4 to protect my APIs (Implicit Flow Mode) which are accessed by angular application. Every thing is working fine, however at specific period the access token suddenly became invalid even before its expiry.
Configuration:
Here is the Identity Server Startup file:
var identityBuilder = services.AddIdentityServer().AddInMemoryStores().SetTemporarySigningCredential();
identityBuilder.AddInMemoryScopes(identitySrvConfig.GetScopes());
identityBuilder.AddInMemoryClients(identitySrvConfig.GetClients());
Protecting the APIs:
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = identityOptions.Authority,
ScopeName = "userProfile_api",
RequireHttpsMetadata = false
});
Investigation:
The issue was the bearer was not authenticated
Bearer was not authenticated. Failure message: IDX10501: Signature validation failed. Unable to match 'kid': 'e4f3534e5afd70ba74c245fe2e39c724', token
After some investigation, it appears that identity server is generating a new key which was causing the signature validation to fail.
In the log, I can see when the two warning events at end happening, then I see "Repository contains no viable default key" and "a new key should be added to the ring"
Questions
Why would there no be a key at anytime when the key lifetime is almost 3 months even I am using temporary signing (SetTemporarySigningCredential) and I am not restarting the server?
Creating key {a2fffa4a-345b-4f3b-bae7-454d567a1aee} with creation date 2017-03-03 19:15:28Z, activation date 2017-03-03 19:15:28Z, and expiration date 2017-06-01 19:15:28Z.
How can I solve this issue?
Creating a self signing certificate and removing the temporary signing on identity server fixed the issue.
var signingCertificate = new X509Certificate2("ReplaceByCertificatePath, "ReplaceByPasswordCertificate");
var identityBuilder = services.AddIdentityServer().AddInMemoryStores().SetSigningCredential(signingCertificate);
identityBuilder.AddInMemoryScopes(IdentitySrvConfig.GetScopes());
identityBuilder.AddInMemoryClients(IdentitySrvConfig.GetClients());

How to enable certificate pinning with OkHttp

How can I enable certificate pinning using OkHttp for my Android / Java application?
The OkHttp documentation gives us a clear way to do this complete with sample code. In case it goes away, here it is pasted in below:
1. Add a broken CertificatePinner and make a request.
Any request will do, even if it doesn't exist. You can do this in your Android application, or just create a dummy Java application and run this as well.
For example, to pin https://publicobject.com, start with a broken
configuration:
String hostname = "publicobject.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
OkHttpClient client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
Request request = new Request.Builder()
.url("https://" + hostname)
.build();
client.newCall(request).execute();
As expected, this fails with a certificate pinning exception:
javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!
Peer certificate chain:
sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=: CN=publicobject.com, OU=PositiveSSL
sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=: CN=COMODO RSA Secure Server CA
sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=: CN=COMODO RSA Certification Authority
sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=: CN=AddTrust External CA Root
Pinned certificates for publicobject.com:
sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
at okhttp3.CertificatePinner.check(CertificatePinner.java)
at okhttp3.Connection.upgradeToTls(Connection.java)
at okhttp3.Connection.connect(Connection.java)
at okhttp3.Connection.connectAndSetOwner(Connection.java)
2. Configure your OkHttp Client Correctly:
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
.add("publicobject.com", "sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=")
.add("publicobject.com", "sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=")
.add("publicobject.com", "sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=")
.build();
That's all there is to it!
This method will give you all your certificates in the entire chain. This is advantageous since it's safer as only one certificate in the chain has to match for the request to succeed. It's likely at some point in the future, your certificates will be updated, but as long as the entire chain isn't updated, your application shouldn't break.