d2i_RSA_PUBKEY,d2i_RSAPrivateKey和d2i_RSAPublicKey返回NULL

时间:2016-04-22 18:40:22

标签: c openssl rsa

我使用以下命令创建了一个RSA私钥:

    if ( isset( $session ) ) {
  // graph api request for user data
  $request = new FacebookRequest( $session, 'GET', '/me' );
  $response = $request->execute();
  // get response
  $graphObject = $response->getGraphObject();
        $fbid = $graphObject->getProperty('id');              // To Get Facebook ID
        $fbfullname = $graphObject->getProperty('name'); // To Get Facebook full name
        $femail = $graphObject->getProperty('email');    // To Get Facebook email ID
    /* ---- Session Variables -----*/
        $_SESSION['FBID'] = $fbid;           
        $_SESSION['FULLNAME'] = $fbfullname;
        $_SESSION['email'] =  $femail;
        $args = array('scope' => 'email');
        $_SESSION["args"] = $args;
    /* ---- header location after session ----*/
  header("Location: ../");
} else {
  $loginUrl = $helper->getLoginUrl();
 header("Location: ".$loginUrl);
}
?>

我必须为这个项目使用DER编码密钥(PKCS#1),所以我从这个PEM编码的私钥文件中生成了两个DER文件 - 一个带有私钥,另一个带有公钥。

 openssl genrsa -out keypair.pem 2048

在我的代码中,我将这两个文件的内容加载到char *变量中。

以下任何一项都无法按预期工作:

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

我知道因为所有人都返回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); 。我也尝试了以下内容:

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

我做错了什么?

1 个答案:

答案 0 :(得分:3)

TLDR d2i_RSA_PUBKEYd2i_RSAPrivateKey应该有效,并且在Unix上为我做。

你说你想要'DER编码密钥(PKCS#1)'。

对于publickeys,OpenSSL通常使用X.509中定义的格式为SubjectPublicKeyInfo,其中包含AlgorithmIdentifier plus (已编辑)BIT STRING,其中包含一个publickey值根据算法而变化的结构。对于RSA,algid包含标识RSA且没有参数的OID;依赖于算法的结构是PKCS#1。

相比之下,OpenSSL支持两种类型的私钥格式:每种算法都有一种“遗留”格式(DH除外),对于RSA,它是PKCS#1;和PKCS#8定义的通用格式(如SPKI)由AlgorithmIdentifier加上依赖于算法的私钥值组成,这次是OCTET STRING。 PKCS#8还有一个加密密钥的选项,SPKI没有或不需要。

OpenSSL的旧部分,包括genrsarsa命令行实用程序,使用旧的私钥格式,但是OpenSSL命名为PUBKEY的SPKI公钥格式。因此,您的rsa命令创建了一个可由d2i_RSA_PUBKEY读取的publickey文件,但不是d2i_RSAPublicKey(只是PKCS#1部分)和d2i_RSAPrivateKey可读的私钥文件。

如果您确实需要'裸'PKCS#1格式的publickey,rsa实用程序有选项-RSAPublicKey_in-RSAPublicKey_out来读取和写入此格式自1.0.0以来,尽管已记录仅在最近,仍未在帮助信息中。该文件可由d2i_RSAPublicKey读取,但不能由d2i_RSA_PUBKEY读取。

一种可能性:您没有提及操作系统。 DER文件是二进制的,而在C中正确处理Windows上的二进制文件,您必须使用fopen修饰符b,这里您需要"rb"来读取二进制文件。如果我在Unix上运行你的代码它可以工作,但要在Windows上获得正确的结果我必须添加b

也是一个小问题:你谈论'加载内容......在char *变量中'。实际上,您将文件内容加载到内存中并使用char *变量指向它们。严格来说,OpenSSL d2i例程需要const unsigned char *变量的地址 - 并且您的编译器应该至少警告您这种不匹配,如果您在符合标准的模式下运行它。但是C需要指向所有char种类(signed unsigned和'plain')的指针,无论有没有限定条件,都具有相同的表示和对齐要求,即使它们不兼容如标准中所定义,因此将char **传递到预期const unsigned char **的位置确实有效。