如何使用OpenSSL计算RSA公钥指纹?

如何使用OpenSSL计算RSA公钥指纹?,openssl,rsa,rsa-key-fingerprint,Openssl,Rsa,Rsa Key Fingerprint,我有一个EVP_PKEY结构中的RSA公钥(从PEM文件加载,以------开始公钥------)。现在,我希望能够使用OpenSSL API显示代码中该密钥的指纹。(目的是允许操作员在信任JWT之前使用RS256验证其密钥) 不幸的是,我找到的所有资源要么在命令行上使用ssh-keygen,要么对X.509证书进行指纹识别,而不是公钥 那么,如何使用OpenSSL API获取存储在EVP_PKEY结构中的公钥的RSA公钥指纹呢 在我自己的代码(C++)中,我使用了下面的方法,它接受一个EVP_

我有一个EVP_PKEY结构中的RSA公钥(从PEM文件加载,以------开始公钥------)。现在,我希望能够使用OpenSSL API显示代码中该密钥的指纹。(目的是允许操作员在信任JWT之前使用RS256验证其密钥)

不幸的是,我找到的所有资源要么在命令行上使用ssh-keygen,要么对X.509证书进行指纹识别,而不是公钥

那么,如何使用OpenSSL API获取存储在EVP_PKEY结构中的公钥的RSA公钥指纹呢

在我自己的代码(C++)中,我使用了下面的方法,它接受一个EVP_PKEY对象并返回一个RSA对象:

using evp_pkey_ptr = std::unique_ptr<EVP_PKEY>;
using rsa_ptr = std::unique_ptr<RSA>;

rsa_ptr evp_get_rsa(const evp_pkey_ptr& evp) {
  RSA * rsa = EVP_PKEY_get1_RSA(evp.get());
  return rsa_ptr(rsa);
}

虽然我仍然不确定这是否是“官方方式”/(适用于写“这是钥匙的指纹”),但我在“Deutsches Forschungsnetz”()找到了一个参考,在那里他们使用钥匙模数的散列

十六进制表示中的模数可以通过
BN_bn2hex(rsa.n)
从PRSA获取,并且必须以“模数=”作为前缀,并以CR/LF作为后缀,以产生与命令行相同的输出。 这是我得到的Delphi代码:

function GetRsaModulusFingerprint(theRsa: PRSA; md: PEVP_MD; useLowerCase:
    Boolean; const separator: string): string;
var
  len: integer;
  modulusStr: PAnsiChar;
  buff: AnsiString;
  mdValue: array [0..EVP_MAX_MD_SIZE-1] of Byte;
  ctx: EVP_MD_CTX;
  mdLen: Cardinal;
  I: Integer;
begin
  // This func should produce same result as commandline
  // for public key:
  //  openssl rsa -noout -modulus -pubin -in server.pubkey |openssl sha256 -c
  // for private key:
  //  openssl rsa -noout -modulus -in server.privkey |openssl sha256 -c

  Result := '';
  if not Assigned(theRsa) then
    Exit;

  // get hex representation of modulus
  modulusStr := BN_bn2hex(theRsa.n);
  // bring it in same format as commanline
  buff := 'Modulus='+ AnsiString(modulusStr) + #13#10;
  // and free the string returned by BN_bn2hex using OPENSSL_free
  // (in openSSL1.0.2r crypto.h OPENSSL_free is a macro pointing to CRYPTO_free)
  CRYPTO_free(modulusStr);

  // calculate hash
  len := length(buff);
  if len >= 0 then
  begin
    EVP_MD_CTX_init(@ctx);
    EVP_DigestInit_ex(@ctx, md, nil);
    EVP_DigestUpdate(@ctx, PAnsiChar(buff), len);
    EVP_DigestFinal_ex(@ctx, @mdValue[0], mdLen);
    EVP_MD_CTX_cleanup(@ctx);

    //output as hex with separator
    result := '';
    if mdLen > 0 then
      result := IntToHex(mdValue[0]);
    for I := 1 to mdLen-1 do
      result := result + separator + IntToHex(mdValue[I]);

    if useLowerCase then
      result := result.ToLower();
  end;
end;

谢谢你的回答。这给了我openSSL内部RSA结构,但没有指纹。我知道指纹基本上是密钥的散列,但我不知道必须给EVP_Digest函数的密钥的确切格式。提示:EVP_PKEY_get1_rsa返回的rsa结构必须在之后释放()
function GetRsaModulusFingerprint(theRsa: PRSA; md: PEVP_MD; useLowerCase:
    Boolean; const separator: string): string;
var
  len: integer;
  modulusStr: PAnsiChar;
  buff: AnsiString;
  mdValue: array [0..EVP_MAX_MD_SIZE-1] of Byte;
  ctx: EVP_MD_CTX;
  mdLen: Cardinal;
  I: Integer;
begin
  // This func should produce same result as commandline
  // for public key:
  //  openssl rsa -noout -modulus -pubin -in server.pubkey |openssl sha256 -c
  // for private key:
  //  openssl rsa -noout -modulus -in server.privkey |openssl sha256 -c

  Result := '';
  if not Assigned(theRsa) then
    Exit;

  // get hex representation of modulus
  modulusStr := BN_bn2hex(theRsa.n);
  // bring it in same format as commanline
  buff := 'Modulus='+ AnsiString(modulusStr) + #13#10;
  // and free the string returned by BN_bn2hex using OPENSSL_free
  // (in openSSL1.0.2r crypto.h OPENSSL_free is a macro pointing to CRYPTO_free)
  CRYPTO_free(modulusStr);

  // calculate hash
  len := length(buff);
  if len >= 0 then
  begin
    EVP_MD_CTX_init(@ctx);
    EVP_DigestInit_ex(@ctx, md, nil);
    EVP_DigestUpdate(@ctx, PAnsiChar(buff), len);
    EVP_DigestFinal_ex(@ctx, @mdValue[0], mdLen);
    EVP_MD_CTX_cleanup(@ctx);

    //output as hex with separator
    result := '';
    if mdLen > 0 then
      result := IntToHex(mdValue[0]);
    for I := 1 to mdLen-1 do
      result := result + separator + IntToHex(mdValue[I]);

    if useLowerCase then
      result := result.ToLower();
  end;
end;