Base64-koodauskirjasto Arduinon kanssa
BASE64 on koodausjärjestelmä, joka käyttää 64 symbolia, jotka on ryhmitelty viesteiksi, joiden pituus on neljän kerrannainen. Nämä viestit (datapaketit) täydennetään tarvittaessa plussymbolilla (joten käytetään 65), usein yhtäläisyysmerkkiä (=), jos koodattu hyödyllinen tieto johtaa lyhyempään pituuteen.
Käyttämällä 64 merkkiä voit käsitellä koodin 10 numeroa sekä isoja ja pieniä kirjaimia (26+26) ASCII, ongelmana on, että on olemassa 62 yksiselitteistä symbolia plus kaksi, jotka vaihtelevat eri toteutuksissa. Vaikka joskus viitataan ilmaisulla "hahmot". ASCII tulostettava", todellisuudessa ne ovat niitä, jotka vaihtelevat koodin 32 (välilyönti) edustamasta numerosta 126 (~) todella tulostettavaan 95:een.
Koodauksen toteuttaminen BASE64 eniten käytetty, että PEM, jota myös käyttää MIME, käytä ylimääräisiä "+"- ja "/"-merkkejä sekä "="-merkkiä, jotta pakettien pituus on neljän kerrannainen. Kirjaimet A-Z ovat paikoissa 0-25, kirjaimet a-z ovat paikkoja 26-51, numerot 0-9 ovat paikkoja 52-61, plusmerkki (+) ovat 62 ja 63 on kauttaviiva (/ ).
Tapa esittää tiedot muodossa BASE64 koostuu ryhmien ottamisesta alkuperäisistä tiedoista 6 bittiä jotka esitetään vastaavalla koodilla. Jos bittejä on jäljellä, ne täytetään nollilla oikealla. Jos saatu koodien määrä ei ole neljän kerrannainen, se täytetään yhtäläisyysmerkeillä oikealla.
Seuraava kuva näyttää koodauksen ASCII tekstistä ("ohm") ja tavasta, jolla se muunnetaan BASE64. Koska symboleja on 7, viimeinen viesti on täytettävä yhtäläisyysmerkillä. Voisi sanoa, että teksti "ohm" sisään ASCII vastaa «b2htaW8=" in BASE64.
Koodauksen erityiskäyttö BASE64 Ne myös yleensä määräävät enimmäislinjan pituuden. Toimeenpano MIME Rajoittaa jokaisen rivin 76 merkkiin. Normaalisti rivit erotetaan rivin loppukoodilla (CR, jota edustaa arvo 0x0D ASCII) ja toinen uusi rivi (NL, joka vastaa koodia ASCII 0x0A).
Epämukavuus, joka lisätään koodauksen käyttöönotossa BASE64 laitteella, jolla on vähän resursseja, kuten usein a mikro-ohjain on, että sinun on koodattava tiedon saapuessa tai a puskuri minimi, mikä edellyttää myös sellaisen järjestelmän tarjoamista, joka ilmoittaa, että alkuperäisen viestin loppu on saavutettu esimerkiksi lisäämällä erikoiskoodi tai käyttämällä PIN-koodia, jonka taso (vastaanoton kanssa synkronoituna) ilmaisee viestin tilan.
Alla oleva esimerkkikoodi on a kirjasto Arduinolle Base64:ään koodattavaksi joka toteutetaan molemmilla kriteereillä: saapuvan tiedon koodauksella (ilman a puskuri) ja odota varoitussignaalin loppumista.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//base64.h
#include <string.h> // memcpy/strncpy
#define LONGITUD_LINEA 76
#define MASCARA_B64 0B00111111
#define ULTIMO_CODIGO_BASE64 64 // 64 caracteres más el signo igual (empezando a contar desde cero)
#define MAXIMA_LONGITUD_RESULTADO 6 // Máximo número de caracteres del resultado parcial de la codificación. Puede ser 1 si no se ha llegado al final de un bloque (2 bytes en el original, 4 en la conversión), 2 si se ha llegado al final de un bloque, 3 si no se ha llegado al final de un bloque pero se supera la longitud máxima de la línea, 4 si se llega al final de un bloque y se supera la longitud máxima de la línea, 5 si hay que rellenar con un signo igual o 6 si hay que rellenar con dos signos igual
class Base64
{
private:
unsigned char simbolo_base64[ULTIMO_CODIGO_BASE64+1]; // Espacio para la codificación Base64, el relleno (=) una terminación en \0
unsigned int numero_valor; // Posición (empezando en cero) que ocupa el valor que se desea convertir en el mensaje completo original
unsigned int numero_codigo; // Posición del último código calculado. Podría limitarse al ancho de la línea (LONGITUD_LINEA, 76 caracteres) pero usando un contenedor alto se podría implementar también una cuenta estadística
unsigned char resto_base64; // Último resto obtenido al calcular el último código
unsigned char resultado[MAXIMA_LONGITUD_RESULTADO+1]; // Resultado de la conversión actual. Si es terminal puede incluir el caracter 65 (=) una o dos veces
unsigned char contador_caracteres_resultado=0;
void acumular_resultado(unsigned char valor);
public:
Base64();
~Base64();
void iniciar_conversion();
unsigned char *convertir(unsigned char valor_original, bool terminar_conversion);
unsigned char *convertir(unsigned char valor_original);
unsigned char *terminar();
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
//base64.cpp
#include “base64.h”
Base64::Base64() // Constructor
{
memcpy(simbolo_base64,“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=”,ULTIMO_CODIGO_BASE64+1);
iniciar_conversion();
}
Base64::~Base64() // Destructor
{
}
void Base64::iniciar_conversion()
{
numero_valor=0;
numero_codigo=0;
resto_base64=0;
}
unsigned char *Base64::convertir(unsigned char valor_original, bool terminar_conversion) // Valor que se desea convertir a Base64
{
convertir(valor_original);
if(terminar_conversion)
{
terminar();
}
return resultado;
}
unsigned char *Base64::convertir(unsigned char valor_original) // Valor que se desea convertir a Base64
{
unsigned char desplazamiento;
contador_caracteres_resultado=0;
acumular_resultado((valor_original>>(2+(numero_valor%3)*2))|resto_base64);
desplazamiento=4–(numero_valor%3)*2;
resto_base64=(valor_original&(MASCARA_B64>>desplazamiento))<<desplazamiento;
if(((numero_codigo+1)%4==0))
{
acumular_resultado(resto_base64);
resto_base64=0;
}
numero_valor++;
resultado[contador_caracteres_resultado]=0;
return resultado;
}
unsigned char *Base64::terminar()
{
if(numero_codigo%4)
{
acumular_resultado(resto_base64);
while(numero_codigo%4)
{
acumular_resultado(ULTIMO_CODIGO_BASE64);
}
}
resultado[contador_caracteres_resultado]=0;
iniciar_conversion();
return resultado;
}
void Base64::acumular_resultado(unsigned char valor)
{
numero_codigo++;
resultado[contador_caracteres_resultado++]=simbolo_base64[valor];
if((numero_codigo%LONGITUD_LINEA)==0)
{
resultado[contador_caracteres_resultado++]=13; // CR “\r”
resultado[contador_caracteres_resultado++]=10; // LF “\n”
}
}
|
Koodilaskennan perusosa BASE64 Se tehdään lausekkeella:
(valor_original>>(2+(numero_valor%3)*2))|resto_base64
ja lopun laskeminen lausekkeella:
(valor_original&(MASCARA_B64>>desplazamiento))<<desplazamiento
,
ollessa desplazamiento
arvo, joka lasketaan lausekkeella:
4-(numero_valor%3)*2
Näiden lausekkeiden saamiseksi noudatettava prosessi koostuu kunkin neljän koodin laskennan yleistämisestä BASE64 jotka johtuvat edustamalla kolme tavua alkuperäisestä arvosta.
Base64=((byte_1>>2)|resto)&0b00111111 |
resto=(byte_1&0b00000011)<<4 |
Base64=((byte_2>>4)|resto)&0b00111111 |
resto=(byte_2&0b00001111)<<2 |
Base64=((byte_3>>6)|resto)&0b00111111 |
resto=(byte_3&0b00111111)<<0 |
Base64=((byte_3>>0)|resto)&0b00111111 |
resto=(byte_3&0b00111111)<<0 |
Tekstin kanssa Base64
Yllä oleva pseudokoodi viittaa koodiin BASE64 jota lasketaan. Ilmaisua on käytetty byte_n
viitata koodattavaan n:nneen tavuun. Teksti resto
edustaa koodattavan tavun jäljellä olevia bittejä. Laskennan alussa oletetaan, että jäännös on nolla
Selvyyden vuoksi edellisessä pseudokoodissa 6-bittinen maski on sisällytetty kaikkien koodien laskemiseen, vaikka on tarpeen määrittää vain niistä viimeinen, koska muut on kierretty niin, että kaksi eniten bittiä menetetään aina. merkittävä.
Kuten voidaan nähdä, neljäs koodi on kaikki jäännös, eikä jäännöstä tarvitse laskea jälkeenpäin; Siksi on tarpeen suorittaa vain kolme vaihetta, yksi per koodattu tavu. On tärkeää muistaa, että jos paketin kolmatta tavua ei ole koodattu, viimeinen koodi on täytettävä nolilla oikealla. BASE64 saatu.
Yleistyksenä: koodin laskevan lausekkeen oikea kierto BASE64 voidaan esittää muodossa 2+(numero_byte%3)*2
niin, että sulkujen sisällä oleva osa kiertyy nollasta kahteen, jolloin tuloksena olisi 2, 4 ja 6 jokaisessa vaiheessa. Se ei tietenkään ole ainoa tapa yleistää, mutta olen valinnut tämän toiminnallisuuden ja ennen kaikkea selkeyden vuoksi. Koska maski (AND) oli välttämätön vain neljännessä koodissa ja on jo nähty, että sitä ei tarvitse laskea (se on kaikki jäännös), sitä ei sisällytetä lopulliseen lausekkeeseen sen yksinkertaistamiseksi, vaikka meidän täytyy muistaa että käytetystä datatyypistä (tavu ) otetaan vain 6 vähiten merkitsevää bittiä.
Loput vasemmalle voidaan yleistää edellistä vastaavalla tavalla. Voidaan myös nähdä, että levitettävä maski (AND) käy läpi saman bittikierron, mutta vastakkaiseen suuntaan. Tästä syystä siirtymä lasketaan 4-(numero_valor%3)*2
ennen kuin käytät sitä lauseen kutakin osaa vastaavassa merkityksessä.
Seuraava esimerkki näyttää, kuinka kirjastoa käytetään tekstimerkkijonon koodaamiseen (muista tämä BASE64 voidaan käyttää mille tahansa tietojoukolle, kuten kuvalle). Seuraavassa koodissa on pari yksityiskohtaa, joita on mielenkiintoista selventää. Ensinnäkin erityistä symbolia (symbolia ~) on käytetty osoittamaan tekstin loppua laitteistosignaalin tai tekstin pituuden osoittavan sijaan. Loogisesti tämä symboli ei voi olla osa koodattua dataa.
Toinen asia, joka on otettava huomioon, niin tärkeä kuin se onkin, on se, että kohteen dekooderin on tiedettävä, kuinka sen saavuttava tieto esitetään. Teksti sisältää merkkejä, jotka eivät kuulu joukkoon ASCII tulostettavat (32-126), esimerkiksi aksenttikirjaimet. Työläs käyttää kahta tavua (UTF-8) edustamaan näitä merkkejä. Tavallista ei voi yksinkertaisesti käyttää \0
tekstin päätteeksi, koska monissa tapauksissa ensimmäinen tavu, jolla merkki esitetään, on täsmälleen nolla.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#include “base64.h”
char texto_prueba[]=“La bella y graciosa moza marchose a lavar la ropa.\nLa mojó en el arroyuelo y cantando la lavó.\nLa frotó sobre una piedra, la colgó de un abedul.\nDespués de lavar la ropa, la niña se fue al mercado.\nUn pastor vendía ovejas pregonando a viva voz:\nved qué oveja, ved qué lana, ved qué bestia, qué animal.\nLa niña la vio muy flaca, sin embargo le gustó.\nYo te pago veinte escudos y no discutamos más.\nVuelve la niña cantando muy contenta con su oveja.\nCuando llegaron al bosque la ovejita se escapó.\nLa niña desesperada arrojose encima de ella.\nVelozmente y con destreza aferrola por detrás.\nLlegaba por el camino jinete de altivo porte.\nDescendió de su caballo y a la niña le cantó…~”;
char *resultado;
Base64 base64;
void setup()
{
Serial.begin(9600);
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) // ¿Es un Arduino Leonardo (ATmega32U4)?
while(!Serial){}; // Esperar a Arduino Leonardo
#endif
// Mostrar el texto original
unsigned int contador=0;
while(texto_prueba[contador]!=‘~’)
{
//Serial.println(String(texto_prueba[contador])+”=”+String(texto_prueba[contador],DEC));
Serial.print(String(texto_prueba[contador]));
contador++;
}
Serial.println(“\n”);
// Mostrar el texto codificado en Base64
contador=0;
while(texto_prueba[contador]!=‘~’)
{
resultado=base64.convertir(texto_prueba[contador],texto_prueba[contador+1]==‘~’);
byte contador_resultado=0;
while(resultado[contador_resultado]>0)
{
Serial.print(String(resultado[contador_resultado]));
contador_resultado++;
}
contador++;
}
}
void loop()
{
}
|
Edellisen esimerkin rivillä 26 näkyy kirjasto Arduinolle Base64:ään koodattavaksi. On tarpeen ilmoittaa vain menetelmä convertir
jokainen tavu jonka haluat koodata ja valinnaisesti onko se viimeinen tai jos ei, lopeta muunnos menetelmällä terminar
kun tulet loppuun.
Kuten alla olevasta kuvakaappauksesta näkyy, esimerkkiohjelma kirjasto Arduinolle Base64:ään koodattavaksi näyttää ensin tekstin, johon koodataan BASE64, tässä tapauksessa kuuluisan jättiläisten laulun alku Les Luthiers, ja sen jälkeen koodauksen tulos BASE64 käyttämällä muotoa rivin pituus MIME.
Post Comment