På tullverket.se använder vi kakor (cookies) för att webbplatsen ska fungera på ett bra sätt för dig.
Genom att surfa vidare godkänner du att vi använder kakor. Vad är kakor?
Här får du svar på de vanligaste frågorna om PKI, det vill säga autack och signering. Observera att vid skillnader mellan detta dokument och den tekniska specifikationen är den tekniska specifikationen som gäller.
SHA-256
UNH till och med UNT
Checksumman ska representeras hexadecimalt (inte base-64-kodad) i autacken. Det ska inte vara några mellanslag i det hexadecimala värdet.
Det beror på vilket utvecklingsplattform ni använder, men det kan se ut ungefär enligt nedan:
byte [] unhTillUnt = ....
md = MessageDigest.getInstance("SHA-256");
md.update(unhToUnt, 0, unhTillUnt.length);
byte [] checksum = md.digest();
OpenSSL kan användas.
openssl dgst -sha256
Några vanliga anledningar är:
RSA. Ofta görs checksummeberäkning och signering i ett steg och då brukar algoritmen benämnas SHA256WithRSA.
Det är byterepresentationen av checksumman (alltså inte den hexadecimalkodade representationen) som ska signeras.
Beroende på vilken utvecklingsmiljö ni använder görs det i ett eller två steg. I vissa miljöer, till exempel Java, görs det i ett steg och då är det UNH-UNT som signeras, till exempel enligt nedan.
Signature sig = Signature.getInstance("SHA256WithRSA");
sig.initSign(signKey);
sig.update(unhTillUntString, 0, unhTillUntString.length);
byte [] bytes = sig.sign ();
I andra miljöer, till exempel Microsofts CryptoAPI skapas checksumman baserat på UNH-UNT och signaturen beräknas på byte-representationen av checksumman, till exempel enligt nedan.
bResult = CryptHashData(hHash, unhTillUntString, cbRead, 0 );
bResult = CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen );
Den krypterade kryptografiska checksumman (digitala signaturen) får inte kodas enligt base64, utan måste hexadecimalkodas. Det får inte finnas några mellanslag i det hexadecimalkodade värdet.
Vi är ännu inte redo att skicka EDIFACT-filer, men önskar få vår implementering av signaturen verifierad. Kan ni verifiera vår krypterade checksumma? Nej, vi behöver hela EDIFACT-utväxlingen.
Utfyllnad sker med RSASSA-PKCS1-v1_5. Detta är troligen standardalternativet i den utvecklingsmiljö ni använder.
OpenSSL kan användas
openssl rsautl —sign
openssl rsautl —verify
Orsaken kan till exempel vara:
Detta är en unik intern referns från USH till motsvarande USY-segment. I princip är det en räknare vars namn genereras av sändaren, men i praktiken räcker det med ett värde, till exempel SRN01 eftersom endast en signatur används.
Detta är ert EORI-nummer inklusive land-kod. Observera att det inte ska sammanblandas med certifikatets serienummer och det ska varken kodas med base-64 eller med hexadecimal.
Detta är en base-64 kodning av certifikatets serienummer. Det är byte-representationen av serienumret som ska base-64 kodas. Ett vanligt fel är att istället använda den hexadecimalkodade representationen av serienumret som presenteras i en del certifikatvisningsverktyg. Ett annat vanligt fel är att använda EORI-nummer från certifikatets ämnes fält (SERIALNUMBER=, OU=, O=,C=,CN=..)
Detta är en base-64 kodning av nyckel-id för utfärdarcertifikatet. Detta används av Tullverket för att avgöra vilket certifikat som signaturen ska verifieras mot.
Som exempel ser värdet för certifikat utgivna av “CN=Swedish Customs Public CA 1.0, SERIALNUMBER=SE2021000969, OU=Only for authorized use, OU=Public Intermediate Certificate Authority, OU=Swedish Customs, O=Tullverket, C=SE" ut så här:
PS1IRSLAUC0cmps4EQMSDUL77f8=
Verifieringen innefattar följande steg:
1. Checksumma beräknas på UNH-UNT med SHA-256. Denna checksumma jämförs med checksumman i autacken. Fel skulle upptäckas även om enbart verifiering gjordes av den elektroniska signaturen, men detta steg ger oss möjlighet att ge bättre felmeddelanden.
2. Den publika nyckeln för certifikatet som pekas ut med serienummer och nyckel-id för utfärdare hämtas ut.
3. Den elektroniska signaturen dekrypteras med den publika nyckeln som hämtades i föregående steg.
4. Den dekrypterade elektroniska signaturen (=checksumman) jämförs med den beräknade checksumman.
Exakt hur detta görs beror på er utvecklingsmiljö, men det kan se ut ungefär så här i Java:
BigInteger serial = x509Certificate.getSerialNumber().
new Base64Encoder().encode(serial.toByteArray());
och så här i C#
System.Convert.ToBase64String(X509Certificate.GetSerialNumber());
Observera att certifikatets serienummer inte är samma som SERIALNUMBER i ämne (subject distinguished name) för certifikatet.
Byte-representationen av serienumret ska kodas med base-64. Ett vanligt fel är att istället använda hexadecimalkodning eftersom många certifikatvisningsprogram presenterar serienumret i hexadecimalform. Ett annat vanligt fel är att base-64 koda den hexadecimala representationen istället för byte-representationen. I Unix kan ett hexadecimalt värde konverteras till base-64 med nedanstående kommando. Det kan användas för att verifiera att värde i genererad autack är korrekt:
echo "00 97 95 45 e3 c4 c2 59 ef " | xxd -r -p | openssl base64
AJeVRePEwlnv
Fältet authorityKeyIdentifier i ett certifikat används för att unikt identifiera vilket utfärdarcertifikat som har använts för att signera ett certifikat. Fältet authorityKeyIdentifier i ett certifikat svarar mot fältet subjectKeyIdentifier i motsvarande utfärdarcertifikatet. Fältet kan innehålla följande underliggande fält (se också RFC 5280).
Publika nycklar bifogas inte i autack vid signering och därför måste Tullverket söka fram vilket certifikat som signaturen ska verifieras mot. Det underliggande fältet keyIdentifier (nyckel-id) används av Tullverket för att hitta detta certifikat. Serienummer är inte tillräckligt eftersom eftersom olika utfärdare kan ha samma serienummer."Se också avsnitt 4.2.1.1 i http://www.rfc-editor.org/rfc/rfc5280.txt för mer information.
Läs ut det underliggande fältet keyIdentifier från certifikatfältet AuthorityKeyIdentifier och koda detta värde med base64. AuthorityKeyIdentifier återfinns i certifikatextensionen 2.5.29.35. Exakt hur man läser detta värde beror på vilken utvecklingsmiljö ni använder, men det kan se ut ungefär enligt nedan:
byte[] extvalue = x509Certificate.getExtensionValue("2.5.29.35");
DEROctetString oct = (DEROctetString) (new ASN1InputStream(new ByteArrayInputStream(extvalue)).readObject());
AuthorityKeyIdentifier keyId = new AuthorityKeyIdentifier((ASN1Sequence) new ASN1InputStream(new ByteArrayInputStream(oct.getOctets())).readObject());
base64Encode(keyId.getKeyIdentifier());
Byte-representationen av nyckel-id för authorityKeyIdentifier ska kodas med base-64. Ett vanligt fel är att istället använda hexadecimalkodning eftersom många certifikatvisningsprogram presenterar fältet i hexadecimalform. Ett annat vanligt fel är att base-64-koda den hexadecimala representationen istället för byte-representationen. I Unix kan ett hexadecimalt värde konverteras till base-64 med nedanstående kommando. Det kan användas för att verifiera att värde i genererad autack är korrekt:
echo "3d 2d 48 45 22 c0 50 2d 1c 9a 9b 38 11 03 12 0d 42 fb ed ff" | xxd -r -p | openssl base64
PS1IRSLAUC0cmps4EQMSDUL77f8=
Riktlinjer och anvisningar avseende säkerhet vid informationsutbyte via EDI
Nya rot-och CA-certifikat för Tullverkets CA för informationsutbyte via EDI