【问题标题】:Initailzing EVP_PKEY(in opensssl) from public key given by 'google inapp billing'从“google inapp billing”给出的公钥初始化 EVP_PKEY(在 openssl 中)
【发布时间】:2013-11-01 04:27:40
【问题描述】:

我打算在服务器端实现的 c 或 c++ 中验证“google inapp billing signature”

我通过php找到了方法(Android in-app billing signature verification in php server) 并建议它可以在 openssl 中使用 EVP_Verify... 函数..但是 使用:

int EVP_VerifyFinal(EVP_MD_CTX *ctx,unsigned char *sigbuf, unsigned int siglen,EVP_PKEY *pkey);

它需要 'EVP_PKEY* pkey' 结构的实例作为参数...但我没有!

我相信有办法将“Google InApp Billing 签名字符串(带有 PKCS#1 填充的 base64 编码 SHA1-with-RAS 签名)”转换为 EVP_PKEY..但我不知道该怎么做。

如何将它作为 EVP_VerifyFinal 函数的参数传递??

int main()
{
    OPENSSL_config(NULL);
    OpenSSL_add_all_digests();
    ERR_load_crypto_strings();

    EVP_MD_CTX* ctx = EVP_MD_CTX_create();
    const EVP_MD* md = EVP_get_digestbyname("SHA1");
    if(0 == EVP_VerifyInit_ex(ctx, md, NULL))
    {
        std::cerr << "init error" << std::endl;
        return 0;
    }

    const char* data = "{\"orderId\":\"12999763169054705758.1310724241212373\",\"packageName\":\"com.company.game.google\",\"productId\":\"game_product_001\",\"purchaseTime\":1358227642000,\"purchaseState\":0,\"developerPayload\":\"12322144\",\"purchaseToken\":\"}";
    if(0 == EVP_VerifyUpdate(ctx, (void*)data, strlen(data)))
    {
        std::cerr << "update error" << std::endl;
        return 0;
    }

    const char* key_context = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh0UDlUA1aYPvfRFq6qUjDVG/fi5EetC6LsjdT/WNmHUAy0muvuOTFfQEzBoELciDfh23VXgwVnb/XsfuvQrCgtnQbuMKsj+sDhofLjeq8TznEMlQcJ//0LsGSM8rRVHw72BYA2mSVKi04k1GIicB9J25c2f+eIwF7lEWJlWqVDlNqOS7GIIjnq3HPhqki3ZRSA9c";

    EVP_PKEY* pub_key = EVP_PKEY_new();
    if(NULL == pub_key)
    {
        std::cerr << "evp_pkey new error" << std::endl;
        return 0;
    }

    // I have to call 'EVP_VerifyFinish' here!! but I don't know how to!!
    ERR_remove_state(0);
    ERR_free_strings();

    return 0;
}

请有人帮助我!!

【问题讨论】:

    标签: openssl


    【解决方案1】:

    代码未经测试,但应该是这样的:

    BIO *mem= BIO_new(BIO_s_mem());
    BIO_puts(mem, "your data");
    RSA *cipher;
    PEM_read_bio_RSAPublicKey(mem, &cipher, NULL, NULL);
    EVP_PKEY *pkey  = EVP_PKEY_new();
    EVP_PKEY_set1_RSA(pkey, cipher);
    

    【讨论】:

      【解决方案2】:

      感谢您的回答.. 但我像下面那样做了.. (它可以找到..我已经测试过!!)

      ps。代码中的Base64Decode函数..您可以在互联网上找到很多来源..

      int Verify_GoogleInappBilling_Signature(const char* data, const char* signature, const char* pub_key_id)
      {
          std::shared_ptr<EVP_MD_CTX> mdctx = std::shared_ptr<EVP_MD_CTX>(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
          const EVP_MD* md = EVP_get_digestbyname("SHA1");
          if(NULL == md)
          {
              return -1;
          }
          if(0 == EVP_VerifyInit_ex(mdctx.get(), md, NULL))
          {
              return -1;
          }
      
          if(0 == EVP_VerifyUpdate(mdctx.get(), (void*)data, strlen(data)))
          {
              return -1;
          }
      //!!!!!!!!!!!!!!!!!!!
          std::shared_ptr<BIO> b64 = std::shared_ptr<BIO>(BIO_new(BIO_f_base64()), BIO_free);
          BIO_set_flags(b64.get(),BIO_FLAGS_BASE64_NO_NL);
      
          std::shared_ptr<BIO> bPubKey = std::shared_ptr<BIO>(BIO_new(BIO_s_mem()), BIO_free);
          BIO_puts(bPubKey.get(),pub_key_id);
          BIO_push(b64.get(), bPubKey.get());
      
          std::shared_ptr<EVP_PKEY> pubkey = std::shared_ptr<EVP_PKEY>(d2i_PUBKEY_bio(b64.get(), NULL), EVP_PKEY_free);
      //!!!!!!!!!!!!!!!!!!!
          std::string decoded_signature = Base64Decode(std::string(signature));
          return EVP_VerifyFinal(mdctx.get(), (unsigned char*)decoded_signature.c_str(), decoded_signature.length(), pubkey.get());
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-28
        • 1970-01-01
        • 2011-12-12
        • 2013-08-11
        • 2014-10-21
        • 1970-01-01
        相关资源
        最近更新 更多