Bokmål English
Registrer deg Register
Språk    Language    Bokmål English Tjenester privat Tenester privat Private Tjenester bedrift Tenester verksemd Business Hjelp Help Hjelp Help
For partnere For partnarar For partners For utviklere For utviklarar For developers Sikkerhet Sikkerheit Security Vilkår Terms
Du må oppgradere nettleseren din for å bruke Digipost. Les mer her.

Sikkerhet i Digipost API

Security in the Digipost API

Sikkerheten er svært viktig for Digipost. Derfor har vi utviklet en sikkerhetsmekanisme som garanterer meldingers konfidensialitet, autentisitet, integritet og uavviselighet.

Security is critical for Digipost. Therefore we have designed a custom security mechanism which guarantees the message's confidentiality, autenticity, integrity and non-repudiation.

Mekanismen er i stor grad basert på bransjestandarder, men kombinasjonen av alle disse elementene gjør at vi anbefaler at du leser dette dokumentet nøye slik at du har forståelse for hvordan sikkerheten er håndtert. Dersom du skal gjøre en integrasjon mot Digipost api-et, må du også ha en god forståelse av disse mekanismene.

The security mechanism is based on a combination of well-established standards. Since our approach is a custom combination, we recommend that you read the following page thoroughly so that you understand security in the Digipost API. If you are planning to integrate directly with the Digipost API, you must understand the following content.

1. Introduksjon

1. Introduction

Sikkerheten til Digipost-api-et er basert på at alle meldinger mellom api-klienten og api-serveren signeres med SHA-256 med rsa-kryptering (SHA256WithRSAEncryption-algoritmen).

The security in the Digipost api is based on all messages between the (api) client and Digipost being signed with SHA-256 with rsa encryption (SHA256WithRSAEncryption algorithm).

SHA-256 er en enkel hashing-algoritme som gjør at meldingen som signeres, blir mindre. rsa er en standard for kryptering med asymmetriske nøkler, og er basert på at du som bruker benytter din private nøkkel (som ligger som en del av ditt sertifikat) for å signere, mens vi benytter din åpne (public) nøkkel for å verifisere signaturen.

SHA-256 is a simple hashing algorithm that will make the message to be signed smaller. rsa is a standard for encrypting with asymmetrical keys which is based on you using your private key (which is included in your certificate) to sign the message, while the Digipost solution uses your public key to verify the signature.

Denne mekanismen og det faktum at meldinger transporteres over ssl, sørger for at rest-api-et oppnår den sikkerheten det trenger:

This mechanism plus use ofsslat the transport layer ensures that the Digipost api is secure:

  1. Konfidensialitet: Ingen andre kan lese meldingens innhold.
  2. Autentisitet: Vi vet at meldingen kommer fra deg og ingen andre.
  3. Integritet: Vi vet at meldingen ikke er blitt endret på veien mellom deg og oss.
  4. Uavviselighet: Vi kan dokumentere i ettertid at det var du og ingen annen som sendte meldingen.
  1. Condidentiality: No one else can read the content of the message.
  2. Autenticity: We know that you are the originator of the message and no one else.
  3. Integrity: We know that the message has not been changed in transport between you and us/Digipost.
  4. Non-repudiation: We can document after the fact that you were the originator of the message.

2. Headere

2. Headers

Måten sikkerheten til api-et er implementert på, krever at du legger til noen headere på alle forespørsler du gjør. Følgende headere benyttes:

Security in the Digipost api requires that you add a few custom headers in all the requests you make. The following headers are used.

Når disse tre headerne er lagt på, og forespørselen er ferdig laget fra din side, kan du generere den siste headeren. Denne er basert på de tre foregående headerne, pluss enkelte andre elementer i forespørselen (metode, sti, parametre).

When those three headers are added and the request is ready on your end, you can create the last header. This header is based on those three other headers and other parts of your request (HTTP method, path, parameters).

Resten av denne siden dreier seg om nettopp denne headeren, og hvordan du kan generere den.

The following information is related to this header and how to generate it.

2.1 Eksempel på alle headerne

2.1 Example of all headers

Følgende er et eksempel på et fullstendig sett av de headerne som er påkrevd for en POST-forespørsel fra vår side. http-forespørselen vil normalt også inneholde en rekke andre headere, men de er ikke relevante her. En GET-forespørsel uten innhold vil ha de samme headerne bortsett fra X-Content-SHA256 som da ikke er med.

The following is an example with a complete set of the required headers in a POST request to the Digipost API. The http request will typically also include other headers that are not relevant in this context. A GET request will include the same headers with the exception of X-Content-SHA256 which should then not be included.

Date: Wed, 29 Jun 2011 14:58:11 GMT
X-Digipost-UserId: 9999
X-Content-SHA256: q1MKE+RZFJgrefm34/uplM/R8/si9xzqGvvwK0YMbR0=
X-Digipost-Signature: BHvtgDTKz490iMbYZsOf5+FvWCsWDt5oJgyTvXlLiNrWgUu/fhuY8AJYBoH8g+0t46slsmJqQxNlsa6u+cF1aE921cZy7ISSeRLl/z6WlwCtTGu9fFH9X4Kr+2ffwPqzCTRPD4D5jHrbudmSGZJIq3ImAKU250t6SCJ//aiAKMg=

3. Signering av request

3. Signing the request

Signering av meldingen gjøres ved å benytte SHA256WithRSAEncryption-algoritmen på en strengt definert streng. Dette resulterer i en lang streng som vi senere kan verifisere på serveren ved å benytte din offentlige nøkkel og en tilsvarende streng vi genererer.

You sign the request by using the SHA256WithRSAEncryption algorithm on a strongly defined string. This will result in a long string that we can verify server-side using your public key and a similar string we generate on our end.

3.1 Buypass-sertifikat vs. Digipost-sertifikat

3.1 Buypass certificate vs. Digipost certificate

For å signere forespørselen din trenger du først et sertifikat. Dette kan enten være et virksomhetssertifikat du har kjøpt av Buypass, eller et Digipost-sertifikat vi genererer til deg. Forskjellen mellom dem er at med Buypass-sertifikatet er vi ikke på noe tidspunkt i besittelse av den private delen av ditt sertifikat, og vi oppnår dermed full uavviselighet. Til forskjell fra dette vil vi når vi genererer et Digipost-sertifikat, i en kort periode være i besittelse av den private delen av nøkkelen. Denne lagres aldri på disk, og slettes fra minnet umiddelbart etter at den er oversendt til deg, men gjør like fullt at forsendelser gjort med dette sertifikatet ikke kan regnes som fullt uavviselige. Derfor er det viktig at din virksomhet gjør en vurdering av hvilket type sertifikat dere ønsker å benytte ut i fra disse to alternativene. Når valget er tatt, kan du enkelt laste opp eller laste ned (avhengig av typen du velger) sertifikatet fra virksomhetssidene dine på Digipost.

To sign your request you need a certificate. This can either be a Buypass certificate that you have purchased or a Digipost certificate that we generate for you. When you use your own Buypass certificate, Digipost will never be in posession of the private key part of your certificate, which is required for full non-repudiation. If we generate the certificate for you, we will for a very short period be in posession of the private key part of the generated certificate. The private key is never stored on disc, it is only stored in memory until it is made available for your download. It is your responsibility to decide which certificate type best meets your security requirements. After you have decided what type of certificate you wish to use, you can easily upload or download (depending on the type you use) the certificate at digipost.no/bedrift.

3.2 Generering av strengen som skal signeres

3.2 Generating the string to be signed

Når sertifikatet ditt er lagret hos Digipost og du har tilgang til dette fra kodebasen din, er du klar til å generere strengen som skal signeres. Dette er en streng på et fast format som er basert på innholdet av meldingen.

When you have stored your certificate with Digipost and you can access the private key of your certficate from your code base, you are ready to generate the string that needs to be signed. This is a string that follows a defined format based on the content of your message.

Det vil være unødvendig, tidkrevende og til dels umulig å signere hele meldingen. Istedenfor genererer du en kortere streng som inneholder vesentlige og uforanderlige deler av forespørselen, som du deretter signerer. Det er viktig at strengen som skal signeres, genereres eksakt som beskrevet nedenfor – ellers vil forespørselen avvises av serveren.

It would be both unnecessary, timeconsuming and likely not possible to sign the entire message. Instead you will generate a shorter string which includes relevant and unchangeable parts of your request, that is then signed. It is important that the string is generated exactly as described below. If not, your request will be rejected.

Strengen består av seks linjer, hver med et påfølgende linjeskift (også for den siste linjen). Merk at linjeskiftene består av én byte (\n) og altså ikke er Windows-linjeskift, men Unix-linjeskift.

The string is comprised of six lines, each line finishes with a newline (also the last line). Note that the newline consists of one byte (\n) and is not a Windows newline (it is a Unix newline).

3.2.1 Eksempel på signeringsstreng

3.2.1 Example of signed string

Følgende streng er et eksempel på hvordan en slik generert streng kan se ut for en POST-forespørsel med innhold:

The following is an example of how such a generated string may look in a POST request with content

POST
/messages
date: Wed, 29 Jun 2011 14:58:11 GMT
x-content-sha256: q1MKE+RZFJgrefm34/uplM/R8/si9xzqGvvwK0YMbR0=
x-digipost-userid: 9999
parameter1=58&parameter2=test

Tilsvarende for en GET-forespørsel uten innhold:

Example of a GET request without content:

GET
/
date: Wed, 29 Jun 2011 14:58:11 GMT
x-digipost-userid: 9999
parameter1=58&parameter2=test

3.2.2 Pseudokode for generering

3.2.2 Pseudocode for generating the string

Her er pseudokode som forklarer hvordan man genererer signaturstrengen:

The following is pseudocode for how to generate the string to be signed:

String stringToSign = uppercase(verb) + "\n" +
                      lowercase(path) + "\n" +
                      "date: " + datoHeader + "\n" +
                      "x-content-sha256: " + sha256Header + "\n" +
                      "x-digipost-userid: " + virksomhetsId + "\n" +
                      lowercase(urlencode(requestparametre)) + "\n";

String signature =    base64(sign(stringToSign));

3.2.3 Java-kode for generering

3.2.3 Java code for generating string

Følgende Java-kode benyttes av Java-klientbiblioteket for å generere signatur-strengen.

The following Java code is included in the Java client library to generate the string to be signed.

Dersom du bruker et av våre klientbibliotek, håndteres dette for deg, men dersom du lager din egen implementasjon, kan du bruke denne klassen som inspirasjon for din kode:

If you use one of our client libraries, you will not need to implement this. If you are implementing an integration directly with the Digipost API, the following can be used as inspiration:

public class MessageSignatureUtil {

    private static final List<String> HEADERS_FOR_SIGNATURE = Arrays.asList(X_Content_SHA256.toLowerCase(),
            Content_MD5.toLowerCase(), Date.toLowerCase(), X_Digipost_UserId.toLowerCase());

    public static String getCanonicalRequestRepresentation(final RequestToSign request) {
        StringBuilder s = new StringBuilder();
        s.append(getCanonicalMethodRepresentation(request));
        s.append(getCanonicalUrlRepresentation(request));
        s.append(getCanonicalHeaderRepresentation(request));
        s.append(getCanonicalParameterRepresentation(request));
        return s.toString();
    }

    private static String getCanonicalMethodRepresentation(final RequestToSign request) {
        return request.getMethod().toUpperCase() + "\n";
    }

    private static String getCanonicalUrlRepresentation(final RequestToSign request) {
        return request.getPath().toLowerCase() + "\n";
    }

    private static String getCanonicalHeaderRepresentation(final RequestToSign request) {
        SortedMap<String, String> headers = request.getHeaders();
        StringBuilder headersString = new StringBuilder();
        for (Entry<String, String> entry : headers.entrySet()) {
            String key = entry.getKey();
            if (isHeaderForSignature(key)) {
                headersString.append(key.toLowerCase() + ": " + entry.getValue() + "\n");
            }
        }
        return headersString.toString();
    }

    private static String getCanonicalParameterRepresentation(final RequestToSign request) {
        return request.getParameters().toLowerCase() + "\n";
    }

    private static boolean isHeaderForSignature(final String key) {
        return HEADERS_FOR_SIGNATURE.contains(key.toLowerCase());
    }

}

3.3 Signaturen

3.3 Signature

Når du har generert en streng som beskrevet, kan den signeres ved hjelp av din private nøkkel. Algoritmen som brukes, er SHA-256 med rsa-kryptering.

When you have generated the string as described, it can be signed with your private key. SHA-256 with rsa encryption is the algorithm that should be used.

Når signaturen er laget, chiffrerer man den med Base64. Deretter legges denne representasjonen til i http-headeren X-Digipost-Signature.

When the signature is created, you Base64 encode it. The result is then used as the header value for the http header X-Digipost-Signature.

Siden den signerte strengen inneholder SHA256-hashen av meldingen, er det ikke mulig å endre meldingen etter signering uten at signaturen ugyldiggjøres. Signaturen inneholder også din virksomhets id, samt datoen for når requesten ble sendt. Dette sørger for autentisering, og forhindrer replay-angrep. I tillegg kan signaturen bare genereres av noen som kjenner din private nøkkel, noe som gjør at uavviselighetskravet oppfylles.

Since the signed string includes a SHA256 hash of the message, it is not possible to change the message after signing with invalidating the signature. The signature also includes your sender id and the date/time the request was sent. The ensures correct authentication and prevents replay attacks. The signature can only be generated by someone in posession of your private key which ensures non-repudiation.

4. Verifisering av respons-signatur

4. Verifying the response signature

På samme måte som du signerer alle forespørsler du sender til serveren, så signerer også serveren alle svar den sender tilbake til deg. Du kan verifisere denne signaturen på samme måte som vi verifiserer din signatur.

The same way that you sign all requests that you send to Digipost, Digipost signs all responses that are sent to you. You can verify this signature the same way that Digipost verifies you signature.

4.1 Hvordan vi genererer signaturen

4.1 How Digipost gererates the signature

Signaturmekanismen fungerer på akkurat samme måte som beskrevet i seksjonen om request-signering. Følgende steg gjøres på serveren for å generere signaturen:

The signature mechanism works exactly as described in the section on signing the request. The following steps occur server-side to generate the signature.

Følgende er et eksempel på en kanonisk streng som representerer responsen:

The following is an example og a canonical string that represents the response:

200
/messages
date: Mon, 18 Nov 2013 09:06:42 GMT
x-content-sha256: lTapuncEksiIcxVAw0ibcWzex3zoeMWmACvtov4IZJY=

Avslutningsvis signerer vi denne strengen med den private nøkkelen til Digipost (vi bruker SHA256WithRSAEncryption-algoritmen), og legger på signaturen i en header kalt X-Digipost-Signature.

The final step is to sign this string with Digiposts private key (we use the SHA256WithRSAEncryption algorithm) and populate the value for the X-Digipost-Signature header.

Vi ender opp med at responsen har følgende headere:

We end up with a response with the following headers:

Date: Mon, 18 Nov 2013 09:06:42 GMT
X-Content-SHA256: lTapuncEksiIcxVAw0ibcWzex3zoeMWmACvtov4IZJY=
X-Digipost-Signature: BHvtgDTKz490iMbYZsOf5+FvWCsWDt5oJgyTvDUMMYrWgUu/fhuY8AJYBoH8g+0t46slsmJqQxNlsa6u+cF1aE921cZy7ISSeRLl/z6WlwCtTGu9fFH9X4Kr+2ffwPqzCTRPD4D5jHrbudmSGZJIq3ImAKU250t6SCJ//aiAKMg=

4.2 Hvordan du kan verifisere signaturen

4.2 How do you verify the signature

For å verifisere denne signaturen gjør du følgende steg på din side:

To verify the signature you do the following:

For å matche signaturen trenger du den offentlige nøkkelen til Digipost (public key). Denne vil du finne vedlagt i rotressursen, altså svaret du får når du kaller på https://api.digipost.no/:

To verify the signature in the response you will need Digipost's public key. You can access this key at the root resource (i.e. in the response when you send a request to https://api.digipost.no/):

GET / HTTP/1.1
Accept: application/vnd.digipost-v6+xml

Nøkkelen finner du da i XML-responsen:

The Digipost public key is in the response:

200
Content-Type: application/vnd.digipost-v6+xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

	
-----BEGIN CERTIFICATE-----
MIIBtTCCAWOgAwIBAgIQQLU1zzCvy4ZPp4vRzp4yzjAJBgUrDgMCHQUAMBYxFDASBgNVBAMTC1Jv
b3QgQWdlbmN5MB4XDTExMDUwMzEwMTgyOFoXDTM5MTIzMTIzNTk1OVowGDEWMBQGA1UEAxMNRGln
aXBvc3QgVGVzdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAx6io8f76X+1PsL5i9kTjzSIy
...
-----END CERTIFICATE-----
	
    ...

OBS: Sertifikatet ovenfor er bare et eksempel på hvordan det vil se ut, det er viktig at du bruker sertifikatet du får ut fra rot-ressursen til å gjøre verifiseringen. Ved å alltid bruke sertifikatet du får ut på rotressursen, sørger du for at du bruker riktig sertifikat også når Digipost bytter sertifikat på grunn av f.eks utløpsdato.

Note: The certificate above is only an example. When verifying responses from Digipost, it is important that you use the public key that is actually returned in the response when you make a request to the root resource. That way Digipost can change certificate without impact.

5. Feilsøking

5. Troubleshooting

For at det skal være enklest mulig for deg å oppdage feil når du implementerer denne sikkerhetsmekanismen, har vi gjort vårt beste for at feilhåndteringen i api-et skal være robust, og at du får informative feilmeldinger og hjelp til å feilsøke dersom noe går feil.

In order to make troubleshooting the Digipost api security implementation as painless as possible, we have made error handling in the api as robust as possible, and included informative error messsages.

5.1 Et tenkt feilsøkingsscenario

5.1 A possible troubleshooting scenario

Her er et eksempel på et tenkt scenario der en utvikler forsøker å integrere mot api-et. Vi ser her på hva utvikleren forsøker å gjøre, og ser hvordan api-et hjelper ham med å feilsøke etter problemer.

The following is an example that shows how a developer may interact with the Digipost api when troubleshooting.

5.1.1 Første forsøk

5.1.1 First

Utvikleren gjør et første forsøk på å sende et brev, og gjør følgende kall:

A developer makes a first attempt at sending a letter and sends the following request:


POST https://api.digipost.no/messages
Accept: application/vnd.digipost-v6+xml
X-Digipost-UserId: 5
Content-Type: application/vnd.digipost-v6+xml
Date: Fri, 01 Jul 2011 09:19:20 GMT
X-Content-SHA256: q1MKE+RZFJgrefm34/uplM/R8/si9xzqGvvwK0YMbR0=
X-Digipost-Signature: BHvtgDTKz490iMbYZsOf5+FvWCsWDt5oJgyTvXlLiNrWgUu/fhuY8AJYBoH8g+0t46slsmJqQxNlsa6u+cF1aE921cZy7ISSeRLl/z6WlwCtTGu9fFH9X4Kr+2ffwPqzCTRPD4D5jHrbudmSGZJIq3ImAKU250t6SCJ//aiAKMg=
User-Agent: Java/1.6.0_24
Host: api.digipost.no
Connection: keep-alive
Content-Length: 389

<?xml version="1.0" encoding="utf-8">

	
		ola.nordmann#1234
	
	
		6d99008e-2672-4b55-9b09-996b09a06e47
		simple-document
		txt
		PASSWORD
		NORMAL
	


api-et svarer da med følgende respons:

The api answers with the following response:


403
Content-Type: application/vnd.digipost-v6+xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

	GENERAL_ERROR
	No certificate found. Please upload a certificate in virksomhetsadmin at digipost.no.

Utvikleren laster så opp sitt sertifikat, og forsøker igjen.

The developer then uploads the organisation's certificate to Digipost and tries again.

5.1.2 Andre forsøk

5.1.2 Second try

Utvikleren gjør akkurat samme kall som i første forsøk, og siden han nå har lastet opp sitt sertifikat får han ikke lenger den samme feilmeldingen. Men denne gangen kommer det en annen feilmelding:

The developer sends the exact same request as in the first try. Since she has uploaded the correct certificate, the error message has changed:


403
Content-Type: application/vnd.digipost-v6+xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

	GENERAL_ERROR
	
The signature found in the " + X_Digipost_Signature + " header could not be verified.
Possible reasons for this may be that the certificate used for signing is not the same that is uploaded to Digipost, or the format of the signature is invalid.

Canonical string to sign generated by Digipost, with each line terminated with a newline character (\\\\n), was:
===START===
POST
/messages
date: Wed, 05 Dec 2012 12:48:10 GMT
x-content-sha256: q1MKE+RZFJgrefm34/uplM/R8/si9xzqGvvwK0YMbR0=
x-digipost-userid: 5

===SLUTT===
	

Utvikleren sjekker på sin side og ser at strengen han har generert er følgende:

The developer checks on her side and sees that the string she has generated is the following:

POST
/messages
Date: Wed, 29 Jun 2011 14:58:11 GMT
X-Content-SHA256: q1MKE+RZFJgrefm34/uplM/R8/si9xzqGvvwK0YMbR0=
X-Digipost-UserId: 5

Etter å ha sammenlignet disse to strengene, oppdager han to problemer:

After comparing the two strings, she notices two problems:

  1. Han har glemt å skrive headernavnene med små bokstaver. Dette gjør at signaturen blir helt forskjellig.
  2. I tillegg er det en liten detalj til som er feil: Legg merke til at han i denne forespørselen ikke har noen request-parametre. Han har derfor glemt å legge på en tom linje til slutt der disse skulle ha vært (noe spesifikasjonen krever). Selv en liten feil som dette vil gjøre signaturen helt forskjellig. Han legger også på dette linjeskiftet, og står da igjen med følgende streng til signering:
  1. She has not generated the header names in small caps. This results in the signature being different.
  2. There is also another small detail that is incorrect. Note that this request does not have any request parameters. The developer has not included an empty line where the request parameters would typically be included (and that the specification requires). Even a small detail like this will cause the signature to be different. The developer adds this empty line. The result is the following string:
POST
/messages
date: Wed, 29 Jun 2011 14:58:11 GMT
x-content-sha256: q1MKE+RZFJgrefm34/uplM/R8/si9xzqGvvwK0YMbR0=
x-digipost-userid: 5

5.1.3 Tredje forsøk

5.1.3 Third try

Etter å ha rettet problemene med signaturstreng-genereringen på sin side, forsøker utvikleren igjen å gjøre forespørselen mot api-et.

After making the necessary changes to the string to be signed, the developer sends a new request to the Digipost api.

Serveren svarer nå følgende:

The Digipost api now responds with the following:

201

Location: https://api.digipost.no/messages/1001
Content-Type: application/vnd.digipost-v6+xml



	DIGIPOST
	497013
	DELIVERED
	2016-12-07T08:45:32.675+01:00
	
		6d99008e-2672-4b55-9b09-996b09a06e47
		simple-document
		txt
		PASSWORD
		NORMAL
		false
		5o0RMsXcgSZpGsL7FAmhSQnvGkqgOcvl5JDtMhXBSlc=
	


Denne gangen aksepteres meldingen av serveren, og utvikleren kan nå sende inn pdf-en slik at han får sendt brevet. Når alt virker, kan han si seg fornøyd med testingen mot sin testkonto hos Digipost, og han kan gå over til å benytte Digipost produksjonskontoen for å sende brev på ordentlig. Åpning a produksjonskonto kan gjøres ved å sende en e-post til Digipost support.

This time Digipost accepts the request and the developer can send the actual document content (e.g. pdf). When the developer is comfortable with the completed testing against the organisation's test account, the Digipost production account can be made accessible by sending av email to Digipost support.

Åpne Posten og Bring sin chatdialog