Velg feil signeringsalgoritme for JSON Web Token, og du sitter enten med en autentiseringstjeneste som sluker CPU-tid, eller med et hull en angriper kan kjøre gjennom med et par linjer Python. HS256, RS256 og ES256 løser det samme problemet, å bevise at et token ikke er tuklet med, men de gjør det med helt ulik matematikk, ulik nøkkelhåndtering og svært ulik ytelse. Nyere biblioteker har i tillegg lagt til EdDSA (Ed25519) som et fjerde alternativ, og flere sikkerhetsmiljøer peker nå på det som standardvalget for nye systemer.
Denne gjennomgangen går gjennom faktiske benchmarktall fra tre uavhengige kilder, offentlig dokumenterte sårbarheter med CVE-numre, og en kostnadsberegning basert på reelle AWS Lambda-priser. Målet er ikke å kåre en universell vinner, for det finnes ikke, men å gi deg tallene du trenger for å velge riktig algoritme til ditt system.
Bakgrunnen for at spørsmålet dukker opp igjen og igjen, er at de fleste team møter valget for sent. En startup velger HS256 fordi det er standardoppsettet i et rammeverks quickstart-guide, og oppdager først halvannet år senere, når et partnerselskap trenger å verifisere tokens uavhengig, at hele autentiseringsarkitekturen må bygges om. Andre går motsatt vei: de velger RS256 fra dag én for et internt system med to tjenester, og betaler unødvendig CPU-kostnad i årevis for en fleksibilitet de aldri bruker. Riktig valg handler om å kjenne arkitekturen din, ikke om å følge en generell anbefaling blindt.
Hva er JWT, og hvorfor betyr algoritmevalget noe
Et JSON Web Token består av tre deler adskilt av punktum: en header med metadata om algoritmen, en payload med selve dataene (claims), og en signatur som beviser at innholdet ikke er endret etter utstedelse. Strukturen er standardisert i RFC 7519, mens selve signeringsalgoritmene, altså hvilken matematikk som brukes til å produsere signaturen, er definert i RFC 7518 (JSON Web Algorithms, JWA).
Algoritmen du velger påvirker tre ting direkte: hvor raskt tjeneren din kan signere og verifisere tokens under last, hvor mange bytes hvert token legger til i hver HTTP-forespørsel, og hvilken type nøkkelhåndtering du må bygge rundt løsningen. HS256 bruker én delt hemmelighet for både signering og verifisering. RS256 og ES256 bruker nøkkelpar, der en privat nøkkel signerer og en offentlig nøkkel verifiserer, noe som er nødvendig når utsteder og forbruker av tokenet er ulike systemer. Denne strukturelle forskjellen er kjernen i hele sammenligningen, og den avgjør hvilken algoritme som faktisk passer arkitekturen din.
For norske og nordiske utviklerteam som bygger API-er mot tredjepartsklienter, eller som må forholde seg til OIDC-baserte innloggingsløsninger fra store identitetsleverandører, er dette valget sjelden trivielt. Feil valg tidlig i et prosjekt betyr ofte en smertefull migrering senere, noe vi går gjennom i detalj mot slutten av artikkelen.
Det er også verdt å skille mellom hva claims-delen av tokenet brukes til og hva signaturalgoritmen faktisk beskytter. Payload-delen av et JWT er kun Base64URL-kodet, ikke kryptert, og kan leses av hvem som helst som fanger opp tokenet, uavhengig av om du bruker HS256, RS256, ES256 eller EdDSA. Signaturalgoritmen garanterer integritet og autentisitet, altså at innholdet ikke er endret og at det kommer fra riktig utsteder, ikke konfidensialitet. Skal sensitive data holdes skjult, trengs et eget krypteringslag, typisk JWE, i tillegg til signeringen. Denne distinksjonen er grunnleggende, men overraskende mange nye utviklere antar feilaktig at et signert JWT også er kryptert.
HS256 forklart: symmetrisk signering med delt hemmelighet
HS256 står for HMAC med SHA-256, en symmetrisk MAC-algoritme (Message Authentication Code) der samme hemmelige nøkkel brukes både til å produsere og til å verifisere signaturen. Konstruksjonen er enkel: hemmeligheten hasjes sammen med token-innholdet via HMAC, og resultatet blir en 32-byte signatur.
Fordelen er ren fart. Fordi HMAC bare krever hashing og ingen tung asymmetrisk matematikk, er HS256 den desidert raskeste av de fire algoritmene både til signering og verifisering, noe benchmarktallene lenger ned dokumenterer med god margin. Ulempen er strukturell: enhver part som kan verifisere et token, kan også signere nye tokens, siden det er samme nøkkel. Det gjør HS256 uegnet i systemer der utsteder og forbruker er separate tjenester eid av ulike team eller ulike selskaper, fordi du da må dele en hemmelighet som begge parter kan misbruke.
HS256 krever i tillegg en sterk, tilfeldig generert hemmelighet på minst 256 bit. Auth0 har dokumentert i egen forskning at svake eller forutsigbare HS256-hemmeligheter kan brute-forces offline, noe som har vært en reell årsak til kontoovertakelser i produksjonssystemer.
I praksis passer HS256 best i monolittiske applikasjoner eller i mikrotjeneste-arkitekturer der alle tjenestene eies av samme team og kjører bak samme brannmur. Sesjonshåndtering i en enkelt Node.js- eller Django-backend, interne administrasjonspaneler, og batch-jobber som signerer korte, kortlevde tokens for intern kommunikasjon er klassiske eksempler. Så snart en ekstern part, en mobilapp utenfor din kontroll, eller en tredjeparts mikrotjeneste skal verifisere tokenet uten å kunne signere nye selv, blir HS256 feil verktøy uansett hvor rask den er.
RS256 forklart: RSA og offentlig/privat nøkkelpar
RS256 bruker RSASSA-PKCS1-v1_5 med SHA-256 og et asymmetrisk RSA-nøkkelpar, normalt på minst 2048 bit. Den private nøkkelen signerer tokenet, mens den offentlige nøkkelen, som kan distribueres fritt via et JWKS-endepunkt (JSON Web Key Set), brukes til å verifisere signaturen. Dette løser problemet HS256 har: mange forskjellige tjenester kan verifisere tokens uten noensinne å få tilgang til nøkkelen som faktisk kan lage nye.
Prisen for denne fleksibiliteten er størrelse og hastighet. En RS256-signatur med en 2048-bit nøkkel er 256 byte, åtte ganger større enn HS256, og RSA-signering er beregningstungt sammenlignet med HMAC. Verifisering av RSA-signaturer er derimot relativt rask, noe som gjør RS256 til et fornuftig valg når ett system signerer sjelden (for eksempel en identitetsleverandør som utsteder tokens) mens svært mange klienter verifiserer ofte.
Dette mønsteret forklarer hvorfor RS256 fortsatt er standardvalget hos store identitetsplattformer. Auth0 bruker RS256 som standard signeringsalgoritme for de fleste OIDC-kompatible applikasjoner, og både AWS Cognito og Firebase/Google utsteder RS256-signerte ID-tokens som verifiseres mot offentlig tilgjengelige JWKS-nøkler.
Nøkkelrotasjon er den operasjonelle utfordringen som følger med RS256 i praksis. Fordi den private nøkkelen aldri skal forlate utstederens systemer, må rotasjon skje gjennom et JWKS-endepunkt der flere nøkler publiseres samtidig, identifisert med hver sin kid-verdi, slik at gamle tokens fortsatt kan verifiseres mens nye signeres med den ferske nøkkelen. Dette krever mer infrastruktur enn HS256, der rotasjon i prinsippet bare er å bytte ut en hemmelighet i en secrets manager, men gevinsten er at kompromittering av en enkelt forbrukertjeneste aldri kan brukes til å forfalske nye tokens, siden forbrukeren kun har den offentlige nøkkelen.
ES256 forklart: elliptisk kurve-kryptografi for JWT
ES256 bruker ECDSA (Elliptic Curve Digital Signature Algorithm) over NIST-kurven P-256, kombinert med SHA-256. Som RS256 er dette en asymmetrisk algoritme med separat privat og offentlig nøkkel, men den elliptiske kurve-matematikken gir samme sikkerhetsnivå som RSA-2048 med langt mindre nøkler og signaturer.
En ES256-signatur i JWS-format består av to 32-byte heltall, r og s, satt sammen til totalt 64 byte, fire ganger mindre enn RS256. RFC 7518 klassifiserer ES256 som “Recommended+”, den høyeste anbefalingskategorien IETF bruker for JWA-algoritmer. Det praktiske resultatet er tokens som er betydelig kortere når de Base64URL-kodes og sendes i HTTP-headere, noe som teller når header-budsjettet ligger rundt 8 kB og hvert token følger med på hver eneste forespørsel.
Ulempen er implementasjonskompleksitet. ECDSA er mer følsom for feil i implementasjonen enn RSA, spesielt rundt generering av tilfeldige nonce-verdier under signering, noe som historisk har ført til nøkkellekkasjer i dårlig implementerte biblioteker. Godt vedlikeholdte JWT-biblioteker håndterer dette korrekt i dag, men det er en grunn til at enkelte konservative miljøer fortsatt foretrekker RSA.
Til tross for denne historiske bekymringen er ES256 i dag godt utprøvd i produksjonsmiljøer med enorm skala. Moderne kryptografibiblioteker som håndterer nonce-generering deterministisk eller via sikre tilfeldighetskilder i operativsystemet, har lukket de fleste av svakhetene som plaget tidlige implementasjoner. Det gjenstående argumentet for RSA fremfor ECDSA handler i dag mer om organisatorisk treghet og eksisterende sertifiseringskrav enn om reell teknisk risiko.
P-256-kurven ES256 bygger på er en NIST-standardisert kurve fra FIPS 186, og den er også godkjent under CNSA-regelverket for føderale amerikanske systemer, noe som gjør ES256 til et trygt valg i regulerte bransjer som bank og offentlig forvaltning. Samtidig peker den pågående overgangen til postkvante-kryptografi mot at rene elliptisk kurve-algoritmer på sikt må erstattes eller kombineres med kvanteresistente signaturer for de mest langsiktige bruksområdene, selv om dette foreløpig ikke er en praktisk bekymring for et JWT med levetid på minutter eller timer.
EdDSA og Ed25519: den nyeste utfordreren
EdDSA med Ed25519-kurven er standardisert for JOSE/JWT i RFC 8037 og har de siste årene gått fra nisjevalg til anbefalt standard i flere sikkerhetsveiledninger. Signaturen er, som ES256, 64 byte, men den underliggende kurve-konstruksjonen unngår flere av fallgruvene som gjør ECDSA-implementasjoner sårbare, blant annet ved at Ed25519 er deterministisk og ikke er avhengig av en tilfeldig nonce for hver signering.
Sikkerhetsveiledningen fra Curity peker på EdDSA som algoritmen med best kombinasjon av sikkerhet og ytelse blant de fire, med ES256 som godt alternativ der EdDSA ikke støttes, for eksempel i enkelte FIPS-sertifiserte miljøer. En egen 2026-veiledning for JWT-praksis anbefaler eksplisitt EdDSA som standardvalg for nye systemer, med ES256 som reserveløsning i maskinvare- eller FIPS-begrensede miljøer.
Svakheten er økosystemstøtte. Ikke alle eldre JWT-biblioteker og identitetsleverandører støtter EdDSA ennå, og store OIDC-klienter forventer fortsatt RS256 som laveste fellesnevner. For nye, interne systemer uten legacy-krav er EdDSA likevel verdt en alvorlig vurdering.
Adopsjonen beveger seg likevel raskt. Populære JavaScript-biblioteker som jose og etablerte Python- og PHP-biblioteker har lagt til full EdDSA-støtte de siste par årene, og flere nyere identitetsplattformer tilbyr EdDSA som alternativ ved siden av RS256. For team som starter et helt nytt system i 2026, uten en eksisterende brukerbase av eldre klienter å ta hensyn til, er mangelen på universell støtte i stadig mindre grad et reelt hinder.
Spesifikasjonstabell: HS256, RS256, ES256 og EdDSA side om side
Tabellen under samler nøkkeltallene fra RFC 7518, RFC 8037 og publiserte biblioteksdokumentasjoner for de fire algoritmene. Legg spesielt merke til forholdet mellom signaturstørrelse og hvor mange verifiserende parter algoritmen egner seg for, det er dette forholdet som i praksis avgjør valget for de fleste systemer, mer enn de rene ytelsestallene lenger ned i artikkelen.
| Egenskap | HS256 | RS256 | ES256 | EdDSA (Ed25519) |
|---|---|---|---|---|
| Type | Symmetrisk (HMAC) | Asymmetrisk (RSA) | Asymmetrisk (ECDSA) | Asymmetrisk (EdDSA) |
| Hash-funksjon | SHA-256 | SHA-256 | SHA-256 | SHA-512 (internt) |
| Nøkkelstørrelse | ≥256 bit hemmelighet | ≥2048 bit RSA | 256 bit (P-256) | 256 bit (32 byte) |
| Signaturstørrelse | 32 byte | 256 byte (RSA-2048) | 64 byte | 64 byte |
| Base64URL-lengde signatur | ~43 tegn | ~342 tegn | ~86 tegn | ~86 tegn |
| IETF-anbefaling (RFC 7518) | Required | Recommended | Recommended+ | Definert i RFC 8037 |
| Nøkkeldeling nødvendig | Ja (samme nøkkel begge veier) | Nei (offentlig nøkkel) | Nei (offentlig nøkkel) | Nei (offentlig nøkkel) |
| Egnet for flere verifiserende parter | Nei | Ja | Ja | Ja |
| Implementasjonsrisiko | Lav (men avhengig av nøkkelstyrke) | Lav-moderat | Moderat (nonce-håndtering) | Lav |
| Typisk bruksområde | Intern mikrotjeneste | OIDC, offentlige API-er | Mobil, SPA, IoT | Nye systemer, edge |
| Standardvalg hos | Enkelte interne systemer | Auth0, AWS Cognito, Firebase | Enkelte moderne API-er | Voksende adopsjon 2025-2026 |
Ytelsesbenchmarks: hvor mye raskere er HS256 egentlig
Tallene under kommer fra tre uavhengige, offentlig publiserte benchmarker, slik at du ikke trenger å stole på én enkelt kildes metodikk. Det viktigste å merke seg er hvor stor spennet er mellom algoritmene, og at rekkefølgen ikke alltid er den samme mellom signering og verifisering.
Den mest detaljerte offentlige benchmarken kommer fra en GitHub-issue i Auth0s node-jsonwebtoken-bibliotek, som sammenligner versjon 8.5.1 mot 9.0.2. I versjon 8.5.1 målte biblioteket følgende gjennomstrømning for signering: HS256 klarte 120 423 operasjoner per sekund, ES256 klarte 2 418 operasjoner per sekund, og RS256 klarte kun 793 operasjoner per sekund. Det gir HS256 en fordel på rundt 152 ganger over RS256 til signering. For verifisering var tallene 87 990 operasjoner per sekund for HS256, 5 921 for RS256 og 4 763 for ES256, en fordel på nesten 15 ganger for HS256 over RS256.
En separat benchmark fra PHP-biblioteket web-token måler tid per operasjon i mikrosekunder for HS256 og EdDSA direkte. HS256 signerer på 19,593 mikrosekunder (rundt 51 000 operasjoner per sekund) og verifiserer på 24,045 mikrosekunder (rundt 41 600 operasjoner per sekund). EdDSA (Ed25519) bruker 139,323 mikrosekunder til signering (rundt 7 180 operasjoner per sekund) og 169,125 mikrosekunder til verifisering (rundt 5 910 operasjoner per sekund). Det gir HS256 en fordel på omtrent 7 ganger over EdDSA i dette biblioteket, en helt annen skala enn forskjellen mot RS256, men fortsatt betydelig.
| Kilde | Algoritme | Signering (ops/s) | Verifisering (ops/s) |
|---|---|---|---|
| node-jsonwebtoken 8.5.1 (GitHub) | HS256 | 120 423 | 87 990 |
| node-jsonwebtoken 8.5.1 (GitHub) | RS256 | 793 | 5 921 |
| node-jsonwebtoken 8.5.1 (GitHub) | ES256 | 2 418 | 4 763 |
| web-token/jwt-doc (PHP) | HS256 | ~51 000 | ~41 600 |
| web-token/jwt-doc (PHP) | EdDSA | ~7 180 | ~5 910 |
Tredje kilde er en samlet analyse fra Curity som bekrefter det kvalitative mønsteret på tvers av flere JWT-biblioteker: HMAC-baserte algoritmer er raskest, RSA er tregest særlig til signering, og elliptisk kurve-kryptografi (ES256 og EdDSA) ligger et sted i midten, men med langt mindre signaturer enn RSA. Konklusjonen som går igjen på tvers av alle tre kildene er at algoritmevalget i praksis handler mer om nøkkelhåndtering og sikkerhetsmodell enn om rå CPU-fart, siden selv den tregeste algoritmen (RS256) verifiserer flere tusen ganger i sekundet på moderne maskinvare.
Et viktig forbehold: absolutte ops/sekund-tall er sterkt avhengige av maskinvare, biblioteksversjon og om implementasjonen bruker native kryptografiske biblioteker (som OpenSSL under panseret) eller rene JavaScript/Python-implementasjoner. Selve node-jsonwebtoken-issuen som ligger til grunn for hovedbenchmarken over dokumenterer nettopp dette: mellom versjon 8.5.1 og 9.0.2 av samme bibliotek falt encoding-hastigheten med en faktor på over 50 på grunn av interne endringer i avhengigheter, uten at selve den kryptografiske sikkerheten endret seg. Bruk derfor de relative forholdstallene mellom algoritmer, ikke de absolutte ops/sekund-tallene, som rettesnor når du dimensjonerer egen infrastruktur, og kjør gjerne egne benchmarks på din produksjonslignende maskinvare før du tar en endelig beslutning.
Signaturstørrelse og token-vekt i praksis
Et token sendes med på nesten hver eneste API-forespørsel en autentisert bruker gjør, ofte i en Authorization-header. Det betyr at signaturstørrelsen ikke bare er et akademisk tall, den er faktisk nettverkstrafikk som gjentas millioner av ganger daglig i et system med mye trafikk.
Med en typisk payload på noen hundre byte, legger en RS256-signatur på 256 byte til rundt 342 Base64URL-tegn i selve token-strengen. ES256 og EdDSA legger til rundt 86 tegn hver, mens HS256 legger til rundt 43 tegn. Forskjellen mellom RS256 og ES256 alene er om lag 250 byte per token, noe en 2026-teknisk gjennomgang av JWT-strukturer peker på som meningsfullt når header-budsjetter typisk ligger rundt 8 kB per forespørsel og systemet håndterer høy samtidighet.
For mobilapplikasjoner på ustabile mobilnett, eller for IoT-enheter med begrenset båndbredde, er denne forskjellen ikke marginal. Et system som sender titalls millioner autentiserte forespørsler daglig, sparer flere gigabyte total nettverkstrafikk per måned ved å bytte fra RS256 til ES256 eller EdDSA, uten å svekke sikkerhetsnivået.
Regn på et konkret eksempel: en nordisk SaaS-tjeneste med 2 millioner daglig aktive brukere, der hver bruker i snitt gjør 50 autentiserte API-kall per dag, sender 100 millioner tokens daglig. Forskjellen i signaturlengde mellom RS256 (~342 Base64URL-tegn) og ES256/EdDSA (~86 tegn) er 256 tegn per token. Ganget med 100 millioner tokens blir det rundt 25,6 gigabyte ekstra trafikk per dag bare fra selve signaturdelen, om lag 768 gigabyte over en måned, trafikk som må transporteres, mellomlagres i CDN-lag og prosesseres av lastbalanserere uansett hvor liten den enkelte forskjellen virker per token.
Driftskostnad ved skala: hva koster signering i skyen
For å gjøre ytelsesforskjellene konkrete har vi regnet om benchmarktallene fra node-jsonwebtoken til faktisk AWS Lambda-kostnad. AWS Lambda koster 0,0000166667 dollar per GB-sekund for x86-arkitektur, pluss 0,20 dollar per million forespørsler, samme sats globalt inkludert eu-north-1 (Stockholm). Beregningen under forutsetter en 128 MB Lambda-funksjon som verifiserer 100 millioner tokens.
| Algoritme | Beregnet CPU-tid per verifisering | Beregningskostnad per 100M verifiseringer | Forespørselskostnad | Totalt per 100M |
|---|---|---|---|---|
| HS256 | 0,0114 ms | $2,37 | $20,00 | $22,37 |
| RS256 | 0,1689 ms | $35,19 | $20,00 | $55,19 |
| ES256 | 0,2100 ms | $43,74 | $20,00 | $63,74 |
Beregningen, basert på ops/sekund-tallene fra node-jsonwebtoken 8.5.1 og AWS’ offentlige Lambda-prisliste, viser at RS256 koster om lag 2,5 ganger mer i ren beregningstid enn HS256 ved 100 millioner verifiseringer, og ES256 enda litt mer i dette konkrete biblioteket og denne konfigurasjonen. Forespørselskostnaden, 20 dollar per 100 millioner kall, er lik uavhengig av algoritme og dominerer ofte totalregningen ved lavere volum. Det praktiske poenget er at kompute-forskjellen sjelden er den avgjørende kostnadsfaktoren alene, den avgjørende faktoren er som regel driftskostnaden ved å håndtere nøkkelrotasjon, HSM-er eller KMS-tjenester for asymmetriske nøkler, en kostnad HS256 slipper helt fordi det kun krever en hemmelighet lagret i en secrets manager.
Sikkerhetssårbarheter: alg:none-angrepet og nøkkelforvirring
Nesten alle alvorlige JWT-sårbarheter de siste ti årene skyldes ikke svakheter i selve matematikken bak HS256, RS256 eller ES256, men feil i hvordan biblioteker og applikasjoner implementerer algoritme-valget. To angrepsmønstre går igjen.
Det første er alg:none-angrepet. JWT-spesifikasjonen tillater i teorien “none” som algoritmeverdi for usignerte tokens i kontrollerte miljøer. Biblioteker som stoler blindt på algoritm-feltet i tokenets header, uten å sjekke det mot en tillatt liste på server-siden, kan lures til å godta et token der angriperen selv har satt alg til none og fjernet signaturen. Det opprinnelige og mest kjente tilfellet er CVE-2015-9235 i Node.js-biblioteket jsonwebtoken, med en CVSS-score på 9,8. Mønsteret lever fortsatt: CVE-2026-27804 i Parse Server tillot i 2026 en uautentisert angriper å forfalske Google-autentiseringstokens ved å sette alg til none, og CVE-2026-28802 i Python-biblioteket Authlib (CVSS 7,7) hadde et tilsvarende problem med tom signatur og none-algoritme.
Det andre mønsteret er algoritme-forvirring, oftest omtalt som RS256-til-HS256-angrepet. Hvis en tjener er satt opp til å verifisere med den offentlige RSA-nøkkelen, og samtidig stoler på algoritmen angitt i token-headeren, kan en angriper signere et falskt token med HS256 og bruke den offentlige RSA-nøkkelen (som er offentlig tilgjengelig per design) som HMAC-hemmelighet. Hvis serveren ukritisk bytter til HMAC-verifisering fordi headeren sier HS256, går angrepet gjennom. To ferske CVE-er illustrerer alvoret: CVE-2025-4692 i python-jose (versjoner til og med 3.3.0) fikk en kritisk CVSS-score på 9,1 og muliggjorde full kontoovertakelse, mens CVE-2025-27371 i golang-jwt/jwt v4 (CVSS 8,5) ga rettighetseskalering.
| CVE | Bibliotek/produkt | Angrepstype | CVSS |
|---|---|---|---|
| CVE-2015-9235 | jsonwebtoken (Node.js) | alg:none | 9,8 |
| CVE-2025-4692 | python-jose ≤3.3.0 | RS256→HS256-forvirring | 9,1 |
| CVE-2025-27371 | golang-jwt/jwt v4 | Algoritme-forvirring | 8,5 |
| CVE-2026-28802 | Authlib (Python) | alg:none-bypass | 7,7 |
| CVE-2026-27804 | Parse Server | alg:none (Google-auth) | Ikke oppgitt |
OWASPs egen testveiledning for JSON Web Tokens er tydelig på hovedforsvaret: server-siden må aldri stole på algoritmen angitt i tokenets header, og må i stedet håndheve en eksplisitt tillatt-liste av algoritmer per endepunkt eller nøkkel. Dette forsvaret er identisk uavhengig av om du bruker HS256, RS256, ES256 eller EdDSA, sårbarheten ligger i valideringslogikken, ikke i selve kryptografien.
Utover de to hovedmønstrene finnes flere beslektede angrep verdt å kjenne til. Header-feltene jku og x5u peker eksternt til hvor tjeneren kan hente den offentlige nøkkelen for verifisering, og dersom applikasjonen henter nøkler fra en URL uten å validere at domenet faktisk tilhører den forventede utstederen, kan en angriper peke til sin egen nøkkel og signere gyldige falske tokens. Kid-feltet, som identifiserer hvilken nøkkel som skal brukes blant flere publiserte, er i enkelte implementasjoner blitt brukt som direkte inndata til et databasekall eller filoppslag uten sanitering, noe sikkerhetsmiljøer har dokumentert som en vei til SQL-injeksjon eller katalogtraversering. Ingen av disse svakhetene er iboende i selve HS256, RS256 eller ES256, de oppstår når applikasjonskoden stoler for mye på ukontrollert inndata fra tokenets egen header.
Hvem bruker hva: Auth0, AWS Cognito, Firebase og flere
Praksisen hos de store identitetsleverandørene gir et godt bilde av hvordan bransjen faktisk vekter avveiningene. Auth0s egen dokumentasjon er eksplisitt: RS256 er standard signeringsalgoritme for de fleste OIDC-kompatible applikasjoner, med anbefaling om å bruke RS256 fremfor HS256 nettopp fordi Auth0 da er eneste part med den private nøkkelen, mens klienter kun trenger den offentlige.
AWS Cognito signerer ID- og access-tokens med RS256 og en 2048-bit RSA-nøkkel, der forbrukere av tokenet henter offentlige nøkler fra Cognitos JWKS-endepunkt identifisert via en kid-verdi i token-headeren. Google og Firebase følger samme mønster for sine ID-tokens: RS256-signerte JWT-er verifisert mot Googles offentlig publiserte nøkkelsett. Dette er ikke tilfeldig, det er den naturlige konsekvensen av at én utsteder må la svært mange uavhengige klienter verifisere tokens uten noensinne å kunne signere nye selv.
Samtidig illustrerer sårbarhetene over hva som skjer når dette mønsteret implementeres feil i praksis. CVE-2025-4692 i python-jose rammet reelle produksjonssystemer som stolte på biblioteket for RS256-verifisering, og CVE-2026-27804 i Parse Server rammet konkret integrasjoner mot Google-autentisering. Det er ikke identitetsleverandørens algoritmevalg som var problemet i disse tilfellene, det var forbrukerbibliotekets manglende validering av algoritme-feltet.
Okta, som stor OIDC-leverandør i bedriftsmarkedet, følger samme etablerte mønster som Auth0, AWS Cognito og Firebase: ID-tokens og access-tokens signeres asymmetrisk og verifiseres av forbrukertjenester mot et offentlig publisert nøkkelsett, i tråd med generell OIDC-interoperabilitet. Det gjennomgående bildet på tvers av de store identitetsplattformene er at ingen av dem lar forbrukertjenester dele en symmetrisk hemmelighet med utstederen, nettopp fordi det ville brutt sikkerhetsmodellen der én utsteder betjener tusenvis av uavhengige klientapplikasjoner. HS256 dukker i stedet opp lenger inn i arkitekturen, i de interne tjenestene som konsumerer og re-signerer tokens for egne formål, aldri i grensesnittet mot sluttbrukeren.
Bruksområder: hvilken algoritme passer ditt scenario
- Intern mikrotjeneste i samme klareringsdomene: HS256 er tilstrekkelig og raskest når samme team eller system både utsteder og verifiserer tokens, og en delt hemmelighet ikke er et sikkerhetsproblem.
- Offentlig API med mange tredjepartsklienter: RS256 er fortsatt det tryggeste valget for interoperabilitet, siden nesten alle OIDC-biblioteker og identitetsplattformer støtter det uten videre konfigurasjon.
- Mobilapp eller SPA med båndbreddebudsjett: ES256 gir samme sikkerhetsnivå som RS256-2048 med en fjerdedel av signaturstørrelsen, verdifullt på ustabile mobilnett.
- Nytt system uten legacy-krav: EdDSA (Ed25519) anbefales som standardvalg i flere 2025-2026-veiledninger, med best kombinasjon av sikkerhet, ytelse og implementasjonsrobusthet.
- Regulert miljø med FIPS-krav (offentlig sektor, finans): ES256 er ofte riktig når EdDSA ikke er sertifisert i miljøet, men RSA vurderes for tregt eller for stort.
- Høyfrekvent verifisering i serverless eller edge-funksjoner: HS256 eller EdDSA gir lavest CPU-kostnad per kall, noe som er direkte synlig i skyregningen ved høyt volum, som vist i kostnadsberegningen over.
- Mikrotjenestearkitektur med sentral autentiseringstjeneste: RS256 eller ES256 lar én sentral tjeneste signere, mens et vilkårlig antall interne mikrotjenester verifiserer uavhengig av hverandre, uten at noen av dem kan utstede nye tokens ved en feil eller et sikkerhetsbrudd.
- Partner- eller B2B-integrasjon der en ekstern part skal verifisere dine tokens: RS256 er tryggeste standardvalg her, fordi det er den algoritmen som er mest sannsynlig allerede støttet i partnerens eksisterende JWT-biblioteker uten ekstra tilpasning.
Migreringsguide: fra HS256 til RS256 eller ES256 uten nedetid
Å bytte signeringsalgoritme i et system i produksjon krever en gradvis overgang, siden gamle tokens som allerede er utstedt med HS256 fortsatt må kunne verifiseres mens nye utstedes med den nye algoritmen.
Steg 1: Generer nøkkelpar. Lag en RSA- eller EC-privat/offentlig nøkkel og lagre den private nøkkelen i en secrets manager eller KMS-tjeneste, ikke i kildekoden.
openssl ecparam -genkey -name prime256v1 -noout -out es256-private.pem
openssl ec -in es256-private.pem -pubout -out es256-public.pem
Steg 2: Publiser et JWKS-endepunkt. Eksponer den offentlige nøkkelen med en unik kid-verdi, slik at forbrukere kan hente riktig nøkkel dynamisk uten hardkoding.
Steg 3: Aktiver dobbel algoritmestøtte i verifiseringslogikken. Server-siden må håndheve en eksplisitt tillatt-liste, og den listen skal midlertidig inneholde både gammel og ny algoritme. Denne listen bør aldri bygges dynamisk ut fra hva klienten sender, den skal være en fast, hardkodet konfigurasjonsverdi som kun endres bevisst av deg som utvikler.
const jwt = require('jsonwebtoken');
// Verifiser mot en eksplisitt tillatt-liste, aldri mot header-verdien alene
jwt.verify(token, getKeyForKid, {
algorithms: ['HS256', 'ES256'] // fjern HS256 når migreringen er ferdig
}, (err, decoded) => {
if (err) return handleAuthError(err);
return decoded;
});
Steg 4: Flytt utstedelse til ny algoritme. Sett signeringstjenesten til å bruke den nye private nøkkelen for alle nye tokens, mens verifisering fortsatt aksepterer begge algoritmer.
Steg 5: Vent ut levetiden til gamle tokens. Når det lengste gyldige HS256-tokenet har utløpt (typisk definert av refresh-token-levetiden), kan HS256 fjernes fra tillatt-listen.
Steg 6: Overvåk og rull tilbake ved behov. Logg hvilken algoritme hvert innkommende token faktisk bruker under overgangen, slik at du kan bekrefte at andelen gamle tokens synker mot null før du fjerner støtten helt.
For team som migrerer til EdDSA i stedet for ES256, er fremgangsmåten identisk, kun nøkkelgenereringen skiller seg fra RSA og ECDSA. Med moderne biblioteker som jose i Node.js-økosystemet er nøkkelgenerering og signering rett frem:
import { generateKeyPair, SignJWT } from 'jose';
const { publicKey, privateKey } = await generateKeyPair('EdDSA');
const token = await new SignJWT({ sub: 'bruker-123' })
.setProtectedHeader({ alg: 'EdDSA', kid: 'edd-2026-01' })
.setIssuedAt()
.setExpirationTime('15m')
.sign(privateKey);
Steg 7: Test rollback-planen før produksjonssetting. Verifiser i et test- eller staging-miljø at du faktisk kan reversere til utelukkende gammel algoritme dersom noe går galt, før du ruller endringen ut til produksjon. En migrering uten testet reverseringsvei er den vanligste årsaken til at team utsetter algoritmebytte i årevis, selv når de vet at det er riktig retning å gå.
Fordeler og ulemper
| Algoritme | Fordeler | Ulemper |
|---|---|---|
| HS256 | Raskest, minst signatur, enkel nøkkelhåndtering | Delt hemmelighet, uegnet for mange verifiserende parter |
| RS256 | Bred økosystemstøtte, moden implementasjon, rask verifisering | Tregest til signering, størst signatur (256 byte) |
| ES256 | Liten signatur, god sikkerhet/ytelse-balanse, IETF “Recommended+” | Mer implementasjonssensitiv (nonce-håndtering) |
| EdDSA (Ed25519) | Deterministisk, robust mot implementasjonsfeil, liten signatur | Mindre moden økosystemstøtte enn RS256/ES256 |
Verdikt: hvilken algoritme bør du velge i 2026
Det finnes ikke én riktig algoritme, men tallene peker på en klar arbeidsfordeling. Hvis utsteder og forbruker av tokenet er samme system, velg HS256: den er 152 ganger raskere til signering enn RS256 i node-jsonwebtoken-benchmarken, produserer det minste tokenet, og krever kun en hemmelighet i en secrets manager. Hvis du bygger mot et økosystem av tredjepartsklienter og trenger maksimal kompatibilitet, er RS256 fortsatt tryggest, det er standarden hos Auth0, AWS Cognito og Firebase, selv om det koster mest i ren CPU-tid og størst i signaturbyte.
For nye systemer uten legacy-krav peker både benchmarktall og sikkerhetsveiledninger fra Curity og flere 2026-beste praksis-dokumenter mot EdDSA (Ed25519) som det mest fremtidsrettede valget: 64-byte signaturer, deterministisk oppførsel som fjerner en hel klasse implementasjonsfeil, og god ytelse selv om den ikke slår HS256 i rå fart. ES256 forblir det solide mellomvalget der EdDSA ikke er tilgjengelig, med fire ganger mindre signatur enn RS256 og IETFs høyeste anbefalingsgrad. Uansett hvilken algoritme du velger, viser CVE-listen over at den faktiske risikoen sjelden ligger i matematikken, den ligger i om verifiseringskoden din håndhever en eksplisitt tillatt-liste av algoritmer og aldri stoler blindt på tokenets egen header.
Som en enkel beslutningsregel: spør først om utsteder og forbruker av tokenet er samme system. Er svaret ja, bruk HS256 og spar CPU-tid og kompleksitet. Er svaret nei, spør deretter om du trenger maksimal kompatibilitet med eksisterende OIDC-klienter i dag, eller om du bygger noe nytt uten den begrensningen. Trenger du kompatibilitet nå, bruk RS256, det er veien alle store identitetsplattformer allerede har gått. Bygger du nytt, gå rett til EdDSA eller ES256, og spar deg selv migreringen andre team må gjøre om noen år.
Ofte stilte spørsmål
Er HS256 usikkert sammenlignet med RS256 og ES256?
Nei, HS256 er kryptografisk like solid som de andre når hemmeligheten er sterk (minst 256 bit, tilfeldig generert). Svakheten er ikke matematikken, men at samme nøkkel både signerer og verifiserer, noe som er problematisk kun når flere uavhengige parter må verifisere tokens.
Kan jeg bytte algoritme uten å logge ut alle brukere?
Ja, ved å kjøre begge algoritmene parallelt i verifiseringens tillatt-liste mens gamle tokens utløper naturlig, slik migreringsguiden over beskriver. Ingen brukere trenger å logges ut tvangsmessig.
Hvorfor bruker Auth0, AWS Cognito og Firebase alle RS256 som standard?
Fordi disse plattformene er én utsteder som betjener svært mange uavhengige forbrukere av tokenet. RS256 lar tjenesten holde den private nøkkelen hemmelig mens den offentlige nøkkelen distribueres fritt via JWKS, uten at noen forbruker kan forfalske nye tokens.
Hva er alg:none-angrepet, og er det fortsatt relevant i 2026?
Det er et angrep der en klient setter algoritme-feltet i token-headeren til “none” og fjerner signaturen, i håp om at et sårbart bibliotek godtar tokenet uten verifisering. CVE-2026-27804 og CVE-2026-28802 viser at mønsteret fortsatt dukker opp i nye biblioteker og produkter i 2026, selv om det opprinnelige tilfellet (CVE-2015-9235) er over ti år gammelt.
Er ES256 raskere enn RS256?
Til signering, ja, klart raskere ifølge node-jsonwebtoken-benchmarken. Til verifisering varierer det mellom biblioteker og versjoner, i enkelte tester er RS256 marginalt raskere å verifisere enn ES256, men forskjellen er liten sammenlignet med signeringsgapet.
Bør jeg bruke EdDSA fremfor ES256 i et nytt prosjekt?
Hvis biblioteket og identitetsleverandøren din støtter det fullt ut, ja. Flere 2025-2026-sikkerhetsveiledninger anbefaler EdDSA som standardvalg for nye systemer på grunn av den deterministiske signeringsprosessen. Velg ES256 hvis du trenger bredere kompatibilitet eller opererer i et FIPS-regulert miljø der EdDSA ennå ikke er sertifisert.
Hvordan unngår jeg RS256-til-HS256-forvirringsangrepet?
Håndhev alltid en eksplisitt tillatt-liste av algoritmer i verifiseringskoden, og bruk aldri algoritmen angitt i tokenets egen header til å velge verifiseringsmetode. Dette er det samme forsvaret som mot alg:none, og det er identisk uavhengig av hvilken algoritme du faktisk bruker.
Påvirker algoritmevalget skykostnaden min i praksis?
Ja, målbart ved høyt volum. Beregningen over viser at RS256 koster om lag 2,5 ganger mer i ren Lambda-beregningstid enn HS256 ved 100 millioner verifiseringer, selv om forespørselskostnaden er lik for alle algoritmer. Ved lavt til moderat volum er forskjellen neglisjerbar sammenlignet med andre driftskostnader som nøkkelrotasjon og KMS-bruk.
Kan jeg bruke flere algoritmer samtidig i samme system permanent, ikke bare under migrering?
Ja, det er vanlig i systemer med flere klienttyper, for eksempel RS256 for eksterne partner-API-er og HS256 for interne tjenester i samme system, så lenge hver nøkkel og hvert bruksområde har sin egen eksplisitte tillatt-liste. Poenget er å aldri la ett endepunkt godta flere algoritmer enn det faktisk trenger, siden hver ekstra tillatt algoritme øker angrepsflaten.
Er signaturen i et JWT nok til å holde innholdet hemmelig?
Nei. Signaturalgoritmen, uansett om det er HS256, RS256, ES256 eller EdDSA, beskytter kun integritet og autentisitet, ikke konfidensialitet. Payload-delen er bare Base64URL-kodet og kan leses av alle som fanger opp tokenet. Skal innholdet holdes hemmelig, må du bruke JWE (JSON Web Encryption) i tillegg til signeringen, eller unngå å legge sensitive data i tokenet i utgangspunktet.




