Hvorfor algoritmetilsyn ikke vil virke og hva vi bør gjøre i stedet

Året er 1991 og skolen min har i løpet av sommeren fått mange fine PCer på datarommet. Men, data-læreren min er frustrert, det er allerede langt utpå høsten, og den andre data-læreren på skolen som har ansvaret for å installere anti-virus på maskinene har ikke gjort det. En dag kommer læreren vår til meg og en kamerat og sier “gutta, kan dere gjøre noe for å få satt fart i han andre fyren?”

Joda, det skulle det vel bli en råd med. Så, han låste oss inn på datarommet i en midt-time, og på den tiden gjorde vi et aldri så lite hack. Vi lagde et program som gjorde at etterhvert som man skrev på tastaturet tok det lenger og lenger tid før maskinen oppfattet tastetrykkene. Først var det nesten umerkelig, men når man hadde skrevet 1000 tegn var forsinkelsen ett sekund, og da var det allerede blitt veldig plagsomt. Så erstattet vi et av programmene som maskinen startet automatisk når den ble slått på, og passet på å legge inn mye uvirksom kode som gjorde vårt program tilforlatelig likt det vi erstattet, som ble kjørt etterpå.

I dag ville dette lett blitt oppdaget av anti-virus og “intrusion detection environments”, men datidens anti-virus var avhengig av å kjenne igjen kjente mønstre, og klarte ikke å gjenkjenne programmet vårt, så det ble aldri oppdaget. Men det virket etter sin hensikt, maskinene ble re-installert med anti-virus, og vi fikk en high five fra læreren vår, men meg bekjent er det første gang historien fortelles.

Og grunnen til at jeg forteller den nå er at EU legger opp til et omfattende inspeksjon og revisjons-regime i flere deler av sin lovgivning, og her hjemme har flere gått inn for et algoritmetilsyn for å sørge for at teknologiselskapene følger lovgivningen. Jeg er positiv til tilsynsfunksjoner, men jeg er ganske sikker på at hvis et teknologiselskap prøver å skjule sine svin på skogen, så vil ikke et slikt tilsyn kunne oppdage det.

Eksempel på en algoritme

Det skrives mye om algoritmenes makt, men ofte får jeg på følelsen at mange ikke helt vet hva det er. Det er ikke så vanskelig, vi kjenner alle sammen noen algoritmer, vi lærer dem til og med på barneskolen. Ta for eksempel hvordan man legger sammen to heltall. Vi setter tallene opp over hverandre, ikke sant?

Og så begynner vi bakerst, og legger sammen sifferne på enerplassen. Hvis den resulterende summen er større eller lik 10, deler vi opp tallet, og tar det bakerste sifferet, det blir resultatet på enerplassen, mens 1-tallet først legges sammen med summen av sifferne på tierplassen. Og så gjør vi det samme igjen og igjen helt til det ikke er flere tall igjen å legge sammen.

Så, det er et eksempel på en algoritme vi stadig bruker i hoderegning. For at en datamaskin skal kunne hjelpe oss med utregningen, må dette oversettes til et språk datamaskinen forstår. Nå er det sånn at jobben gjøres av den fysiske prosessoren din, men nå skal vi late som vi må gjøre dette selv. Snart kan det hende språkmodeller kan gjøre denne jobben også, men foreløpig lar vi det gå igjennom noen skritt, der vi skal se på det første. Det er mange programmeringsspråk å velge mellom, men jeg skal bruke JavaScript, fordi det kjører i alle nettlesere.

En ærlig heltallskalkulator

Her er det en enkel kalkulator. Den tar bare heltall og kan bare plusse to tall, men den bruker en implementasjon av algoritmen vår:


+
=

Bare prøv den! Se at den funker! La oss se på den faktiske koden som kjører i dette tilfellet. Hvis du ikke er vant til å se på kode, er det helt greit, jeg skal forklare under.

function run1()
{
	var ledd1 = document.getElementById("f1part1").value;
	var ledd2 = document.getElementById("f1part2").value

	var alle_siffer1 = ledd1.split('');
	var alle_siffer2 = ledd2.split('');

	var resultat;

	var siste1 = parseInt(alle_siffer1.pop());
	var siste2 = parseInt(alle_siffer2.pop());

	while ((! isNaN(siste1)) || (! isNaN(siste2))) {
    	if (isNaN(siste1)) {
        	siste1 = 0
    	}	
    	if (isNaN(siste2)) {
        	siste2 = 0
    	}
    	var del_resultat = siste1 + siste2;
    	siste1 = parseInt(alle_siffer1.pop());
    	siste2 = parseInt(alle_siffer2.pop());
    	if (del_resultat >= 10) {
        	del_resultat = del_resultat.toString().split('').pop();
        	siste1 = isNaN(siste1) ? 1 : siste1 + 1;
    	}

	    resultat = [del_resultat, resultat].join('');

	}
    
	document.getElementById("f1answer").value = resultat;
}

Altså, alt er i en funksjon som kjøres når du trykker “regn ut”. Linje 3 og 4 henter teksten (formodentlig tall) du har skrevet inn, og gir dem et navn. Linje 6 og 7 deler dem opp. Linje 9 gjør bare klar for å ta vare på resultatet. Linje 11 og 12 er den egentlige starten på algoritmen vår, der tar vi det siste tegnet fra teksten du skrev inn og gjør dem om til et ordentlig heltall, ikke bare en tekst. Og så begynner vi på runden i linje 14, altså “så lenge det finnes noe som ikke er ikke et tall på en av leddene…”. Det er nå man må holde tunga rett i munnen. I linjene 15-20 sjekkes det om vi har et tall. Hvorfor må vi gjøre det? Jo, fordi tallene du skrev inn kan ha forskjellige lengde (og ja, ting kan gå veldig galt her). Og så legger vi sammen de to sifferene i linje 21, før vi igjen i 22 og 23 gjør om neste tegn til et tall. Linjene 24-26 passer på at vi får med tier-overgangen. Linje 29 lager igjen en tekst av resultatet, og linje 33 sender det tilbake til skjemaet over.

OK, så vi ser at det var ganske mye mer involvert i å implementere algoritmen enn å skrive den på prosa. Mye mer tunga rett i munnen, og mange flere steder man kan gjøre feil. Nå vil man jo ikke skrive akkurat denne algoritmen i praktisk bruk, men man må passe på mulige feilsituasjoner. Man må også ta høyde for om brukeren er dum eller slem, og skriver bokstaver i stedet for tall. Koden over gjør ikke den delen av jobben. Og det er koden som kjører, ikke algoritmen som skrives kan skrivers på prosa. Så, det er hovedsakelig koden det må føres tilsyn med, ikke bare algoritmen.

Legg til en dæsj ondskap

OK, så hva om vi gjør dette:

function run2()
{
	var ledd1 = document.getElementById("f2part1").value;
	var ledd2 = document.getElementById("f2part2").value

	var alle_siffer1 = ledd1.split('');
	var alle_siffer2 = ledd2.split('');

	var resultat;

	var siste1 = parseInt(alle_siffer1.pop());
	var siste2 = parseInt(alle_siffer2.pop());

	while ((! isNaN(siste1)) || (! isNaN(siste2))) {
    	if (isNaN(siste1)) {
        	siste1 = 0
    	}	
    	if (isNaN(siste2)) {
        	siste2 = 0
    	}
    	var del_resultat = siste1 + siste2;
    	siste1 = parseInt(alle_siffer1.pop());
    	siste2 = parseInt(alle_siffer2.pop());
    	if (del_resultat >= 10) {
        	del_resultat = del_resultat.toString().split('').pop();
        	siste1 = isNaN(siste1) ? 1 : siste1 + 1;
    	}

	    resultat = [del_resultat, resultat].join('');
		if (resultat == '42') {
			resultat = 17;
		}
	}
    
	document.getElementById("f2answer").value = resultat;
}

Hva har skjedd her, sånn bortsett fra at noen navn har fått tallet 2 der det forrige eksemplet hadde 1? Jo, se på linje 30-32. Jeg har lagt inn kode som gjør at når svaret skulle vært 42, så blir det 17 i stedet. Bare prøv det selv, legg inn noe som blir 42 til sammen:


+
=

Den som skriver koden har makta! Man kan manipulere brukeren på alle måter, man kan underminere brukerens tillit (denne koden kjører faktisk på din enhet), og man kan manipulere andre som vekselvirker med et system. Det er helt avgjørende å forstå hva man kan stole på og hva man ikke kan stole på.

Det blir egentlig bare verre. Prøv å la et av tallene du skriver inn ha et 7-tall i seg. Hva skjedde nå? Jo, hver eneste linje i programmene du ser kan gis en annen mening enn du forventer. I dette tilfellet har jeg overstyrt funksjonen som konverterer tegnene du skriver inn til heltall, og gjort at den trekker fra litt… Jeg introduserte altså en systematisk feil.

Systematiske feil lagt inn med vilje

Det er varierende hvor lett det er så skjule slik ondskap. I JavaScript er det faktisk ikke så lett, men det kan være gode grunner til at det kan være lett. Mekanismer for å skjule slike ting kan også gjøre koden mer lesbar.

I 1984 fikk Ken Thompson Turing-prisen, “informatikkens nobelpris”. I sitt foredrag presenterte han en kort artikkel med tittel “Reflections on Trusting Trust”. Det er en artikkel man kan brekke hjernen sin på, og jeg har ikke forstått detaljene, men han viser en teknikk for å skjule en bakdør inn i kode som er veldig, veldig vanskelig å oppdage. I koden over, er alt helt oppi dagen, jo dypere man kommer, jo vanskeligere er det å oppdage. Det vil ikke være vanskelig å lage en bakdør som kun et lite antall i selskapet kjenner til hvis man har et stort system.

Siden Thompons artikkel har man utviklet en rekke teknikker for å verifisere at koden ikke gjør skumle ting, men spørsmålet er om det holder. Angrepsformen er også modernisert til å gjelde moderne maskinlæring.

Jeg skal innrømme at dette ikke er helt mitt felt, men når man først tenker som meg, så tenker man alltid på mulige angrep. Vi må skille mellom situasjonen der de som skaper teknologien er snille og angriperne kommer utenfra, fra situasjonen der selskapet som skaper teknologien er den som prøver å føre folk bak lyset. Spesielt når det er en mer ressurssterk organisasjon som har langt dypere kunnskap om systemet. Jeg tror vi skal klare å håndtere den første situasjonen og få tilstrekkelig sikkerhet der. Men i de siste tilfellet tror jeg ikke tilsynsmyndighetene kommer til å ha særlig stor suksess.

Volkswagens Dieselgate

Vi har vært borti en slik situasjon for litt siden. Allerede i 2011 oppdaget EU at Volkswagens dieselbiler hadde altfor store emisjoner, og advarte mot “defeat devices”, altså systemer som kunne lure testen som ble brukt til å måle avgassene. Etter at flere hadde sett det samme, slo både europeiske og amerikanske myndigheter det fast i 2015 at det fantes systemer i bilene som lurte testen. Først i 2017 klarte forskere å finne den faktiske koden. Dette tok dem et helt år, på tross av at de hadde tilgang til koden, og det ikke var brukt noen avanserte teknikker, bare at den brukte andre navn om hva den gjorde enn hva som faktisk skjedde.

Man må gjøre aktivt review

Dette illustrerer hvor vanskelig det er å komme inn i kode og se etter ugler i mosen. Det er svært vanlig at man har utviklingsprosesser der man gjør kontinuerlig “review” av all kode før den går inn i kodebasen. Å gjøre review innebærer at man går gjennom ny kode og gjør seg selv sikker på at man forstår hva den gjør. Ofte vil et ordentlig review gjøre at man skriver en lengre tilbakemelding og ber om større endringer. Man utsetter den også for automatiske tester slik at man vet godt hva koden gjør. Jeg har selv både gjort review, lagd rammeverk for automatiske tester og skrevet en masse tester. Jeg liker å skrive tester først for å være sikker på at jeg forstår hva koden skal gjøre. Min erfaring er at for å kunne gjøre et godt review bør man være involvert i koden jevnlig, helst på daglig basis. Hvis man skal kunne oppdage at noen gjør slemme ting og prøver å skjule det, så er det helt nødvendig at man er inne på daglig basis, og helst ikke bare ved å gjøre review, man bør aktivt utvikle i systemet. Du bør gjøre review av andres kode, og de bør gjøre review av din, og alt må testes hele tiden, og man må ha automatiserte tester for alt. Bare slik får man god kode. Bare så god kode og slik praksis vil kunne gjøre at tilsynsmyndigheter har en sjanse. Skulle europeiske tilsynsmyndigheter gjort denne typen review, måtte man ha titusenvis av ansatte. Selv da er det et spørsmål om man klarer å ha nødvendig avstand mellom utvikler og revisor, når disse måtte jobbe sammen til daglig.

Sorte svaner og overflatekonsekvenser

I likhet med dieselgate kan man gjøre inspeksjon ved ikke bare å sjekke kode, men også sjekke hvilke konsekvenser koden har. I dieselgate oppdaget man først altfor store emisjoner. Det er et meget stort felt som driver med dette, og man utvikler “benchmarks” som skal prøve å identifisere mulige problemer. Jeg mener denne tilnærmingen har ganske lite for seg, det kan være helt andre ting som er problematisk enn det man forestilte seg da man lagde benchmarken. Benchmarking er sjelden god vitenskap. Man kan ikke bevise at det ikke finnes en julenisse på nordpolen med et reinsdyr som har rød nese, og slik kan man aldri være sikker på at man har truffet den faktiske skurkestreken. Man kan heller ikke slutte av at alle svaner er hvite selv om man aldri har sett noe annet.

Kunnskapsskjevhetens betydning

Det er klart at en tilsynsmyndighet kan komme inn og sjekke at man følger god praksis. Man kan bruke moderne teknikker for å prøve å kryptografisk sikre at koden man ser er den som faktisk kjøres. I en situasjon der man har balanse mellom kunnskapen tilsynsmyndighetene besitter og teknologiselskapene besitter kan det kanskje hende det kunne fungert.

Det er enklest å lage en forretningsmodell hvis man har eksklusivitet. Du må ha en konkurransefordel, noe som ikke konkurrentene dine har. Så, mesteparten av IT-industrien er bygd rundt det, og det man som oftest har eksklusivitet på er faktisk ikke selve programvaren, men kunnskapen som er bygd inn i den programvaren. Det er ikke alltid problematisk, men det blir veldig problematisk når den programvaren setter normer for hvordan samfunnet vårt fungerer. Da blir det giftig fordi da er det teknologiselskapet som bestemmer normene, uten demokratisk mandat. Det er etter min oppfatning hovedgrunnen til at teknologiutviklingen har gått så galt. Kunnskapsskjevhet er et grunnlagsproblem, ingen tilnærminger som ikke løser dette problemet vil ha ønsket effekt.

Så, vi er veldig langt fra en situasjon der det er balanse mellom myndigheter og selskaper. Vi er veldig, veldig langt fra det. Inspeksjon- og revisjonsregimet er ikke løsningen på dette problemet, selv om EU later til å tro det. Dette er problemet som må løses før tilsynsmyndigheter kan ha betydning. Så hvordan gjør vi det?

Den digitale allmenningen er redningen

Det finnes en annen måte å utvikle programvare og standarder på. Den utgjør faktisk det meste. Det er basisen for Android og iOS, for webservere og datasentre, og for maskinlæring. Den består også av nesten alle standardene som brukes i ditt dagligliv, og man finner mye åpne data i den. Den digitale allmenningen er flere tiår gammel og er stor og innovativ.

Vi som jobber i den digitale allmenningen har deling av kunnskap som det viktigste vi gjør, det er hvem vi er. Vi tilbyr transparens, inklusivitet, selvbestemmelse, bruksrett og mulighet til å bidra og til å direkte påvirke hva teknologien gjør. Utviklingen gjøres i åpne miljøer med flere aktører, noen ganger konkurrenter.

I allmenningen har vi kjente metoder for omfattende review og testing. Ta en titt på endringsloggen til Linux for eksempel, der personer fra flere selskaper tester og gjør review av koden. Man kan for eksempel se at en ansatt i AMD gjør review av et endringsforslag gjort av en ansatt i Intel. Intel og AMD er to av verdens største produsenter av prosessorer, og er hverandres hovedkonkurrenter. Når hver kodebit gjennomgår en slik prosess blir det ikke bare svært vanskelig å snike inn noe, man får en ordning som skalerer, det er et helt miljø som sørger for at koden ikke inneholder ting som ikke skulle vært der, ikke bare en tilsynsmyndighet med begrensede ressurser. Når kommersielle konkurrenter har gjensidig nytte av å sikre god forvaltning av kode oppstår det gode effekter for samfunnet som helhet, det er nettopp det allmenninger handler om.

Men ikke alt er rosenrødt i den digitale allmenningen heller. Man ser at mennesker brenner seg ut, man ser at den er underfinansiert (og det er nok fordi det er vanskeligere å finne gode forretningsmodeller), man ser at man ikke klarer å organisere god nok testing og review og dermed blir sikkerhetsfeil gående uoppdaget, og man ser også at selskaper prøver å bygge gjerder som ødelegger. Det er derfor fortsatt behov for en tilsynsmyndighet, men den kan være mye mindre enn det som vil være nødvendig i EUs regime. Den må sørge for at prosjekter som har betydning for normene i samfunnet har en god maktbalanse mellom aktørene, og hvis det ikke gjøres god nok review og testing, så må man sørge for at det blir satt inn tilstrekkelig med ressurser til å gjøre det. Det kan gjøres ved å finansiere noen av aktørene slik Tyskland gjør med sitt Sovereign Tech Fund og som nå er i ferd med å bli generell EU-politikk.

Enda bedre, mener jeg, er om man setter opp en ny type samfunnsinstitusjon, som skal utvikle programvare med et demokratisk mandat snarere enn et kommersielt mandat. Jeg har kalt en slik institusjon “Senter for normativ teknologiutvikling”. Demokratiet vil bruke en slik tverrfaglig institusjon til å direkte påvirke normene som settes gjennom teknologien. Å utføre review og testing og sette inn ressursene som gir maktbalanse er blant de operative tingene en slik institusjon vil gjøre, men den vil først og fremst være skapende. Tilsynsmyndigheten vil fortsatt ha et overordnet ansvar for sørge for at allmenningen blir godt forvaltet.

Tillit er fortsatt det beste

Jeg vil ikke ha Big Tech-selskapene i det norske samfunnet. De har så til grader brutt ned tilliten, både min egen tillit til dem og den tilliten samfunnet bør ha til dem. Vi bør ikke ha slike selskaper som opererer i vårt samfunn. Når tilliten er brutt er det lett å ønske seg et veldig omfattende inspeksjon- og revisjons-regime, men det EU legger opp til vil aldri kunne bygge opp tillit, det vil kun bidra til at Big Tech får operere omtrent som før, bare under en solid mengde papirarbeid.

Men likevel, de nordiske tillitssamfunnene er fortsatt de beste. At vi har sterke tilsynsmyndigheter er en viktig årsak til at vi har slike tillitssamfunn, men våre tilsynsmyndigheter driver ikke med tilsyn for papirarbeidets skyld, de er faglig sterke myndigheter som leverer ordentlige resultater. Det regimet som vil oppstå hvis kunnskapsskjevheten mellom industri og reguleringsmyndigheter består må ikke forveksles med det norske tilsynsmyndigheter gjør i dag.

Jeg er sjelden blant dem som er redd for at innovasjon blir skadelidende ved innblanding av offentlige myndigheter. Men jeg tror at det kan bli mindre innovasjon av et slikt regime, mens innovasjonsevnen vil øke sterkt hvis det offentlige bidrar til utviklingen av digitale allmenninger gjennom et “Senter for normativ teknologiutvikling”. Jeg sier et stort ja takk til offentlig innblanding hvis det gjøres på riktig måte.

Siden digitale allmenninger er radikalt åpne, vil disse kunne opparbeide seg tillit på en måte som lukkede teknologiselskaper aldri kan fortjene, og dette vil gjøre at vi kan ha en nordisk tillitsmodell til selskapene som utvikler i allmenningen. Det inkluderer også Big Tech. Noe slikt kan ikke EU få til, men nordiske land kan.

Konklusjon

Det er en stor kunnskapsskjevhet mellom industri og reguleringsmyndigheter i IKT-feltet, noe som gjør at et inspeksjon- og revisjonsregime ikke vil fungere, det er altfor lett å skjule hva kode faktisk gjør. Et algoritmetilsyn vil føre tilsyn med feil ting, og vil ikke få betydning for de faktiske problemene. I stedet får vi ineffektiv teknologiutvikling og mange offentlige ansatte som ikke bidrar til nyskaping.

I stedet må myndighetene sørge for at teknologi som setter normer utvikles i åpne miljøer, slik mye programvare allerede gjør. Dette må skje i digitale allmenninger. Ved å gjøre dette vil befolkningen kunne ha tillit til teknologiutviklingen, og vi vil få offentlige ansatte som bidrar direkte i verdiskaping og innovasjon, og få fart på bærekraftig innovasjon i næringslivet.