2017-06-26 3 views
1

ich googeln für diese beiden C-Funktionen um, die ich brauche passieren, und die saubersten, die ich über kam, war http://fm4dd.com/programming/base64/base64_stringencode_c.htm Aber es scheint mir, wie das folgende kleine Teil davon ...Endian-unabhängige base64_encode/Dekodierungsfunktion

... wird endian-abhängig (dito eine entsprechende encodeblack(), die Sie an der obigen URL sehen können). Aber es ist ansonsten nett und sauber, im Gegensatz zu einigen anderen: einer hat drei eigene Header-Dateien, ein anderer eine eigene spezielle malloc() -ähnliche Funktion usw. Jeder kennt ein nettes, kleines, sauberes (keine Header, nein Abhängigkeiten, etc.) Version, wie diese, das ist mehr architekturunabhängig?

bearbeiten Grund, warum ich für diese Suche ist, dass base64_encode() wird in einem PHP-Skript ausgeführt werden, die Teil einer HTML-Seite ist, vorbei, dass codierte Zeichenfolge zu einem ausgeführten CGI-Programm auf einem fernen Feld. Und das cgi muss dann base64_decode(). Also Architektur-Unabhängigkeit ist nur eine zusätzliche Sicherheit, nur für den Fall, dass das CGI auf einer nicht-Intel Big-Endian-Box (Intel's wenig) läuft.

bearbeiten wie pro Kommentar unten, hier ist der vollständige Code zusammen mit ein paar Änderungen, die ich gemacht ...

/* downloaded from... 
    http://fm4dd.com/programming/base64/base64_stringencode_c.htm */ 
/* ------------------------------------------------------------------------ * 
* file:  base64_stringencode.c v1.0         * 
* purpose:  tests encoding/decoding strings with base64     * 
* author:  02/23/2009 Frank4DD           * 
*                   * 
* source:  http://base64.sourceforge.net/b64.c for encoding   * 
*    http://en.literateprograms.org/Base64_(C) for decoding  * 
* ------------------------------------------------------------------------ */ 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

/* ---- Base64 Encoding/Decoding Table --- */ 
char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"; 

/* decodeblock - decode 4 '6-bit' characters into 3 8-bit binary bytes */ 
void decodeblock(unsigned char in[], char *clrstr) { 
    unsigned char out[4]; 
    out[0] = in[0] << 2 | in[1] >> 4; 
    out[1] = in[1] << 4 | in[2] >> 2; 
    out[2] = in[2] << 6 | in[3] >> 0; 
    out[3] = '\0'; 
    strncat(clrstr, out, sizeof(out)); 
    } /* --- end-of-function decodeblock() --- */ 

char *base64_decode(char *b64src /*, char *clrdst */) { 
    static char clrdstbuff[8192]; 
     char *clrdst = clrdstbuff; 
    int c, phase, i; 
    unsigned char in[4]; 
    char *p; 

    clrdst[0] = '\0'; 
    phase = 0; i=0; 
    while(b64src[i]) { 
    c = (int) b64src[i]; 
    if(c == '=') { 
     decodeblock(in, clrdst); 
     break; } 
    p = strchr(b64, c); 
    if(p) { 
     in[phase] = p - b64; 
     phase = (phase + 1) % 4; 
     if(phase == 0) { 
     decodeblock(in, clrdst); 
     in[0]=in[1]=in[2]=in[3]=0; } 
     } /* --- end-of-if(p) --- */ 
    i++; 
    } /* --- end-of-while(b64src[i]) --- */ 
    return (clrdstbuff); 
    } /* --- end-of-function base64_decode() --- */ 

/* encodeblock - encode 3 8-bit binary bytes as 4 '6-bit' characters */ 
void encodeblock(unsigned char in[], char b64str[], int len) { 
    unsigned char out[5]; 
    out[0] = b64[ in[0] >> 2 ]; 
    out[1] = b64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; 
    out[2] = (unsigned char) (len > 1 ? b64[ ((in[1] & 0x0f) << 2) | 
      ((in[2] & 0xc0) >> 6) ] : '='); 
    out[3] = (unsigned char) (len > 2 ? b64[ in[2] & 0x3f ] : '='); 
    out[4] = '\0'; 
    strncat(b64str, out, sizeof(out)); 
    } /* --- end-of-function encodeblock() --- */ 

/* encode - base64 encode a stream, adding padding if needed */ 
char *base64_encode(char *clrstr /*, char *b64dst */) { 
    static char b64dstbuff[8192]; 
     char *b64dst = b64dstbuff; 
    unsigned char in[3]; 
    int i, len = 0; 
    int j = 0; 

    b64dst[0] = '\0'; 
    while(clrstr[j]) { 
    len = 0; 
    for(i=0; i<3; i++) { 
     in[i] = (unsigned char) clrstr[j]; 
     if(clrstr[j]) { 
     len++; j++; } 
     else in[i] = 0; 
     } /* --- end-of-for(i) --- */ 
    if(len) { 
     encodeblock(in, b64dst, len); } 
    } /* --- end-of-while(clrstr[j]) --- */ 
    return (b64dstbuff); 
    } /* --- end-of-function base64_encode() --- */ 

#ifdef TESTBASE64 
int main(int argc, char *argv[]) { 
    char *mysrc = (argc>1? argv[1] : "My bonnie is over the ocean  "); 
    char *mysrc2 = (argc>2? argv[2] : "My bonnie is over the sea  "); 
    char myb64[2048]="", myb642[2048]=""; 
    char mydst[2048]="", mydst2[2048]=""; 
    char *base64_enclode(), *base64_decode(); 
    int testnum = 1; 
    if (strncmp(mysrc,"test",4) == 0) 
    testnum = atoi(mysrc+4); 

    if (testnum == 1) { 
    strcpy(myb64,base64_encode(mysrc)); 
    printf("The string [%s]\n\tencodes into base64 as: [%s]\n",mysrc,myb64); 
    strcpy(myb642,base64_encode(mysrc2)); 
    printf("The string [%s]\n\tencodes into base64 as: [%s]\n",mysrc2,myb642); 
    printf("...\n"); 
    strcpy(mydst,base64_decode(myb64)); 
    printf("The string [%s]\n\tdecodes from base64 as: [%s]\n",myb64,mydst); 
    strcpy(mydst2,base64_decode(myb642)); 
    printf("The string [%s]\n\tdecodes from base64 as: [%s]\n",myb642,mydst2); 
    } /* --- end-of-if(testnum==1) --- */ 

    if (testnum == 2) { 
    strcpy(mydst,base64_decode(mysrc2)); /* input is b64 */ 
    printf("The string [%s]\n\tdecodes from base64 as: [%s]\n",mysrc2,mydst); 
    } /* --- end-of-if(testnum==2) --- */ 

    if (testnum == 3) { 
    int itest, ntests = (argc>2?atoi(argv[2]):999); 
    int ichar, nchars = (argc>3?atoi(argv[3]):128); 
    unsigned int seed = (argc>4?atoi(argv[4]):987654321); 
    char blanks[999] = "       "; 
    srand(seed); 
    for (itest=1; itest<=ntests; itest++) { 
     for (ichar=0; ichar<nchars; ichar++) mydst[ichar] = 1+(rand()%255); 
     mydst[nchars] = '\000'; 
     if (strlen(blanks) > 0) strcat(mydst,blanks); 
     strcpy(myb64,base64_encode(mydst)); 
     strcpy(mydst2,base64_decode(myb64)); 
     if (strcmp(mydst,mydst2) != 0) 
     printf("Test#%d:\n\t in=%s\n\tout=%s\n",itest,mydst,mydst2); 
     } /* --- end-of-for(itest) --- */ 
    } /* --- end-of-if(testnum==3) --- */ 

    return 0; 
    } /* --- end-of-function main() --- */ 
#endif 
+0

Aber die Endiannität * ist * wichtig. Sie könnten ein htonl/s in der Kodierung und ntohl/s in der Dekodierung hinzufügen, bevor Sie etwas anderes tun. Dann weißt du, dass du immer die gleiche Endianz hast. –

+0

Können Sie Ihre endianess-Abhängigkeit Zweifel näher ausführen? Vielleicht geben Sie ein Beispiel, wo Sie falsche/unterschiedliche Ergebnisse für Berechnungen in beiden Endigungen erhalten? – Yunnosch

+0

@Yunnosch Ich bin nicht unterschiedliche Ergebnisse bekommen - siehe oben bearbeiten (aber eine Minute warten, bis ich ihn dort) –

Antwort

2

Nein, es nicht Endian abhängig ist. Base64 selbst ist 4 Byte bis 3 Byte Codierung und kümmert sich nicht um die tatsächliche Darstellung im Speicher. Wenn Sie jedoch die Übertragung von Little/Big-Endian-Daten erwarten, müssen Sie die Endianness vor der-Codierung und nach der Decodierung normalisieren.

Dieses Fragment adressiert nur alle Bytes unabhängig voneinander. Es wäre endian-abhängig, wenn es 4 Bytes in uint32_t oder so geladen würde, und die Verwendung von Bit-Twiddling erzeugte eine Ausgabe, die in den Ergebnispuffer kopiert würde, wie es ist.


jedoch, dass Code gefährlich mit seinem strncat gebrochen und mit eingebettetem NUL Bytes nicht funktionieren würde. Stattdessen sollten Sie etwas wie

void decodeblock(unsigned char in[], unsigned char **clrstr) { 
    *((*clrstr) ++) = in[0] << 2 | in[1] >> 4; 
    *((*clrstr) ++) = in[1] << 4 | in[2] >> 2; 
    *((*clrstr) ++) = in[2] << 6 | in[3] >> 0; 
} 

verwenden, die mit eingebetteten NULs funktionieren würde.

+0

Was ist mit der letzten Zeile der OP-Frage: 'out [3] =' \ 0 ';' –

+2

@AndreKampling es ist für nichts erforderlich. Es ist ein ungünstiger Versuch, den Puffer für strncat geeignet zu machen, aber strncat mit Limit 3 würde niemals 'out [3]' oder das vierte Zeichen im Puffer absuchen. –

+0

Danke, Antti. Das ist vielleicht der beste Ansatz. Aber er macht eine strcat(), weil er ** zu Recht oder zu Unrecht (wahrscheinlich zu Unrecht) ** immer ein ptr an den ** Anfang ** der klaren Zeichenfolge weitergibt (siehe den Link zu seinem Code), also bist du es Ersetzen Sie immer die ersten paar Bytes, anstatt am Ende zu addieren. Stattdessen müssen Sie zunächst das Ziel-ptr mit strlen (* clrstr) anheben und schließlich ein weiteres abschließendes '\ 000' hinzufügen, damit die eindeutige Zeichenfolge immer null-terminiert bleibt. Aber du hast Recht, die ganze Sache ist ein bisschen unordentlich (aber einige der anderen Sachen, die ich sah, waren noch unordentlicher). (P.S. strcat Limit ist eigentlich 4) –