2016-04-22 12 views
1

ich einen privaten RSA-Schlüssel mit dem folgenden Befehl erstellt:d2i_RSA_PUBKEY, d2i_RSAPrivateKey und d2i_RSAPublicKey gibt NULL zurück

openssl genrsa -out keypair.pem 2048 

Ich muß DEN-codierten Schlüssel (PKCS # 1) für dieses Projekt verwenden, so erzeugen ich zwei DIE Dateien aus dieser PEM-codierten privaten Schlüsseldatei - eine mit dem privaten Schlüssel und eine mit dem öffentlichen Schlüssel.

In meinem Code habe ich den Inhalt dieser beiden Dateien in char * Variablen geladen.

Keiner der folgenden Arbeiten wie erwartet:

d2i_RSA_PUBKEY(NULL, &public_key_bytes, public_key_length); 

d2i_RSAPublicKey(NULL, &public_key_bytes, public_key_length); 

d2i_RSAPrivateKey(NULL, &private_key_bytes, private_key_length); 

Ich weiß beacause alle von ihnen, dass null zurückzukehren. Ich habe auch versucht die folgenden:

RSA * rsa = RSA_new(); 
d2i_RSA_PUBKEY(&rsa, &public_key_bytes, public_key_length); 

RSA * rsa = RSA_new(); 
d2i_RSAPublicKey(&rsa, &public_key_bytes, public_key_length); 

RSA * rsa = RSA_new(); 
d2i_RSAPrivateKey(&rsa, &private_key_bytes, private_key_length); 

Alle Rückkehr null auch.

Mein kompletter Test-Code lautet wie folgt:

#include <stdio.h> 
#include <stdlib.h> 

#include <openssl/rsa.h> 
#include <openssl/bio.h> 
#include <openssl/pem.h> 

typedef struct 
{ 
    int len; 
    char * bytes; 
} FileData; 

static FileData readFileBytes(const char * name, int zero_ended) 
{ 
    FILE * fl = fopen(name, "r"); 
    if (fl == NULL) return (FileData) { .len = 0, .bytes = NULL }; 
    fseek(fl, 0, SEEK_END); 
    long len = ftell(fl); 
    char * ret = malloc(len + (zero_ended ? 1 : 0)); 
    fseek(fl, 0, SEEK_SET); 
    fread(ret, 1, len, fl); 
    if (zero_ended) ret[len] = 0; 
    fclose(fl); 
    return (FileData) { .len = len, .bytes = ret }; 
} 

int main() 
{ 
    FileData private_key = readFileBytes("../private.der", 0); 
    FileData public_key = readFileBytes("../public.der", 0); 

    char* public_key_bytes = public_key.bytes; 
    int public_key_length = public_key.len; 

    char* private_key_bytes = private_key.bytes; 
    int private_key_length = private_key.len; 

    RSA * rsa; 

    public_key_bytes = public_key.bytes; 
    public_key_length = public_key.len; 
    rsa = d2i_RSA_PUBKEY(NULL, &public_key_bytes, public_key_length); 
    printf("d2i_RSA_PUBKEY(NULL, &public_key_bytes, public_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false"); 

    public_key_bytes = public_key.bytes; 
    public_key_length = public_key.len; 
    rsa = d2i_RSAPublicKey(NULL, &public_key_bytes, public_key_length); 
    printf("d2i_RSAPublicKey(NULL, &public_key_bytes, public_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false"); 

    private_key_bytes = private_key.bytes; 
    private_key_length = private_key.len; 
    rsa = d2i_RSAPrivateKey(NULL, &private_key_bytes, private_key_length); 
    printf("d2i_RSAPrivateKey(NULL, &private_key_bytes, private_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false"); 

    public_key_bytes = public_key.bytes; 
    public_key_length = public_key.len; 
    rsa = RSA_new(); 
    rsa = d2i_RSA_PUBKEY(&rsa, &public_key_bytes, public_key_length); 
    printf("d2i_RSA_PUBKEY(&rsa, &public_key_bytes, public_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false"); 

    public_key_bytes = public_key.bytes; 
    public_key_length = public_key.len; 
    rsa = RSA_new(); 
    rsa = d2i_RSAPublicKey(&rsa, &public_key_bytes, public_key_length); 
    printf("d2i_RSAPublicKey(&rsa, &public_key_bytes, public_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false"); 

    private_key_bytes = private_key.bytes; 
    private_key_length = private_key.len; 
    rsa = RSA_new(); 
    rsa = d2i_RSAPrivateKey(&rsa, &private_key_bytes, private_key_length); 
    printf("d2i_RSAPrivateKey(&rsa, &private_key_bytes, private_key_length) != NULL -> %s\n", (rsa != NULL) ? "true" : "false"); 

    getchar(); 

    return 0; 
} 

Was mache ich falsch?

+0

* "Keine der folgenden Arbeiten" * Woher weißt du das? – dbush

+0

Aktualisiert die Frage mit einer Erklärung. Warum die negative Stimme? – LordCapybara

+0

Wenn Sie interessiert sind, können Sie ein Beispiel für das Lesen eines Schreibschlüssels in einer Reihe von Formaten mit C++ unter [Wie generiere ich einen privaten RSA-Schlüssel mit openssl?] (Http://stackoverflow.com/a/30493975/608639) Sie würden [d2i_X509] (http://www.openssl.org/docs/manmaster/crypto/d2i_X509.html) verwenden, um ein ganzes Zertifikat im Format ASN.1/DER zu lesen. – jww

Antwort

3

TLDR: d2i_RSA_PUBKEY und d2i_RSAPrivateKey sollte funktionieren, und für mich auf Unix.

Sie sagen, Sie wollen 'DER-codierte Schlüssel (PKCS # 1)'.

Für public OpenSSL verwendet normalerweise das Format in X.509 definiert als die SubjectPublicKeyInfo enthält eine AlgorithmIdentifierzuzüglich (herausgegeben) BIT STRING publickey einen Wert in einer Struktur enthält, die auf dem Algorithmus variiert. Für RSA enthält das Algid eine OID, die RSA und keine Parameter identifiziert; Die algorithmusabhängige Struktur ist PKCS # 1.

Im Gegensatz dazu unterstützt OpenSSL zwei Arten von privaten Schlüsselformaten: Für jeden Algorithmus (außer DH) gibt es ein "Legacy" -Format, das für RSA PKCS # 1 ist; und ein generisches Format, das durch PKCS # 8 definiert wird, das wie SPKI aus einem AlgorithmIdentifier plus einem Algorithmus-abhängigen privaten Schlüsselwert besteht, diesmal in OCTET STRING. PKCS # 8 hat auch eine Option, um den Schlüssel zu verschlüsseln, den SPKI nicht hat oder braucht.

Ältere Teile von OpenSSL, einschließlich der Kommandozeilenprogramme genrsa und rsa, verwenden das Legacy-Privatekey-Format, aber SPKI publickey format, das OpenSSL PUBKEY nennt. So haben Ihre rsa Befehle eine öffentlich lesbare Datei erstellt, die von d2i_RSA_PUBKEY gelesen werden kann, aber nicht d2i_RSAPublicKey (was nur der Teil von PKCS # 1 wäre) und eine private Schlüsseldatei, die von d2i_RSAPrivateKey gelesen werden kann.

Wenn Sie wirklich publickey in ‚nackt‘ PKCS # 1-Format benötigen, das rsa Dienstprogramm hat Optionen -RSAPublicKey_in und -RSAPublicKey_out zu lesen und dieses Format seit 1.0.0 zu schreiben, obwohl erst vor kurzem dokumentiert und noch nicht in der Hilfemeldung. Diese Datei wird von d2i_RSAPublicKey aber nicht d2i_RSA_PUBKEY gelesen werden.

Eine Möglichkeit: Sie erwähnen Betriebssystem nicht.DER-Dateien sind binär, und in C, um binäre Dateien unter Windows korrekt zu behandeln, müssen Sie mit dem Modifikator b, hier wollen Sie "rb" für Binär lesen. Wenn ich deinen Code unter Unix ausführe, funktioniert es, aber um korrekte Ergebnisse unter Windows zu erhalten, muss ich die b hinzufügen.

Auch ein kleiner Punkt: Sie sprechen über 'Inhalte laden ... in char * Variablen'. Tatsächlich laden Sie den Inhalt der Datei in den Speicher und verwenden eine char * Variable, um auf sie zu zeigen. Streng genommen wollen OpenSSL d2i Routinen die Adresse einer Variable - und Ihr Compiler sollte Sie vor dieser Diskrepanz warnen, zumindest wenn Sie es in einem standardkonformen Modus ausführen. Aber C erfordert Zeiger auf alle char Aromen (signedunsigned und 'plain'), mit oder ohne Qualifikation, die gleiche Darstellung und Ausrichtung Anforderungen, auch wenn sie nicht kompatibel sind, wie in der Norm definiert, so ist char ** erwartet funktioniert.

+0

Ja, ich bin auf Windows - das "rb" -Flag hat es behoben. Ich wusste nicht über die "b" -Flagge auf Windows ... Schande über mich. – LordCapybara