将命令行从Openssl转换为C ++

时间:2019-12-10 18:06:53

标签: c++ openssl

我有一个用于OpenSSL的命令行:

openssl pkeyutl -inkey private.key -sign -in b64.dat -pkeyopt digest:SHA256 -out result.dat

我想使用C ++和OpenSSL库进行编码。 对于CURL,有一条诸如--libcurl code.c之类的指令,它以给定命令的C语言输出等效代码,这可以节省大量时间。

OpenSSL中是否存在这种情况?如果没有,该命令等效于什么?

2 个答案:

答案 0 :(得分:0)

为了对已经散列的字符串进行签名,我们可以使用EVP_PKEY_sign; 此处的私钥必须是带有PEM格式的解密私钥的字符串。

将结果写入文件result.dat中,我们可以base64 result.dat(在Linux中)获得有效的签名。

RSA* createPrivateRSA(std::string key) {
  RSA *rsa = NULL;
  const char* c_string = key.c_str();
  BIO * keybio = BIO_new_mem_buf((void*)c_string, -1);
  if (keybio==NULL) {
      return 0;
  }
  rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
  return rsa;
}

void sellar(std::string hashclear, std::string privateKey_string){

  EVP_PKEY_CTX *ctx;
  /* md is a SHA-256 digest in this example. */
  unsigned char *sig;
  size_t siglen;

  unsigned char clear_message[hashclear.length()];
  strcpy((char*) clear_message,hashclear.c_str());
  size_t mdlen;
  // //1. Decodificar hashclear. || base64 -d data.dat > b64.dat -> Me debe dar una cadena de 32 bytes.
  unsigned char * md = base64_decode(clear_message, strlen((char*) clear_message), &mdlen);
  std::cout << "MD is " << mdlen << " bytes long.\n";
  // //2. Cargar llave privada.
  RSA* privateRSA = createPrivateRSA(privateKey);
  EVP_PKEY* signing_key  = EVP_PKEY_new();

  EVP_PKEY_assign_RSA(signing_key, privateRSA);

  ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */);
  if(!ctx) {
    std::cout << "Error CTX_new" << std::endl;
    return;
  }
  if (EVP_PKEY_sign_init(ctx) <= 0){
    std::cout << "Error sign_init\n";
    return;
  }
 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0){
    std::cout << "Error set_rsa_padding\n";
    return;
 }
 if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0){
    std::cout << "Error set_signature_md\n";
    return;
 }

 /* Determine buffer length */
 if (EVP_PKEY_sign(ctx, NULL, &siglen, md, mdlen) <= 0){
    std::cout << "Error PKEY_sign\n";
    return;
 }
 sig = (unsigned char*)OPENSSL_malloc(siglen);

 if (!sig){
    std::cout << "Error malloc";
    return;
 }

 if (EVP_PKEY_sign(ctx, sig, &siglen, md, mdlen) <= 0){
    std::cout << "Error sign";
    return;
 }
 std::cout << siglen << " bytes written in buffer sig\n";
 /* Signature is siglen bytes written to buffer sig */
 size_t cadena_sellada_len;
 unsigned char * cadena_sellada = base64_encode(sig, siglen, &cadena_sellada_len);

 std::ofstream myfile ("result_final.dat");
 if (myfile.is_open())
  {
    for(int count = 0; count < cadena_sellada_len; count ++){
        myfile << cadena_sellada[count] ;
    }
    myfile.close();
  }
  else std::cout << "Unable to open file";
}

答案 1 :(得分:-2)

  

OpenSSL中是否存在这种情况?

是的,像openssl本身一样使用libssl和libcrypto(具有特定于平台的名称)-但据我了解,如果愿意,最好使用this这样的c ++准备的库正确地做。

  

如果没有,那么此命令等效于什么?

也是-如果我对您没错,您正在搜索类似的内容

#include <iostream> 

int main () 
{ 

    system("openssl pkeyutl -inkey private.key -sign -in b64.dat -pkeyopt digest:SHA256 -out result.dat"); //in one line
    return 0; 
} 

“系统”在从其开始的终端中将c ++字符串转换为bash代码,并且效果很好。

希望对您有所帮助:)如果您需要第一个示例的进一步帮助,我可以编辑我的帖子-请就您的需要发表评论。

此外,如果您获得了正确的答案,请避免将您的问题检查为已解决,以避免它出现在stackoverflow.com的“未解决”部分;)