2017-06-01 9 views
0

Ich versuche, EVP_ * APIs von OpenSSL zu verwenden, aber ich habe ein merkwürdiges Verhalten bei dem Versuch, den Public/Private-Schlüssel aus der EVP_PKEY-Struktur auszugeben.Aufruf von OpenSSLs PEM_write_PUBKEY || PEM_write_PrivateKey API beendet das Programm abrupt mit der Meldung "no OPENSSL_Applink"

Problem :: Nach dem Auffüllen der EVP_PKEY Struktur, beim Aufruf PEM_write_PUBKEY API (siehe TRIAL1), das Programm beendet. Das Gleiche passiert beim Aufruf von PEM_write_PrivateKey API (siehe TRIAL2).

Ausgang: Ich bin mit einer temp.pem 0 Byte Datei links und eine Nachricht auf cmd prompt sagt OPENSSL_Uplink(5D8C7000,08): no OPENSSL_Applink

#define TRIAL1 

void InitOpenSSLLib(void) 
{ 
    SSL_library_init(); 
    SSL_load_error_strings(); 
    OpenSSL_add_all_algorithms(); 
} 

int main(int argc, char** argv) 
{ 
    EVP_PKEY_CTX* ctx = NULL; 
    EVP_PKEY* pKeyPair = EVP_PKEY_new(); 

    BIO *mem = BIO_new(BIO_s_mem()); 
    FILE* fp = fopen("temp.pem", "wb"); 

    InitOpenSSLLib(); 

    ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, 0); 
    EVP_PKEY_keygen_init(ctx); 
    EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048); 
    EVP_PKEY_keygen(ctx, &pKeyPair); 

    // Succeeds till here... all of the above called APIs return value greater than 0 

#ifdef TRIAL1 
    // Program exits even before printing any error 
    if (PEM_write_PUBKEY(fp, pKeyPair) <= 0) 
     printf("PEM_write_PUBKEY failed\n"); 
#elif TRIAL2 
    // same behavior with this API too 
    PEM_write_PrivateKey(fp, pKeyPair, NULL, NULL, 0, 0, NULL); 
#endif 
    // Tried this too.... but the control never reaches here 
    fflush(fp); 

    // Tried this too... most of the mem struct members are NULL. 
    EVP_PKEY_print_private(mem, pKeyPair, 0, 0); 

    //.... Cleanup codes 
    fclose(fp); 
    BIO_free_all(mem); 

    return 0; 
} 

Alle Zeiger? Mache ich hier etwas falsch? Gibt es eine andere Möglichkeit, privaten/öffentlichen Schlüssel oder das Paar PEM-Format in eine Datei zu dumpen?

Ich bin mit VC++ 2015. Auch Ctrl beim Auftreffen auf + F5, zeigt die Eingabeaufforderung die Meldung :: OPENSSL_Uplink (5D8C7000,08): nein OPENSSL_Applink

meine eigene Frage zu beantworten für future devs

+0

Also, was genau ist das Ergebnis? Eine Datei "temp.pem" mit 0 Bytes? – Ctx

+0

@Ctx: Genau .. – Abhineet

+0

Hilft das? https://www.openssl.org/docs/faq.html#PROG2 – Ctx

Antwort

0

Die Schlüsselfrage hier ist der Fehler (lesen, Nachricht) von OpenSSL geworfen, dh keine OPENSSL_Applink.

wie dokumentiert here,

Wie pro 0.9.8 die obige Beschränkung für .DLLs eliminiert wird. OpenSSL .DLLs kompiliert mit einer bestimmten Laufzeitoption [bestehen wir auf der Standard/MD] kann mit Anwendung kompiliert mit anderen Option oder sogar anderen Compiler bereitgestellt werden. Aber es gibt einen Haken! Anstatt OpenSSL-Toolkit neu kompilieren, wie Sie mit früheren Versionen müssen, müssen Sie kleine C-Snippet mit Compiler und/oder Optionen Ihrer Wahl kompilieren. Das Snippet wird als /include/openssl/applink.c installiert und sollte entweder zu Ihrem Anwendungsprojekt hinzugefügt werden oder einfach # include-d in einem [und nur einem] von Ihre Anwendungsquelldateien. Wenn Sie dieses Shim-Modul nicht mit verknüpfen, wird Ihre Anwendung als fataler "no OPENSSL_Applink" Laufzeitfehler angezeigt. Eine ausdrückliche Erinnerung ist, dass in dieser Situation [Mixing Compiler-Optionen] ist es wichtig, CRYPTO_malloc_init vor dem ersten Aufruf an OpenSSL hinzuzufügen.

sollten Sie Ihre Kompilierung Optionen für /MD überprüfen (vorausgesetzt, Sie die Code Generation Optionen unter VC++ Project Properties kennen).

Ich tat das gleiche, aber mein Problem wurde nicht gelöst.Die Antwort auf diese ist der zweite Absatz auf den angegebenen Link [https://www.openssl.org/docs/faq.html#PROG2], wo es uns <install-root>/include/openssl/applink.c

Wo bekommt man diese applink.c Datei aufzunehmen anweist, wenn nicht in OpenSSL dir gefunden?

In meinem Fall habe ich installiert OpenSSL exe binär mit und ich konnte nicht diese spezifische applink.c Datei irgendwo in meinen <install-root> finden, so begann ich auf der Suche und fand es here on GitHub.

Sie müssen diese Datei als Quelldatei in Ihr Projekt einfügen oder sie lieber in openssl install-root dir speichern, damit Sie sie auch für andere Projekte vom selben Speicherort einbinden können.

// applink.c from https://github.com/openssl/openssl/blob/master/ms/applink.c 
/* 
* Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. 
* 
* Licensed under the OpenSSL license (the "License"). You may not use 
* this file except in compliance with the License. You can obtain a copy 
* in the file LICENSE in the source distribution or at 
* https://www.openssl.org/source/license.html 
*/ 

#define APPLINK_STDIN 1 
#define APPLINK_STDOUT 2 
#define APPLINK_STDERR 3 
#define APPLINK_FPRINTF 4 
#define APPLINK_FGETS 5 
#define APPLINK_FREAD 6 
#define APPLINK_FWRITE 7 
#define APPLINK_FSETMOD 8 
#define APPLINK_FEOF 9 
#define APPLINK_FCLOSE 10  /* should not be used */ 

#define APPLINK_FOPEN 11  /* solely for completeness */ 
#define APPLINK_FSEEK 12 
#define APPLINK_FTELL 13 
#define APPLINK_FFLUSH 14 
#define APPLINK_FERROR 15 
#define APPLINK_CLEARERR 16 
#define APPLINK_FILENO 17  /* to be used with below */ 

#define APPLINK_OPEN 18  /* formally can't be used, as flags can vary */ 
#define APPLINK_READ 19 
#define APPLINK_WRITE 20 
#define APPLINK_LSEEK 21 
#define APPLINK_CLOSE 22 
#define APPLINK_MAX  22  /* always same as last macro */ 

#ifndef APPMACROS_ONLY 
# include <stdio.h> 
# include <io.h> 
# include <fcntl.h> 

static void *app_stdin(void) 
{ 
    return stdin; 
} 

static void *app_stdout(void) 
{ 
    return stdout; 
} 

static void *app_stderr(void) 
{ 
    return stderr; 
} 

static int app_feof(FILE *fp) 
{ 
    return feof(fp); 
} 

static int app_ferror(FILE *fp) 
{ 
    return ferror(fp); 
} 

static void app_clearerr(FILE *fp) 
{ 
    clearerr(fp); 
} 

static int app_fileno(FILE *fp) 
{ 
    return _fileno(fp); 
} 

static int app_fsetmod(FILE *fp, char mod) 
{ 
    return _setmode(_fileno(fp), mod == 'b' ? _O_BINARY : _O_TEXT); 
} 

#ifdef __cplusplus 
extern "C" { 
#endif 

__declspec(dllexport) 
void ** 
# if defined(__BORLANDC__) 
/* 
* __stdcall appears to be the only way to get the name 
* decoration right with Borland C. Otherwise it works 
* purely incidentally, as we pass no parameters. 
*/ 
__stdcall 
# else 
__cdecl 
# endif 
OPENSSL_Applink(void) 
{ 
    static int once = 1; 
    static void *OPENSSL_ApplinkTable[APPLINK_MAX + 1] = 
     { (void *)APPLINK_MAX }; 

    if (once) { 
     OPENSSL_ApplinkTable[APPLINK_STDIN] = app_stdin; 
     OPENSSL_ApplinkTable[APPLINK_STDOUT] = app_stdout; 
     OPENSSL_ApplinkTable[APPLINK_STDERR] = app_stderr; 
     OPENSSL_ApplinkTable[APPLINK_FPRINTF] = fprintf; 
     OPENSSL_ApplinkTable[APPLINK_FGETS] = fgets; 
     OPENSSL_ApplinkTable[APPLINK_FREAD] = fread; 
     OPENSSL_ApplinkTable[APPLINK_FWRITE] = fwrite; 
     OPENSSL_ApplinkTable[APPLINK_FSETMOD] = app_fsetmod; 
     OPENSSL_ApplinkTable[APPLINK_FEOF] = app_feof; 
     OPENSSL_ApplinkTable[APPLINK_FCLOSE] = fclose; 

     OPENSSL_ApplinkTable[APPLINK_FOPEN] = fopen; 
     OPENSSL_ApplinkTable[APPLINK_FSEEK] = fseek; 
     OPENSSL_ApplinkTable[APPLINK_FTELL] = ftell; 
     OPENSSL_ApplinkTable[APPLINK_FFLUSH] = fflush; 
     OPENSSL_ApplinkTable[APPLINK_FERROR] = app_ferror; 
     OPENSSL_ApplinkTable[APPLINK_CLEARERR] = app_clearerr; 
     OPENSSL_ApplinkTable[APPLINK_FILENO] = app_fileno; 

     OPENSSL_ApplinkTable[APPLINK_OPEN] = _open; 
     OPENSSL_ApplinkTable[APPLINK_READ] = _read; 
     OPENSSL_ApplinkTable[APPLINK_WRITE] = _write; 
     OPENSSL_ApplinkTable[APPLINK_LSEEK] = _lseek; 
     OPENSSL_ApplinkTable[APPLINK_CLOSE] = _close; 

     once = 0; 
    } 

    return OPENSSL_ApplinkTable; 
} 

#ifdef __cplusplus 
} 
#endif 
#endif 

Das ist es, wird dies das seltsame Verhalten von Programmausgang zu beseitigen.

Verwandte Themen