2016-07-13 11 views
1

Ich habe versucht, ein 32Byte base64 String mit OpenSSL zu erzeugen, aber es funktioniert nicht immer 32 Byte-String erzeugen und manchmal die Ausgabe verstümmelt und nicht korrektNicht druckbare Zeichen nach Erzeugung von Zufall n-Byte-Base64-String

#include <openssl/rand.h> 
#include <openssl/bio.h> 
#include <openssl/evp.h> 
#include <openssl/buffer.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int Base64Encode(const unsigned char* buffer, unsigned char** b64text) { //Encodes a binary safe base 64 string 
    BIO *bio, *b64; 
    BUF_MEM *bufferPtr; 

    b64 = BIO_new(BIO_f_base64()); 
    bio = BIO_new(BIO_s_mem()); 
    bio = BIO_push(b64, bio); 

    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line 
    BIO_write(bio, buffer, strlen(buffer)); 
    BIO_flush(bio); 
    BIO_get_mem_ptr(bio, &bufferPtr); 
    BIO_set_close(bio, BIO_NOCLOSE); 
    BIO_free_all(bio); 

    *b64text=bufferPtr->data; 

    return (0); //success 
} 

int main() { 
    unsigned char buffer[35], *base64EncodeOutput; 
    int ret = RAND_bytes(buffer, 32); 
    buffer[32]='\0'; // Null terminate 

    (void)Base64Encode(buffer, &base64EncodeOutput); 
    (void)printf("Return value of the operation was: %d\n%s\n", ret, base64EncodeOutput); 

    return EXIT_SUCCESS; 
} 
angezeigt

Kompilieren und Ausführen mit gcc rand_str.c -lcrypto && ./a.out | tail -1, erzeugt manchmal so etwas wie:

I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`�

und manchmal ist die Ausgabe 32 Byte Länge nicht gerade ist.

Mein Ziel ist es zu replizieren, was dieser Befehl tut: openssl rand -base64 32


Was muss ich anders machen müssen?

Antwort

1

Dank der oben genannten Lösungen konnte ich dieses Problem beheben. Hier ist das Ergebnis:

#include <openssl/rand.h> 
#include <openssl/bio.h> 
#include <openssl/evp.h> 
#include <openssl/buffer.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

static char* base64_bytes(int size) { 
    char *buff = malloc(size + 1), *bytes = NULL; 
    int chunk; 
    BIO *b64, *out; 
    BUF_MEM *bptr; 

    // Create a base64 filter/sink 
    if ((b64 = BIO_new(BIO_f_base64())) == NULL) { 
     return NULL; 
    } 

    // Create a memory source 
    if ((out = BIO_new(BIO_s_mem())) == NULL) { 
     return NULL; 
    } 

    // Chain them 
    out = BIO_push(b64, out); 
    BIO_set_flags(out, BIO_FLAGS_BASE64_NO_NL); 

    // Generate random bytes 
    if (!RAND_bytes(buff, size)) { 
     return NULL; 
    } 

    // Write the bytes 
    BIO_write(out, buff, size); 
    BIO_flush(out); 

    // Now remove the base64 filter 
    out = BIO_pop(b64); 

    // Write the null terminating character 
    BIO_write(out, "\0", 1); 
    BIO_get_mem_ptr(out, &bptr); 

    // Allocate memory for the output and copy it to the new location 
    bytes = malloc(bptr->length); 
    strncpy(bytes, bptr->data, bptr->length); 

    // Cleanup 
    BIO_set_close(out, BIO_CLOSE); 
    BIO_free_all(out); 
    free(buff); 

    return bytes; 
} 

int main() { 
    char *b64 = base64_bytes(32); 
    puts(b64); 

    free(b64); 

    return EXIT_SUCCESS; 
} 

Das Hauptproblem mit meinem ursprünglichen Versuch wurde, dass, wenn das Nullabschluss durch die base64 Filter geleitet wird, ist es nicht als das Ende der Zeichenfolge erkannt wird, sondern es ist konvertiert zu base64, was die Saite so aussehen lässt, wie sie es in meinem ursprünglichen Beitrag getan hat.

Also die vorgeschlagene Lösung ist das Entfernen des Base64-Filters von der BIO nach dem Schreiben der ursprünglichen Zeichenfolge, das dann nur die out BIO verlässt. Da die out BIO einfach eine Senke ist, können wir so ziemlich alles schreiben und es ändert nicht ihre Eingabe. Dies gibt die Möglichkeit, einen Null-Terminator in den zugrundeliegenden Puffer zu schreiben und später die vollständige Zeichenfolge abzurufen.

2

BIO_write(bio, buffer, strlen(buffer));

NUL ein gültiger Zufalls Byte, so daß Strlen manchmal weniger zurückkehren wird als der Sollwert (32).

Das ` ist wegen des base64-Puffers, der keinen NUL-Terminator hat, also liest er etwas zufälligen Müll vor. Ich weiß nicht von irgendeiner Weise OpenSSL zu zwingen, eine NUL hinzuzufügen, aber Sie können printf sagen, wo zu stoppen:

(void)printf("Return value of the operation was: %d\n%.44s\n", ret, base64EncodeOutput);

+0

Danke für die Antwort. Kannst du mir sagen, was ist der Unterschied zwischen '% 44s' und'% .44s'? – smac89

+1

% 44s druckt mindestens 44 Zeichen, während% .44s maximal 44 Zeichen ausgibt.Wenn die Zeichenfolge kürzer als das Minimum ist, wird sie mit Leerzeichen aufgefüllt. Wenn es länger ist als das Maximum, ist es abgeschnitten. – Alcaro

+0

Habe gerade etwas Neues gelernt. Vielen Dank – smac89

2

Kompilieren und Ausführen mit gcc rand_str.c -lcrypto & & ./ a.out | tail -1, erzeugt manchmal so etwas wie:

I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`� 

Die BIO'snicht produzieren C-Strings tun. Sie sind nicht NULL beendet.

Führen Sie einen weiteren BIO_write aus und schreiben Sie das NULL-Zeichen, nachdem Sie das Base64 BIO aus der Kette entfernt haben.