WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   Swish TLS certificate och .Net / C# kod (https://www.wn.se/forum/showthread.php?t=1066196)

RickardP 2016-01-14 12:31

Swish TLS certificate och .Net / C# kod
 
Hej, är det någon mer än mig som börjat kollat på att implementera Swish API för e-handel i sina webshopar eller siter?

Jag utvecklar min webshop i .Net och C# och får det inte att fungera och funderar på om någon fått det att fungera med ASP.NET MVC eller C# eller något annat .Net språk.

Egentligen tror jag mitt problem ligger i själva certifikat hanteringen i windows så någon som har erfarenhet av det får gärna höra av sig.

Försöker kolla detta forum men maila gärna till rickardnp [ at ] gmail.com eller privatmeddelande här så får jag mail om det.

Nerix 2016-01-14 16:58

Är de inte bättre att problemet löses öppet så att fler kan ta del av din lösning?

Skicka bara med ditt cert när du ställer en fråga till Swish API så är du klar sedan. Du behöver inte lägga till certifikatet i Windows lista bland root-cert.

RickardP 2016-01-15 14:50

Jag kan tänka mig ha svaret öppet om jag får ett svar och jag vet hur jag vill göra dem kodexempel jag hittar på nätet vill inte riktigt som jag vill.

naak2803 2016-01-20 12:14

sitter också med samma problem, är det någon som har lyckats komma runt detta?

Nerix 2016-01-20 19:35

Fungerade inte mitt förslag? De fungerar bra här iaf.

RickardP 2016-01-20 20:21

Nerix: problemet var ju hur man skickade med certifikatet men det är löst nu har jag kommit så långt att jag får ok på certifikatet men får internal server error som svar från dem så inväntar svar från swish och se varför.

Nerix 2016-01-20 20:48

Citat:

Ursprungligen postat av RickardP (Inlägg 20515477)
Nerix: problemet var ju hur man skickade med certifikatet men det är löst nu har jag kommit så långt att jag får ok på certifikatet men får internal server error som svar från dem så inväntar svar från swish och se varför.

Du skrev att du hade problem med certifikat i Windows, inte att du hade problem att skicka med de. Du har dessutom inte postat någon kod eller felmeddelande så förstår inte riktigt vad du förväntar dig för hjälp. Slutligen så är det en användare till här i tråden som har samma problem som dig så varför postar du inte din kod?

RickardP 2016-01-20 21:23

Citat:

Ursprungligen postat av Nerix (Inlägg 20515479)
Du skrev att du hade problem med certifikat i Windows, inte att du hade problem att skicka med de. Du har dessutom inte postat någon kod eller felmeddelande så förstår inte riktigt vad du förväntar dig för hjälp. Slutligen så är det en användare till här i tråden som har samma problem som dig så varför postar du inte din kod?

Därför jag och han pratar med privata meddelanden.

Jag har kommit så långt att den authentiserar sig men sen får jag internal server error som svar.

Min kod ser just nu ut så här:http://pastebin.com/H3acarx4

Nerix 2016-01-20 21:25

Citat:

Ursprungligen postat av RickardP (Inlägg 20515477)
Nerix: problemet var ju hur man skickade med certifikatet men det är löst nu har jag kommit så långt att jag får ok på certifikatet men får internal server error som svar från dem så inväntar svar från swish och se varför.

Citat:

Ursprungligen postat av RickardP (Inlägg 20515480)
Därför jag och han pratar med privata meddelanden.

Varför?!?!?!

RickardP 2016-01-21 08:05

Citat:

Ursprungligen postat av Nerix (Inlägg 20515481)
Varför?!?!?!

Han skrev till mig och jag svarade därav liten konversation privat.

x264 2016-01-22 11:19

Citat:

Ursprungligen postat av RickardP (Inlägg 20515485)
Han skrev till mig och jag svarade därav liten konversation privat.

Tror Nerix försöker säga att det är bättre ni tar det här så kan andra eventuellt i framtiden få hjälp om de fastnar vid samma ställe :)

RickardP 2016-01-22 14:51

Nu har jag kommit så långt att jag inte får error tillbaka utan får HTTP 200 utan någon respons contents. Senaste koden hittas på: https://gist.github.com/RickardPette...402d2d59552732

Nu är nästa problem callback urlen måste vara HTTPS av någon anledning... jag som alldrig satt up någon site med SSL måste ta och lära mig det.

Nerix 2016-01-22 18:00

Citat:

Ursprungligen postat av x264 (Inlägg 20515499)
Tror Nerix försöker säga att det är bättre ni tar det här så kan andra eventuellt i framtiden få hjälp om de fastnar vid samma ställe :)

Exakt! Halva Sveriges ehandel-utvecklare lär just sitta med samma problem inom nån månad.

RickardP 2016-01-22 18:19

Citat:

Ursprungligen postat av Nerix (Inlägg 20515507)
Exakt! Halva Sveriges ehandel-utvecklare lär just sitta med samma problem inom nån månad.

Japp så om någon har rekommendation vilken av alla cert man ska köpa endast för att få det att fungera jag bryr mig inte så mycket om säkerheten osv vill få https att fungera så jag kan gå vidare :)

Nerix 2016-01-22 19:30

Citat:

Ursprungligen postat av RickardP (Inlägg 20515508)
Japp så om någon har rekommendation vilken av alla cert man ska köpa endast för att få det att fungera jag bryr mig inte så mycket om säkerheten osv vill få https att fungera så jag kan gå vidare :)

Här finns gratis cert https://letsencrypt.org/ något som diskuteras här http://www.wn.se/showthread.php?t=1066017

SEOutanHatt 2016-02-10 15:11

Sitter och sliter mitt hår lite över detta. Får inte till det utan får endast ett felmeddelande "Begäran avbröts: Det gick inte att skapa en säker SSL/TLS-kanal." hur jag än försöker.

Använder koden som RickardP lagt upp på github. Har importerat både root och client certifikaten på datorn.

Kod:

                string URL = "https://mss.swicpc.bankgirot.se/swish-cpcapi/api/v1/paymentrequests/";

                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11; // har provat med ssl3, tls, tls11, tls12

                Uri requestURI = new Uri(URL);

                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestURI);

                req.ContentType = "application/json; charset=UTF-8";
                req.Method = "POST";
                req.ProtocolVersion = HttpVersion.Version10;

                string path = @"Swish Merchant Test Certificate 1231181189.p12"; // ja, filen ligger på rätt plats och hittas.

                X509Certificate cert = new X509Certificate2(path, "swish", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

                req.ClientCertificates.Add(cert);

                Stream requestStream = req.GetRequestStream();


Det är alltså direkt vid req.GetRequestStream() som det tar stopp. Någon som har något tips?

lazat 2016-02-13 23:07

kolla brandväggen! TCP dump av trafiken för om anropet skickas. Är koden i c# så finns det också risk för att certifikaten är ouppdaterade eller liknande. Testa callback URL på ssllabs för att se att allting ser bra ut. Se om det fungerar utan SSL. Kolla om användaren som din application i webbservern körs som har rätt till path.

SEOutanHatt 2016-02-14 02:04

Tack för tipsen. Tyvärr hjälpte de inte :(

Testat både på webbservern och lokalt (helt utan brandvägg).

Kört med Fiddler för att se så att anropet går iväg.

Callback url är ju inte inblandat ännu - jag måste upprätta en anslutning först innan jag kan skicka dem vilken callbackurl jag vill använda.

Alla filrättigheter är som de ska. Har debuggat efter att req.ClientCertificates.Add(cert); och kan se att certifikatinformation laddas in i requesten. Använder ju deras eget testcertifikat rakt av... har även debuggat och kollat utgångsdatumet för att se att det är färskt.

Har kontaktat Swish och frågat om hjälp.. de ska kolla upp mitt anrop i sina loggar och återkomma. I deras första svar gissade de att kanske inte "hela kedjan" med certifikat skickas med. Filen ska dock innehålla hela kedjan så det är om C# inte plockar med allt av någon anledning i så fall.

Kommer uppdatera denna tråd med mer info när jag får svar från Swish.

lazat 2016-02-14 10:14

Utan att veta så skulle jag gissa på chiffer suite fel. Bankerna brukar kräva säkra anslutningar, dessutom så har det den senase tiden många buggar dykt upp i ovan. Alla dessa måste bankerna skydda sig mot och ofta blir resultatet att den som ska anropa måste anpassa sig till dessa krav. Testa att med Internet Explorer gå in på post url från både server och din dator för att se om du får något cert fel. Om du gör det så här du nog hittat felet

lazat 2016-02-14 10:25

https://www.ssllabs.com/ssltest/anal...hideResults=on

Erkar som de har problem med cert. Beroende av Hur din dator behandlar detta så kan det bli problem

SEOutanHatt 2016-02-15 11:45

Att ssllabs.com inte "gillar" dem är nog på grund av att detta är deras testserver (om jag fattat rätt). De har nog ett ordentligt certifikat på produktionsservern.


Här är svaret jag fick från Swish:
---
Det jag ser i loggen är att vi får ett client hello sen inget mer, det betyder att antingen så är inte hela certifikatskedjan med eller så är det något fel i TLS handshake, så antingen felversion eller så blir det fel cipher suite.
Feb 11 16:39:06 lbt_bgc_a1 info tmm1[30882]: Rule /Common/pass_client_cert <CLIENT_ACCEPTED>: client IP: port=[mitt-ip-nummer]:59334; VIP=/Common/mss.swicpc.bankgirot.se_https_vs: New TCP connection to 172.31.21.185:443
---

Känns lite som att jag är ute och cyklar på djupt vatten här. Varför är de tvungna att krångla med certifikat? Kunde man inte använt id+lösen/tokens som alla andra betalleverantörer gör :(

SEOutanHatt 2016-02-15 13:05

Testade nu att läsa in certifikatet från certificate store istället för från fil och det verkar fungera.

Kod:

string serial = "1b46f254ae99f31c";

                X509Store store = new X509Store("My", StoreLocation.LocalMachine);
                store.Open(OpenFlags.ReadOnly);

                X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindBySerialNumber, serial, true);
                X509Certificate2 certificate = certificates[0];

                req.ClientCertificates.Add(certificate);


Så nu vet vi att det fungerar, nu gäller det bara att få det att fungera vid inläsning från fil istället. För det är inte direkt skalbart att behöva importera ett cert per kund när man har flera hundra kunder.

SEOutanHatt 2016-02-15 13:15

Nu hittade jag felet. Blir så trött på skitfel.

Koden här https://gist.github.com/RickardPette...402d2d59552732 har endast ett fel:

Det saknas en tvåa efter "X509Certificate". På rad 48 ska alltså stå:

Kod:

X509Certificate2 cert = new X509Certificate2(path, "swish", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
Lite lagom hemligt fel när det smet igenom kompilatorn också.

Tack för de tips jag fått och hoppas att mina tillägg kan ha hjälpt någon.

SEOutanHatt 2016-02-15 13:34

Hade visst fel. Trodde att när jag läste in certifikatet från fil så behövde jag inte ha det i cert store, men när jag tog bort det från cert store så slutade det att fungera. Tillbaka till ritbordet med andra ord :(

RickardP 2016-02-18 13:08

Låter som du SEOutanHatt kommit lika långt som mig förutom att jag fick det att fungera läsa från fil i en console app i windows men när jag gjort om till ASP.NET MVC projekt under iis så hittar den inte certifikatet så jag tror det har med rättigheter att göra.

Däremot inte haft tid att kolla vidare på detta.

Kommer du på en lösning så säg gärna till.

RickardP 2016-02-20 16:34

Jag har kommit så långt att den verkar hitta certifikatet och privat nyckeln men sen säger servern ifrån av någon anledning.

Har hittat något som aktiverae .Net trace log så här står det i den:


System.Net Information: 0 : [11852] SecureChannel#14193427 - Certificate is of type X509Certificate2 and contains the private key.
System.Net Information: 0 : [11852] AcquireCredentialsHandle(package = Microsoft Unified Security Protocol Provider, intent = Outbound, scc = System.Net.SecureCredential)
System.Net Information: 0 : [11852] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = ae84607320:579f591360, targetName = mss.swicpc.bankgirot.se, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [11852] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=1788, returned code=ContinueNeeded).
System.Net Information: 0 : [11852] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = ae84607320:579f591360, targetName = mss.swicpc.bankgirot.se, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [11852] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=IllegalMessage).
System.Net Error: 0 : [11852] Exception in HttpWebRequest#4095822:: - The request was aborted: Could not create SSL/TLS secure channel..
System.Net Error: 0 : [11852] Exception in HttpWebRequest#4095822::EndGetRequestStream - The request was aborted: Could not create SSL/TLS secure channel..

jayzee 2016-02-20 22:02

Lägg till denna innan anropet:

Kod:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

RickardP 2016-02-21 07:59

Citat:

Ursprungligen postat av jayzee (Inlägg 20516043)
Lägg till denna innan anropet:

Kod:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Hjälpte inte och det var en av grejerna som gjorde att jag kom vidare tidigare var att sätta Tls11 då deras server kör TLS 1.1

jackjson 2016-02-29 10:09

Digrad affärssystem bjuder på en lösning :)

Kod:

private HttpWebRequest CreateSwishRequest(String url, String clientCertPath, String clientCertPass)
{
    //Basic set up
    ServicePointManager.CheckCertificateRevocationList = false;
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11; //Tls12 does not work

    //Load client certificates
    var clientCerts = new X509Certificate2Collection();
    clientCerts.Import(clientCertPath, clientCertPass ?? "", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

    //Assert CA certs in cert store, and get root CA
    var rootCertificate = AssertCertsInStore(clientCerts);

    var req = HttpWebRequest.Create(url) as HttpWebRequest;
    req.ClientCertificates = clientCerts;
    req.Method = "POST";
    req.ContentType = "application/json; charset=UTF-8";
    req.AllowAutoRedirect = false;
           
    //Verify server root CA by comparing to client cert root CA
    req.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => {
        var chainRootCa = chain?.ChainElements?.OfType<X509ChainElement>().LastOrDefault()?.Certificate;
        if (rootCertificate == null || chainRootCa == null)
            return false;
        return rootCertificate.Equals(chainRootCa); //Same root CA as client cert
    };

    return req;
}

private X509Certificate2 AssertCertsInStore(X509Certificate2Collection certs)
{
    //Create typed array
    var certArr = certs.OfType<X509Certificate2>().ToArray();
    //Build certificate chain
    var chain = new X509Chain();
    chain.ChainPolicy.ExtraStore.AddRange(certArr.Where(o => !o.HasPrivateKey).ToArray());
    var privateCert = certArr.FirstOrDefault(o => o.HasPrivateKey);
    if (privateCert == null)
        return null;
    var result = chain.Build(privateCert);
    //Get CA certs
    var caCerts = chain.ChainElements.OfType<X509ChainElement>().Where(o => !o.Certificate.HasPrivateKey).Select(o => o.Certificate).ToArray();
    if (caCerts == null || caCerts.Length == 0)
        return null;
    //Assert CA certs in intermediate CA store
    var intermediateStore = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser);
    intermediateStore.Open(OpenFlags.ReadWrite);
    foreach (var ca in caCerts)
    {
        if (!intermediateStore.Certificates.Contains(ca))
            intermediateStore.Add(ca);
    }
    intermediateStore.Close();
    //Return last CA in chain (root CA)
    return caCerts.LastOrDefault();
}


RickardP 2016-03-03 09:01

Citat:

Ursprungligen postat av jackjson (Inlägg 20516204)
Digrad affärssystem bjuder på en lösning :)

Kod:

private HttpWebRequest CreateSwishRequest(String url, String clientCertPath, String clientCertPass)
{
    //Basic set up
    ServicePointManager.CheckCertificateRevocationList = false;
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11; //Tls12 does not work

    //Load client certificates
    var clientCerts = new X509Certificate2Collection();
    clientCerts.Import(clientCertPath, clientCertPass ?? "", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

    //Assert CA certs in cert store, and get root CA
    var rootCertificate = AssertCertsInStore(clientCerts);

    var req = HttpWebRequest.Create(url) as HttpWebRequest;
    req.ClientCertificates = clientCerts;
    req.Method = "POST";
    req.ContentType = "application/json; charset=UTF-8";
    req.AllowAutoRedirect = false;
           
    //Verify server root CA by comparing to client cert root CA
    req.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => {
        var chainRootCa = chain?.ChainElements?.OfType<X509ChainElement>().LastOrDefault()?.Certificate;
        if (rootCertificate == null || chainRootCa == null)
            return false;
        return rootCertificate.Equals(chainRootCa); //Same root CA as client cert
    };

    return req;
}

private X509Certificate2 AssertCertsInStore(X509Certificate2Collection certs)
{
    //Create typed array
    var certArr = certs.OfType<X509Certificate2>().ToArray();
    //Build certificate chain
    var chain = new X509Chain();
    chain.ChainPolicy.ExtraStore.AddRange(certArr.Where(o => !o.HasPrivateKey).ToArray());
    var privateCert = certArr.FirstOrDefault(o => o.HasPrivateKey);
    if (privateCert == null)
        return null;
    var result = chain.Build(privateCert);
    //Get CA certs
    var caCerts = chain.ChainElements.OfType<X509ChainElement>().Where(o => !o.Certificate.HasPrivateKey).Select(o => o.Certificate).ToArray();
    if (caCerts == null || caCerts.Length == 0)
        return null;
    //Assert CA certs in intermediate CA store
    var intermediateStore = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser);
    intermediateStore.Open(OpenFlags.ReadWrite);
    foreach (var ca in caCerts)
    {
        if (!intermediateStore.Certificates.Contains(ca))
            intermediateStore.Add(ca);
    }
    intermediateStore.Close();
    //Return last CA in chain (root CA)
    return caCerts.LastOrDefault();
}


Tackar, hade fått det att lira genom att installera root certifikatet på servern men detta kommer ju hjälpa så man slipper den biten.

jackjson 2016-03-03 09:36

Citat:

Ursprungligen postat av RickardP (Inlägg 20516257)
Tackar, hade fått det att lira genom att installera root certifikatet på servern men detta kommer ju hjälpa så man slipper den biten.

Yes, det fina med denna lösning är att alla CA-cert läggs i biblioteket för "mellanliggande certifikat" för aktuell användare, så ingen speciell behörighet krävs, och inga varningsrutor visas.

SEOutanHatt 2016-03-05 11:16

Vackert, tack för den!

RickardP 2017-06-14 10:30

Drar igång denna tråd igen, jag har nu äntligen satt mig ner och försökt få igång Swish för handel i ett projekt igen.

Med jackjson två funktioner får jag payment anropet och status anropet att fungera localhost när jag kör i visual studio och iis express, men så fort jag lägger över allt på min Windows 2012 r2 server med vanliga IIS så får jag:

System.Security.Cryptography.CryptographicExceptio n: The system cannot find the file specified

Så jag undrar nu om någon har fått allt att fungera i c# asp.net mvc eller liknande på en windows server och utan att lägga installera certifkatet?

Några tips?

allstars 2017-06-14 11:26

Prova detta:

Gå till applikationspoolen i IIS för sajten och gå till avancerade inställningar . ändra Load Profile option till true.

RickardP 2017-06-14 12:50

Tack, fungerade!
Citat:

Ursprungligen postat av allstars (Inlägg 20523421)
Prova detta:

Gå till applikationspoolen i IIS för sajten och gå till avancerade inställningar . ändra Load Profile option till true.


RickardP 2017-06-14 13:54

Försöker nu få igång allt LIVE med payex produktionsmiljö så skapade en request i iis server certificate och så la in innehållet på swish bankgrio sida för certifikatet och fick en kod som jag sparade som fil och körde complete på iis server certificate.

Sen exporterade jag den och fick en pfx fil. Hur använder jag nu denna fil localhost när jag debugar i visual studio?

Testade använda den precis som p12 test filen men får "The request was aborted: Could not create SSL/TLS secure channel".

Dock på servern där jag har certet i iis server certificate så fungerar det.

Någon som fått samma cert att fungera localhost?

RickardP 2017-07-09 22:19

Har ikväll släppt http://www.tabetaltmedswish.se/ som är ett test projekt i C# ASP.NET MVC 5 som går att forka eller ladda ner för att se exempel kod hur man får Swish För Handel att fungera.


Alla tider är GMT +2. Klockan är nu 13:33.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson