' dgst验证并签名'相当于' RSA_Verify()'

时间:2015-04-09 23:19:07

标签: openssl rsa sign sha verify

我正在使用RSA_verify()函数来验证我使用openssl程序(通​​过控制台)签名的SHA。 RSA_verify()总是返回一个非成功的验证,所以我认为我发送的参数不正确。

以下控制台命令在Linux Ubuntu中使用OpenSSL 0.9.8k运行。

据我记得,使用OpenSSL 1.0.1 ... c为Android编译了C函数。它肯定是1.0.1(我们正在更新它以避免Heartbleed问题)。

这就是我所做的......请原谅任何错误,因为我自己也在学习。

  1. 生成私钥

    openssl genrsa -out private.key 2048
    
  2. 从私钥中提取公钥

    openssl rsa -in private.key -out public.key -outform PEM -pubout
    
  3. 从名为permissions的文件计算SHA,然后使用private.key对其进行签名,输出将为SHA但具有RSA加密(permissions.sign)

    openssl dgst -sha256 -sign private.key -out permissions.sign permissions
    
  4. 根据权限文件验证收到的SHA签名(它在Ubuntu控制台中是否成功)

    openssl dgst -sha256 -verify public.key -signature permissions.sign permissions
    
  5. 我将权限文件,permissions.sign文件和public.key文件复制到Android中的文件系统。

  6. 我验证了permissions.sign是使用权限和匹配的private.key创建的...所有这些都与我的public.key一起使用(我没有Android中的私钥)。< / p>

  7. 这是C函数。

    #include <openssl/pem.h>
    #include <openssl/rsa.h>
    #include <openssl/sha.h>
    
    ...
    
    /* Initialize the public key */
    RSA *pub_key = RSA_new();
    
    if(NULL == pub_key)
    {
       ANDROID_LOGE("RSA_new failed");
       result = 0;
    }
    else
    {
       FILE* fp = fopen(public_key, "r");
    
       if(NULL == fp)
       {
          ANDROID_LOGE_P("fopen [%s] failed", public_key);
          result = 0;
       }
       else
       {
          /* Read it from the passed path */
          if(PEM_read_RSA_PUBKEY(fp, &pub_key, NULL, NULL) == NULL)
          {
             ANDROID_LOGE_P("[%s] can't be read", public_key);
             result = 0;
             fclose(fp);
          }
          else
          {
             /* Verify the file and its SHA with the public key */
             int verified = RSA_verify(
                 NID_sha256,
                 file, /* message digest (message to validate) */
                 file_size, /* message size */
                 sign, /* signature (signed SHA) */
                 sign_size, /* signature size */
                 pub_key);
             ANDROID_LOGD("NID_sha256");
    
             if(verified)
             {
                result = 1;
                ANDROID_LOGD_P("[%s] is valid", file_to_verify);
             }
             else
             {
                ANDROID_LOGE_P("[%s] is NOT valid", file_to_verify);
             }
    
             fclose(fp);
          }
    
          RSA_free(pub_key);
       }
    }
    
    • public_key是public.key
    • 的路径
    • PEM_read_RSA_PUBKEY成功
    • 我认为NID_sha256应该用于验证
    • file是一个包含权限内容的字节数组
    • file_size是文件的数组大小
    • sign是一个字节数组,其内容为permissions.sign
    • sign_size是符号的数组大小
    • RSA_verify()失败,返回0

    所以问题是,它是否正确:

    • 使用我使用的命令生成密钥,

    • 签署权限文件(生成permissions.sign),

    • 然后尝试使用PEM_read_RSA_PUBKEY()和RSA_verify()验证文件?

    我用于签名过程的命令是否等同于我用于验证过程的C函数?

    如果需要更多信息或我可以在哪里学习更多信息,请告诉我。

    谢谢!

    编辑:我在调用RSA_Verify()之后添加了一些错误打印:

    ANDROID_LOGE_P(&#34; openssl:%s&#34;,ERR_reason_error_string(ERR_get_error()));

    打印:

    openssl:bad signature

    仍在调查。

1 个答案:

答案 0 :(得分:2)

我的公钥读取过程中有几个缺失的步骤。

生成私钥和公钥的正确命令如下:

生成私钥  “openssl genrsa -out private.key 2048”

从私钥中提取公钥(DER证书表单)(RSA_SHA_Verify()需要)  “openssl req -outform DER -new -x509 -key private.key -out public.key -days 30000”

生成没有证书信息的公钥(只有“openssl dgst -sha1 -verify ...”需要)  “openssl x509 -inform DER -in public.key -pubkey -noout&gt; public_no_cert.key”

使用私钥对文件进行签名  “openssl dgst -sha1 -sign private.key -out permissions.sign permissions”

使用公钥验证文件(无证书信息)  “openssl dgst -sha1 -verify public_no_cert.key -signature permissions.sign permissions”

有关详细信息,请参阅OpenSSL.org上的文档。我需要一个持有公钥的X509 DER证书来验证带有RSA_verify()的签名SHA。

RSA_verify()的命令模式的等效性是:

openssl dgst -sha1 -verify public.key -signature permissions.sign permissions

有关代码来源,请参阅此链接: http://www.bmt-online.org/geekisms/RSA_verify

它不会乍一看,你必须调整它。按如下方式调用其中的函数:

   result = sign_data(
         input_file_buffer,
         input_file_size,
         private_key_buffer,
         private_key_size,
         (void**)&signature,
         &signature_size);

   result = verify_data(
         input_file_buffer,
         input_file_size,
         signature_buffer,
         signature_size,
         public_key_buffer,
         public_key_size);

一切都必须在RAM中,将它们作为指针传递。

签名函数需要指向指针(**)的指针将签名的SHA保存到其中。您可以稍后将其保存到文件中。

在Ubuntu openssl 0.9.8k下测试。

如果您发现缺少某些内容,请告知我们。谢谢你的阅读!

编辑:这是源代码的链接...... http://migsantiago.com/index.php/tutoriales/32-firma-y-valida-archivos-con-openssl