Closed bjorkqvist closed 4 years ago
I am experiencing the same issue, did you find out how to fix it?
I have tried to find the problem but can not do and the help from GetSwish AB is bad.
They like me to get throw a supplier of the integration instead do it my self.
But i have figured it out with there help that they only see one certificate of the 3 that they should, more then that i have not got help with.
Tack för svaret! Jag ska försöka ändra HTTP clienten och se om det gör någon skillnad. Fungerar det bra med prod certificates?
Det är med production certifikaten GetSwish AB säger att dem ser bara ett certifikat i requesten jag gör.
Men antar det är samma fel i test miljön.
Precis, så är det.
Hittar du lösning så skriv gärna här eller gör pull request och jag gör självklart samma sak.
Vet du när slutade fungera ung.?
I replaced the http client library for HttpClient, i also ensured that tls1.1 is used and I am skipping CA validation with the exact same results. This is very strange, I do not encounter any issues using curl. Interesting problem.
This is my implementation
public HttpClient CreateRestClient()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;
// Create up a client certificate collection and import the certificate to it
X509Certificate2Collection clientCertificates = new X509Certificate2Collection();
clientCertificates.Import(_certDataBytes, _certificatePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
HttpClientHandler handler = new HttpClientHandler
{
SslProtocols = SslProtocols.Tls11,
ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => true
};
foreach (X509Certificate2 x509 in clientCertificates)
{
handler.ClientCertificates.Add(x509);
}
HttpClient client = new HttpClient(handler);
return client;
}
Yea, i have spent 7-10 hours trying to find a solution without any good result.
I contacted Swish and they gave me a sort of alike response. They only see 2 of the 3 certificates. This makes no sense as the 3 certificates in the collection are appended. Also, I bypass Server SSL validation and I added all certificates to my keychain store and trusted them all.
I do believe there is something on their side but they cannot come back with any useful feedback.
Intresting and i have the same feeling but they dont want to support small developers....
They have forwarded the issue to their developers, let's see if this helps.
Nothing new @jfalameda ?
Unfortunately no. I haven't got any answer from Swish yet.
@RickardPettersson Any progress from your side?
I still haven't got any response from Swish.
I did some more tests and let GetSwish AB tech support check and they asked some question but still didnt give me a good answer.
I have not got good time for this after the small more tests.
I got answer today from GetSwish AB tech support that the developers now working on getting some code examples to give me so maybe soon we can get this to work..
Hi, Have you heard anything from Swish? They haven't come back to me yet.
No, i have asked the tech support like 4 times after 1 April whats happening and they can not say more then they waiting for the developers to do there work. :) I guessing they find it not good as we have done :)
But i have figured it out with there help that they only see one certificate of the 3 that they should, more then that i have not got help with.
I contacted Swish and they gave me a sort of alike response. They only see 2 of the 3 certificates. This makes no sense as the 3 certificates in the collection are appended. Also, I bypass Server SSL validation and I added all certificates to my keychain store and trusted them all.
@jfalameda @RickardPettersson I've been looking into this as well. I can call Swish test API with curl (version 7.70 on Win10, 7.55 did not work):
curl -s -S -i --cert Swish_Merchant_TestCertificate_1234679304.p12:swish --cert-type p12 --tlsv1.2 --header "Content-Type:application/json" https://mss.cpc.getswish.net/swish-cpcapi/api/v1/paymentrequests --data-binary @jsondata.json
However when I try to use .net core built-in HttpClient I get the same error as you: "The message received was unexpected or badly formatted."
I then moved on to comparing the calls made from curl and from .net in Wireshark and I found one difference that caught my eye (even though I was just guessing since this is not really my field of expertise).
Call from curl:
Call from .net core:
The difference is that when a "Certificate"-call/request is made, curl supplies all three certificates from the certificate file (Swish_Merchant_TestCertificate_1234679304.p12) whereas .net core just supplies one.
So I went ahead and looked at the source code for the HttpClient and found that it called CertificateHelper.GetEligibleClientCertificate(ClientCertificates) to get one valid client certificate.
I'm not sure if this is why is the actual reason to why only one certificate is sent from .net core or not, but it could be.
When I was looking in the source code for HttpClient I also saw that if you set handler.ClientCertificateOptions = ClientCertificateOption.Automatic then the certificates are loaded from the "MY" certificate store (which is equal to "Personal certificate" for "Current User" in Windows). I went ahead and imported the certificate and tried again but with no luck (got another error message). But after changing back to handler.ClientCertificateOptions = ClientCertificateOption.Manual it now worked. I looked at the call in Wireshark and now there were three certificates sent:
From the "Personal certificates" I could delete the one named 1234679304 and just keep to two CA certificates:
To sum it up: It looks as if .net core needs the CA certificates to be present in the certificate store. If they just are in the certificate file used as "Client certificate" it wont work.
I will do some additional digging to see if this is the way it is in .net core or if there is some other way to make it behave like curl (include the CA certificates).
I contacted Swish and they gave me a sort of alike response. They only see 2 of the 3 certificates. This makes no sense as the 3 certificates in the collection are appended. Also, I bypass Server SSL validation and I added all certificates to my keychain store and trusted them all.
I do believe there is something on their side but they cannot come back with any useful feedback.
@jfalameda I just found another issue here on Github with the same problem that might interest you: https://github.com/dotnet/runtime/issues/29653#issuecomment-495667695
(Also, they had done the exact same network sniffing I spent some hours on doing myself. Typical ;-) )
This is very intresting @monobjorn Becouse thats can mean that .Net Standard that the whole library working on has the same problem as the .Net Core HttpClient.....
So if we moving the whole code to a .Net Framework project... then it maybe working..
Need to test, comming back with what i finding.
Also seeems very wrong of .Net Core to required to have the certificates installed.
I just posted a question on SO regarding whether or not .net core (HttpClient) requires the certificates to be installed or not: Can a .p12 file with CA certificates be used in C# without importing them to certificate store
I tested convert all projects to .Net Framework 4.8 and got same problem to test environemnt and tested convert to 4.6.1 to have a old version also same result.
But still go on your idea becouse can be different problems.
I got it to work with the answer @monobjorn got on https://stackoverflow.com/questions/61677247/can-a-p12-file-with-ca-certificates-be-used-in-c-sharp-without-importing-them-t/61681840#61681840
I going to implement the certificate handle code in my library and push up the code, work in progress to get all code over but i got a payment in production to work more tests and result comming as soon as i got all code over.
Can not say if its going to be today or tomorrow but its comming.
Thanks @monobjorn and everyone else trying so hard to get it to work.
Now i have pushed the latest code working for me on both my computers without installing the certificate both with the test enviroment that are in the code but even with my production account i got all to work.
I have some code left to update and document about QR Codes but the part of make payment, check payment status, make refund and check refund status now working.
Hope this help people again!
And to clarify i got the console test application in the github repository to work not tested more then that but guesing it going to work overall now.
I letting this be open and i like to get information from you all that this working?
Hi,
I just downloaded your latest code and tested the console app. I get the same SSL error as you guys. I also tried to put the CA cert in Personal and Trusted root certificates without success.
Any other suggestions?
I read about that they updated the test certificate for some days ago or something, i going to update but if you like to test before that download latest simulator package from swish site
Yeah I've done that since I was using my own code. Then I came across this issue and started Googling and found your code. I've also tested that certificate with you code. Same result...
@PJzyber Did you add it to the "current user" certificate store? Adding it to the "local machine" certificate store wont help.
From the "Personal certificates" I could delete the one named 1234679304 and just keep to two CA certificates:
In order to get all to work you need the latest test certificate from GetSwish AB and i have now pushed it to the repository so should be good to pull the latest code and get the console test app to work.
I know closing this issue down becouse the problem this was created for is fixed. If someone else get problems create a new issue please.
Jag får ssl-problem vid anrop till client.MakePaymentRequest från console-appen. Några idéer om vad som kan vara problemet?
Stacktrace: "System.Net.WebException: The SSL connection could not be established, see inner exception. Authentication failed, see inner exception. ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception. ---> System.ComponentModel.Win32Exception: Det mottagna meddelandet var oväntat eller felaktigt formaterat\r\n --- End of inner exception stack trace ---\r\n at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)\r\n at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)\r\n at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)\r\n at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)\r\n at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)\r\n at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Net.Security.SslState.ThrowIfExceptional()\r\n at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)\r\n at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)\r\n at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)\r\n at System.Net.Security.SslStream.<>c.b__47_1(IAsyncResult iar)\r\n at System.Threading.Tasks.TaskFactory
1.FromAsyncCoreLogic(IAsyncResult iar, Func
2 endFunction, Action1 endAction, Task
1 promise, Boolean requiresSynchronization)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)\r\n --- End of inner exception stack trace ---\r\n at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)\r\n at System.Threading.Tasks.ValueTask1.get_Result()\r\n at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Threading.Tasks.ValueTask
1.get_Result()\r\n at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask1 creationTask)\r\n at System.Threading.Tasks.ValueTask
1.get_Result()\r\n at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)\r\n at System.Net.HttpWebRequest.SendRequest()\r\n at System.Net.HttpWebRequest.GetResponse()\r\n --- End of inner exception stack trace ---\r\n at System.Net.HttpWebRequest.GetResponse()\r\n at RestSharp.Http.GetRawResponse(HttpWebRequest request)\r\n at RestSharp.Http.GetResponse(HttpWebRequest request)"