2016-04-22 28 views
1

を返します。このPEMでエンコードされた秘密鍵ファイルのファイル(秘密鍵を持つものと公開鍵を持つもの)d2i_RSA_PUBKEY、d2i_RSAPrivateKeyとd2i_RSAPublicKeyは、私は、次のコマンドを使用して、RSA秘密鍵を作成したNULL

openssl rsa -inform PEM -in keypair.pem -outform DER -pubout -out public.der 

openssl rsa -inform PEM -in keypair.pem -outform DER -out private.der 

私のコードでは、これらのファイルの内容をchar *変数にロードしました。予想通り、次の作品の

なし:

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); 

私はそれらのすべてbeacause nullを返すことを知っています。私はまた次を試みた:

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); 

すべての戻り値null同様に。次のように

私の完全なテストコードは次のとおりです。

#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; 
} 

私が間違って何をしているのですか?

+0

*「次の作品はありません」*あなたはどのように知っていますか? – dbush

+0

質問を説明文で更新しました。なぜ否定的な投票ですか? – LordCapybara

+0

興味があれば、[opensslを使ってRSA秘密鍵を生成するには?](http://stackoverflow.com/a/30493975/608639)でC++を使用して複数の書式キーを読む例を見ることができます。また、 [d2i_X509](http://www.openssl.org/docs/manmaster/crypto/d2i_X509.html)を使用して、証明書全体をASN.1/DER形式で読むことができます。 – jww

答えて

3

TLDRd2i_RSA_PUBKEYおよびd2i_RSAPrivateKeyは、Unixでうまくいくはずです。

「DERエンコードキー(PKCS#1)」が必要です。 OpenSSLが通常のアルゴリズムに依存して変化する構造で公開鍵値を含む(編集)AlgorithmIdentifierプラスBIT STRINGを含んSubjectPublicKeyInfoとしてX.509で定義されたフォーマットを使用するためのpublickeys

。 RSAの場合、algidにはRSAを識別するOIDとパラメータは含まれていません。アルゴリズムに依存する構造はPKCS#1です。

対照的に、OpenSSLは2つのタイプの秘密鍵形式をサポートしています。各アルゴリズム(「DH」を除く)に「レガシー」形式があり、RSAはPKCS#1です。 SPKIのようにAlgorithmIdentifierとアルゴリズムに依存する秘密鍵の値(このときはOCTET STRING)で構成されているPKCS#8で定義されている汎用フォーマットです。 PKCS#8には、SPKIが持っていない、または必要としない鍵を暗号化するオプションもあります。

genrsaおよびrsaコマンドラインユーティリティを含む旧式の部分は、従来の秘密鍵形式を使用しますが、OpenSSLがPUBKEYと名前を付けるSPKI公開鍵形式を使用します。したがって、rsaコマンドは、d2i_RSA_PUBKEYで読み取り可能な公開鍵ファイルを作成しましたが、d2i_RSAPublicKey(PKCS#1部分のみになります)とd2i_RSAPrivateKeyで読み取り可能な秘密鍵ファイルを作成しませんでした。

あなたが本当に「裸」PKCS#1形式で公開する必要がある場合は、ごく最近になって、まだないヘルプメッセージで文書化されたが、rsaユーティリティは、1.0.0以来、このフォーマットを読み書きするためのオプション-RSAPublicKey_in-RSAPublicKey_outを持っています。そのファイルはd2i_RSAPublicKeyでは読み取れるが、d2i_RSA_PUBKEYでは読み取れない。

1つの可能性:オペレーティングシステムについては言及していません。DERファイルはバイナリであり、CではバイナリファイルをWindowsに正しく処理するには、fopenb修飾子を指定する必要があります。ここでは、バイナリを"rb"にします。あなたのコードをUnix上で実行するとうまくいきますが、Windowsで正しい結果を得るためにはbを追加する必要があります。

また、「読み込み中のコンテンツ... char *変数」についてお話しします。実際には、ファイルの内容をメモリにロードし、char *変数を使用してそれらを指し示します。厳密に言えば、OpenSSL d2iルーチンはconst unsigned char *のアドレスを必要とします。コンパイラは、少なくとも標準準拠モードで実行すると、この不一致について警告する必要があります。しかし、標準で定義されているように互換性がないにもかかわらず、同じ表現とアライメントの要件を満たすように、すべてのcharフレーバー(signedunsignedと 'plain')へのポインターが必要です。char **ここで、const unsigned char **は期待は働く。

+0

はい、私はWindows上で動作しています - "rb"フラグがそれを修正しました。私はWindowsの "b"フラグについて知らなかった...私には恥がある。 – LordCapybara

関連する問題