Ohjelmointi

Base64-koodaus ja -dekoodaus Java 8: ssa

Java 8 muistetaan lähinnä lambdojen, suoratoistojen, uuden päivämäärä / aika-mallin ja Nashorn JavaScript -moottorin käyttöönotosta Javalle. Jotkut muistavat myös Java 8: n useiden pienten mutta hyödyllisten ominaisuuksien, kuten Base64-sovellusliittymän, käyttöönotosta. Mikä on Base64 ja miten tätä sovellusliittymää käytetään? Tämä viesti vastaa näihin kysymyksiin.

Mikä on Base64?

Pohja 64 on binääritekstikoodausmenetelmä, joka edustaa binääridataa tulostettavassa ASCII-merkkijonoformaatissa kääntämällä se radix-64-esitykseen. Jokainen Base64-numero edustaa tarkalleen kuutta bittidatan bittiä.

Base64-pyyntö kommenttiasiakirjoista

Base64 kuvattiin ensimmäisen kerran (mutta sitä ei nimetty) asiakirjassa RFC 1421: Internetin sähköisen sähköpostin tietosuojan parantaminen: Osa I: Viestien salaus ja todennusmenettelyt. Myöhemmin se esitettiin virallisesti Base64: nä RFC 2045: Monikäyttöiset Internet-postilaajennukset (MIME): Ensimmäinen osa: Internet-viestirunkojen muoto, ja palasi myöhemmin RFC 4648: Base16-, Base32- ja Base64-datakoodauksiin.

Base64: ää käytetään estämään tietojen muokkaaminen kuljetettaessa tietojärjestelmiä, kuten sähköpostia, jotka eivät välttämättä ole 8-bittisiä (ne voivat hämmentää 8-bittisiä arvoja). Liität esimerkiksi kuvan sähköpostiviestiin ja haluat kuvan saapuvan toiseen päähän hämmentyneenä. Sähköpostiohjelmisto Base64 koodaa kuvan ja lisää vastaavan tekstin viestiin alla olevan kuvan mukaisesti:

Sisältö-sijoitus: inline; tiedostonimi = IMG_0006.JPG Content-Transfer-Encoding: base64 / 9 j / 4R / + RXhpZgAATU0AKgAAAAgACgEPAAIAAAAGAAAAhgEQAAIAAAAKAAAAjAESAAMAAAABAAYA AAEaAAUAAAABAAAAlgEbAAUAAAABAAAAngEoAAMAAAABAAIAAAExAAIAAAAHAAAApgEyAAIAAAAU AAAArgITAAMAAAABAAEAAIdpAAQAAAABAAAAwgAABCRBcHBsZQBpUGhvbmUgNnMAAAAASAAAAAEA ... NOMbnDUk2bGh26x2yiJcsoBIrvtPe3muBbTRGMdeufmH + Nct4chUXpwSPk / qK9GtJRMWWVFbZ0JH I4rf2dkZSbOjt7hhEzwcujA4I7Gust75pYVwAPpXn + kzNLOVYD7xFegWEKPkHsM / pU1F0NKbNS32 o24sSCOlaaFYLUhjky4x9PSsKL5bJsdWkAz3xirH2dZLy1DM2C44zx1FZqL2PTXY / 9k =

Kuva osoittaa, että tämä koodattu kuva alkaa / ja päättyy =. ... tarkoittaa tekstiä, jota en ole esittänyt lyhytkestoisuuden vuoksi. Huomaa, että tämän tai muun esimerkin koko koodaus on noin 33 prosenttia suurempi kuin alkuperäinen binaaritieto.

Vastaanottajan sähköpostiohjelmisto purkaa koodatun tekstikuvan alkuperäisen binaarikuvan palauttamiseksi. Tässä esimerkissä kuva näytetään linjassa muun viestin kanssa.

Base64-koodaus ja -dekoodaus

Base64 perustuu yksinkertaisiin koodaus- ja dekoodausalgoritmeihin. Ne työskentelevät US-ASCII: n 65-merkkisen osajoukon kanssa, jossa kukin 64 ensimmäisestä merkistä kartoittaa vastaavaan 6-bittiseen binaarisekvenssiin. Tässä on aakkoset:

Arvokoodaus Arvokoodaus Arvokoodaus Arvokoodaus 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63/13 N 30 e 47 v 14 O 31 f 48 w (tyyny) = 15 P 32 g 49 x 16 Q 33 h 50 v

65. merkki (=) käytetään Base64-koodatun tekstin pehmustamiseen yhtenäiseksi kooksi, kuten lyhyesti selitetään.

Alijoukko-ominaisuus

Tällä osajoukolla on tärkeä ominaisuus, että se on edustettu identtisesti kaikissa ISO 646 -versioissa, mukaan lukien US-ASCII, ja kaikki osajoukon merkit ovat edustettuina samalla tavoin kaikissa EBCDIC-versioissa.

Koodausalgoritmi vastaanottaa 8-bittisten tavujen tulovirran. Tämän virran oletetaan tilatun ensin merkitsevimmän bitin kanssa: ensimmäinen bitti on ensimmäisen tavun korkeamman tason bitti, kahdeksas bitti on tämän tavun matalatasoinen bitti ja niin edelleen.

Vasemmalta oikealle nämä tavut on järjestetty 24-bittisiin ryhmiin. Kutakin ryhmää käsitellään neljänä ketjutettuna 6-bittisenä ryhmänä. Kukin 6-bittinen ryhmä indeksoidaan joukoksi 64 tulostettavaa merkkiä; tuloksena oleva merkki tulostetaan.

Kun koodattavan datan lopussa on käytettävissä vähemmän kuin 24 bittiä, lisätään nolla bittiä (oikealla) muodostamaan integraali määrä 6-bittisiä ryhmiä. Sitten yksi tai kaksi = tyynymerkit voidaan tulostaa. Harkittavana on kaksi tapausta:

  • Yksi jäljellä oleva tavu: Tähän tavuun liitetään neljä nollabittiä kahden 6-bittisen ryhmän muodostamiseksi. Jokainen ryhmä indeksoi taulukon ja tuloksena oleva merkki tulostetaan. Näiden kahden merkin jälkeen kaksi = tyynymerkit tulostetaan.
  • Kaksi jäljellä olevaa tavua: Kaksi nollabittiä liitetään toiseen tavuun kolmen 6-bittisen ryhmän muodostamiseksi. Jokainen ryhmä indeksoi taulukon ja tuloksena oleva merkki tulostetaan. Seuraamalla näitä kolmea merkkiä, yksi = tyyppimerkki tulostetaan.

Tarkastellaan kolmea esimerkkiä oppiaksemme, kuinka koodausalgoritmi toimii. Oletetaan ensin, että haluamme koodata @!*:

Lähde ASCII-bittisekvenssit valmiilla 0 bitillä 8-bittisten tavujen muodostamiseksi: @! * 01000000 00100001 00101010 Jakamalla tämä 24-bittinen ryhmä neljään 6-bittiseen ryhmään saadaan seuraava: 010000 | 000010 | 000100 | 101010 Nämä bittimallit vastaavat seuraavia hakemistoja: 16 2 4 42 Indeksointi aiemmin esitettyyn Base64-aakkosiin tuottaa seuraavan koodauksen: QCEq

Jatkamme lyhentämällä tulosarjaa kohtaan @!:

Lähde ASCII-bittisekvenssit valmiilla 0 bitillä 8-bittisten tavujen muodostamiseksi: @! 01000000 00100001 Kolme 6-bittistä ryhmää varten liitetään kaksi nollabittiä: 010000 | 000010 | 000100 Nämä bittikuviot vastaavat seuraavia hakemistoja: 16 2 4 Aikaisempi indeksointi aikaisemmin esitettyyn Base64-aakkosiin tuottaa seuraavan koodauksen: QCE An = tyyppimerkki annetaan, jolloin saadaan seuraava lopullinen koodaus: QCE =

Viimeinen esimerkki lyhentää syöttösekvenssin @:

Lähde ASCII-bittisekvenssi valmiilla 0 bitillä 8-bittisen tavun muodostamiseksi: @ 01000000 Neljä nolla bittiä liitetään kahden 6-bittisen ryhmän muodostamiseksi: 010000 | 000000 Nämä bittikuviot vastaavat seuraavia hakemistoja: 16 0 Aikaisempi indeksointi aikaisemmin esitettyyn Base64-aakkosiin tuottaa seuraavan koodauksen: QA Kaksi = pad-merkkiä tulostetaan, jolloin saadaan seuraava lopullinen koodaus: QA ==

Dekoodausalgoritmi on käänteinen koodausalgoritmille. On kuitenkin mahdollista ryhtyä asianmukaisiin toimiin, kun havaitaan merkki, joka ei ole Base64-aakkosessa, tai väärä määrä pad-merkkejä.

Base64-muunnokset

Useita Base64-muunnelmia on kehitetty. Jotkut vaihtoehdot edellyttävät, että koodattu lähtövirta jaetaan useisiin kiinteän pituisiin viivoihin siten, että kukin rivi ei ylitä tiettyä pituusrajaa ja (viimeistä riviä lukuun ottamatta) erotetaan seuraavasta rivistä rivierottimen kautta \ r jota seuraa rivinsyöttö \ n). Kuvaan kolme versiota, joita Java 8: n Base64-sovellusliittymä tukee. Katso täydellinen luettelo muunnelmista Wikipedian Base64-merkinnästä.

Perus

RFC 4648 kuvaa Base64-muunnoksen, joka tunnetaan nimellä Perus. Tämä muunnos käyttää Base64-aakkosia, jotka on esitetty RFC 4648: n ja RFC 2045: n taulukossa 1 (ja esitetty aiemmin tässä viestissä) koodaamiseen ja dekoodaamiseen. Kooderi käsittelee koodattua lähtövirtaa yhtenä rivinä; mitään rivierottimia ei tulosteta. Dekooderi hylkää koodauksen, joka sisältää merkkejä Base64-aakkosien ulkopuolella. Huomaa, että nämä ja muut ehdot voidaan ohittaa.

MIME

RFC 2045 kuvaa Base64-muunnoksen, joka tunnetaan nimellä MIME. Tämä muunnos käyttää RFC 2045: n taulukossa 1 esitettyä Base64-aakkosia koodaamiseen ja dekoodaamiseen. Koodattu lähtövirta on järjestetty enintään 76 merkin pituisiin riveihin; kukin rivi (paitsi viimeinen rivi) erotetaan seuraavasta rivistä viivanerottimen avulla. Kaikki rivierottimet tai muut merkit, joita ei löydy Base64-aakkosista, ohitetaan dekoodauksen aikana.

URL ja tiedostonimi turvallinen

RFC 4648 kuvaa Base64-muunnoksen, joka tunnetaan nimellä URL ja tiedostonimi turvallinen. Tämä muunnos käyttää RFC 4648: n taulukossa 2 esitettyä Base64-aakkosia koodaamiseen ja dekoodaamiseen. Aakkoset ovat identtiset aikaisemmin esitettyjen aakkosien kanssa - korvaa + ja _ korvaa /. Linjaerottimia ei tulosteta. Dekooderi hylkää koodauksen, joka sisältää merkkejä Base64-aakkosien ulkopuolella.

Base64-koodaus on hyödyllinen pitkien binaaritietojen ja HTTP GET -pyyntöjen yhteydessä. Ajatuksena on koodata nämä tiedot ja liittää ne sitten HTTP GET URL-osoitteeseen. Jos käytettiin Basic- tai MIME-muunnosta, mikä tahansa + tai / koodatun datan merkit olisi URL-koodattu heksadesimaalisekvensseihin (+ tulee % 2B ja / tulee % 2F). Tuloksena oleva URL-merkkijono olisi jonkin verran pidempi. Korvaamalla + kanssa - ja / kanssa _, URL ja Filename Safe poistaa URL-koodereiden / -dekoodereiden tarpeen (ja niiden vaikutukset koodattujen arvojen pituuksiin). Tämä muunnos on myös hyödyllinen, kun koodattua tietoa on tarkoitus käyttää tiedostonimelle, koska Unix- ja Windows-tiedostonimet eivät voi sisältää /.

Työskentely Java: n Base64-sovellusliittymän kanssa

Java 8 esitteli Base64-sovellusliittymän, joka koostuu java.util.Base64 luokka yhdessä sen kanssa Kooderi ja Dekooderi sisäkkäin staattinen luokat. Pohja 64 esittelee useita staattinen menetelmät kooderien ja dekooderien saamiseksi:

  • Base64.Encoder getEncoder (): Palauta kooderi Basic-muunnokseen.
  • 64. dekooderi getDecoder (): Palauta dekooderi Basic-muunnokseen.
  • Base64.Encoder getMimeEncoder (): Palauta MIME-variantin kooderi.
  • Base64.Encoder getMimeEncoder (int lineLength, byte [] lineSeparator): Palauta kooderi muokatulle MIME-muunnokselle annetulla lineLength (pyöristetty alaspäin lähimpään 4 - tuloon, ei lähtöä riviin, kun lineLength<= 0) ja lineSeparator. Se heittää java.lang.IllegalArgumentException kun lineSeparator sisältää kaikki Base64-aakkoset, jotka on esitetty RFC 2045: n taulukossa 1.

    RFC 2045: n kooderi, joka palautetaan noargumentista getMimeEncoder () menetelmä on melko jäykkä. Esimerkiksi tämä kooderi luo koodatun tekstin, jonka kiinteä viivan pituus (lukuun ottamatta viimeistä riviä) on 76 merkkiä. Jos haluat kooderin tukevan RFC 1421: tä, joka määrittelee kiinteän linjan pituuden 64 merkkiä, sinun on käytettävä getMimeEncoder (int lineLength, tavu [] lineSeparator).

  • Base64. Dekooderi getMimeDecoder (): Palauta dekooderi MIME-muunnokseen.
  • 64. Encoder getUrlEncoder (): Palauta kooderi URL-osoitteelle ja Tiedostonimi-turvalliselle muunnelmalle.
  • Base64. Dekooderi getUrlDecoder (): Palauta dekooderi URL-osoitteelle ja tiedostonimen turvalliselle muunnelmalle.

64. kooderi esittelee useita threadsafe-esiintymämenetelmiä tavusekvenssien koodaamiseksi. Nollaviitteen välittäminen johonkin seuraavista menetelmistä johtaa java.lang.NullPointerException:

  • tavu [] koodaa (tavu [] src): Koodaa kaikki tavut src äskettäin varattuun tavutaulukkoon, jonka tämä menetelmä palauttaa.
  • int-koodaus (tavu [] src, tavu [] dst): Koodaa kaikki tavut src että dst (alkaen siirtymästä 0). Jos dst ei ole tarpeeksi suuri pitämään koodausta, IllegalArgumentException heitetään. Muussa tapauksessa tavujen määrä kirjoitetaan dst palautetaan.
  • ByteBuffer-koodaus (ByteBuffer-puskuri): Koodaa kaikki jäljellä olevat tavut puskuri vasta varatulle java.nio.ByteBuffer esine. Palattuaan puskuriasema päivitetään rajaansa saakka; sen rajaa ei ole muutettu. Palautetun lähtöpuskurin sijainti on nolla ja sen raja on saatujen koodattujen tavujen määrä.
  • Merkkijono encodeToString (tavu [] src): Koodaa kaikki tavut src merkkijonoon, joka palautetaan. Tämän menetelmän käyttäminen vastaa suorittamista uusi merkkijono (koodaa (src), StandardCharsets.ISO_8859_1).
  • 64. Encoder withoutPadding (): Palauta kooderi, joka koodaa vastaavasti tähän kooderiin, mutta lisäämättä täyttömerkkejä koodattujen tavutietojen loppuun.
  • OutputStream-kääre (OutputStream os): Kääri lähtövirta tavutietojen koodaamista varten. Palautettu lähtövirta on suositeltavaa sulkea heti käytön jälkeen, jolloin se huuhtelee kaikki mahdolliset jäljellä olevat tavut alla olevaan lähtövirtaan. Palautetun lähtövirran sulkeminen sulkee taustalla olevan lähtövirran.

64. dekooderi esittelee useita threadsafe-esiintymämenetelmiä tavusekvenssien dekoodaamiseksi. Nollaviitteen välittäminen johonkin seuraavista menetelmistä johtaa NullPointerException: