Base64 kodeeringu raamatukogu koos Arduinoga
Alus64 on kodeerimissüsteem, mis kasutab 64 sümbolit, mis on rühmitatud sõnumiteks, mille pikkus on neli kordaja. Neid sõnumeid (andmepakette) täiendatakse vajadusel plussmärgiga (seetõttu kasutatakse 65), sageli võrdusmärki (=), kui kodeeritud kasuliku teabe tulemuseks on lühem pikkus.
Kasutades 64 märki, saate töötada koodi 10 numbri ning suur- ja väiketähtedega (26+26) ASCII, probleem on selles, et seal on 62, ütleme, üheselt mõistetavat sümbolit pluss kaks, mis erinevad erinevates rakendustes. Kuigi mõnikord viidatakse sellele väljendiga "tegelased ASCII prinditav", tegelikkuses on need need, mis ulatuvad koodiga 32 (tühik) tähistatud koodist 126 (~) tõeliselt prinditava 95-ni.
Kodeerimise rakendamine Alus64 enim kasutatud, et PEM, mida kasutab ka MIME, kasutage lisamärke "+" ja "/" ning märki "=", et pakettide pikkus oleks neljakordne. Tähed A–Z asuvad positsioonidel 0–25, tähed a–z asuvad positsioonidel 26–51, numbrid 0–9 on positsioonidel 52–61, plussmärk (+) on positsioonidel 62 ja positsiooni 63 hõivab kaldkriips (/ ).
Andmete esitamise viis vormingus Alus64 koosneb algandmetest rühmade võtmisest 6 bitti mis on esindatud vastava koodiga. Kui bitte jääb üle, täidetakse need paremale nullidega. Kui saadud koodide arv ei ole neljakordne, täidetakse see paremal asuvate võrdusmärkidega.
Järgmine pilt näitab kodeerimist ASCII tekstist ("ohm") ja viisist, kuidas see teisendatakse Alus64. Kuna sümboleid on 7, tuleks viimane teade lõpus täita võrdusmärgiga. Võiks öelda, et tekst "ohm" sisse ASCII samaväärne "b2htaW8=" in Alus64.
Kodeerimise spetsiifilised kasutusalad Alus64 Tavaliselt kehtestavad nad ka maksimaalse joone pikkuse. Rakendamine MIME Iga rea pikkus on 76 tähemärki. Tavaliselt eraldatakse read realõpu koodiga (CR, mida tähistab väärtus 0x0D ASCII) ja veel üks uus rida (NL, mis vastab koodile ASCII 0x0A).
Ebamugavused, mis kodeerimise rakendamisel lisanduvad Alus64 väheste ressurssidega seadmel, nagu sageli a puhul mikrokontroller on see, et peate kodeerima teabe saabumisel või a-ga puhver miinimum, mis eeldab ka süsteemi tagamist, mis annab märku, et algse sõnumi lõpp on saavutatud, lisades näiteks spetsiaalse koodi või kasutades PIN-koodi, mille tase (vastuvõtuga sünkroniseerituna) näitab sõnumi olekut.
Allolev näitekood on a teek Arduino jaoks Base64-s kodeerimiseks mida rakendatakse mõlema kriteeriumiga: saabuva teabe kodeerimine (ilma a puhver) ja oodake hoiatussignaali lõppu.
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”
}
}
|
Koodi arvutamise põhiosa Alus64 Seda tehakse väljendiga:
(valor_original>>(2+(numero_valor%3)*2))|resto_base64
ja jäägi arvutamine avaldisega:
(valor_original&(MASCARA_B64>>desplazamiento))<<desplazamiento
,
olemine desplazamiento
väärtus, mis arvutatakse avaldisega:
4-(numero_valor%3)*2
Nende avaldiste saamiseks järgnev protsess seisneb kõigi nelja koodi arvutamise üldistamises Alus64 mis tulenevad algväärtuse kolme baidi esitamisest.
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 |
Koos tekstiga Base64
Ülaltoodud pseudokood viitab sissetulevale koodile Alus64 mida arvutatakse. Väljendit on kasutatud byte_n
viidata kodeeritavale n-ndale baidile. Tekst resto
tähistab kodeeritava baidi järelejäänud bitte. Arvutamise alguses eeldatakse, et jääk on null
Selguse huvides on eelmises pseudokoodis 6-bitine mask kaasatud kõigi koodide arvutamisse, kuigi on vaja määrata ainult viimane neist, kuna teised on pööratud nii, et kaks kõige rohkem bitti lähevad alati kaotsi. märkimisväärne.
Nagu näha, on neljas kood kõik jääk ja pärast pole vaja jääki arvutada; Seetõttu on vaja teha ainult kolm sammu, üks kodeeritud baidi kohta. Oluline on meeles pidada, et kui paketi kolmas bait ei oleks kodeeritud, tuleks viimane kood paremal pool täita nullidega. Alus64 saadud.
Üldistamiseks avaldise õige pööramine, mis arvutab sisse koodi Alus64 saab kujutada kui 2+(numero_byte%3)*2
nii, et sulgudes olev osa pöörleks nullist kaheni, mille tulemuseks on 2, 4 ja 6 igal sammul. Muidugi pole see ainus viis üldistamiseks, kuid valisin selle funktsionaalsuse ja eelkõige selguse huvides. Kuna mask (AND) oli vajalik ainult neljandas koodis ja on juba nähtud, et seda pole vaja arvutada (see on kõik jääk), siis ei lisata seda lõppavaldisesse selle lihtsustamiseks, kuigi me peame meeles pidama et kasutatavate andmete tüüp (bait ) võetakse ainult 6 vähima tähtsusega bitti.
Ülejäänute vasakpoolset pöörlemist saab üldistada analoogselt eelnevaga. Samuti on näha, et rakendatud mask (AND) läbib sama bitipöörde, kuid vastupidises suunas. See on põhjus nihke arvutamiseks 4-(numero_valor%3)*2
enne selle rakendamist igale väljendi osale vastavas tähenduses.
Järgmine näide näitab, kuidas kasutada teeki tekstistringi kodeerimiseks (pidage meeles, et Alus64 saab kasutada mis tahes andmekogumi jaoks, näiteks pildi jaoks). Järgmises koodis on paar detaili, mida on huvitav selgitada. Esiteks on teksti lõpu tähistamiseks kasutatud spetsiaalset sümbolit (sümbolit ~), mitte riistvarasignaali või teksti pikkust näitavat. Loogiliselt võttes ei saa see sümbol olla osa kodeeritud andmetest.
Teine küsimus, mida tuleb käsitleda, nii oluline kui see on ilmselge, on see, et sihtkoha dekooder peab teadma, kuidas temani jõudvat teavet esitatakse. Tekst sisaldab märke, mis komplekti ei kuulu ASCII prinditav (32-126), näiteks aktsendiga tähed. Arduino kasutab kahte baiti (UTF-8) nende märkide tähistamiseks. Tavalist ei saa lihtsalt kasutada \0
teksti terminaatorina, kuna paljudel juhtudel on esimene bait, millega märki esitatakse, täpselt null.
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()
{
}
|
Eelmise näite rida 26 näitab, kuidas kasutada teek Arduino jaoks Base64-s kodeerimiseks. On vaja ainult näidata meetod convertir
iga bait mida soovite kodeerida ja valikuliselt kas see on viimane või kui ei, siis peatage teisendamine meetodiga terminar
kui jõuad lõppu.
Nagu on näha alloleval ekraanipildil, on näidisprogramm teek Arduino jaoks Base64-s kodeerimiseks kuvab esmalt teksti, millesse kodeeritakse Alus64, antud juhul hiiglaste kuulsa laulu algus Les Luthiersja seejärel sisse kodeerimise tulemus Alus64 kasutades vormingu rea pikkust MIME.
Postita kommentaar