Закрепление открытого ключа HTTP (HPKP) без Openssl - PullRequest
0 голосов
/ 15 мая 2019

Я планирую сгенерировать следующий pin-sha256:

Public-Key-Pins: 
  pin-sha256="cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs="; 
  pin-sha256="M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="; 
  max-age=5184000; includeSubDomains; 
  report-uri="https://www.example.org/hpkp-report"

, чтобы я мог оставить его в IIS по соображениям безопасности, как показано ниже:

<system.webServer>
  ...

  <httpProtocol>
    <customHeaders>
      <add name="Public-Key-Pins" value="pin-sha256=&quot;base64+primary==&quot;; pin-sha256=&quot;base64+backup==&quot;; max-age=5184000; includeSubDomains" />
    </customHeaders>
  </httpProtocol>

  ...
</system.webServ

Но моему серверу не хватает open sslи занимает много времени для установки из-за проблем с процессом.

Не могли бы вы сообщить мне, есть ли какая-нибудь альтернатива без этих openssl, что я могу генерировать контакты?

См. эту ссылку для получения дополнительной информациидетали

Это команды генерации контактов, мне нужно это сделать без openssl, это возможно?

openssl rsa -in my-rsa-key-file.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

1 Ответ

0 голосов
/ 16 мая 2019

Вот пример приведенной выше цепочки команд openssl, преобразованной в вызовы API openssl, которые выводят результат base64 на экран.

Основные звонки

  • PEM_read_bio_PrivateKey для чтения в закрытом ключе в формате PEM.
  • i2d_RSA_PUBKEY_bio для преобразования открытого ключа RSA в формат DER
  • EVP_Digest для создания дайджеста SHA256 (скрыто за использованием BIO_f_md BIO)
  • BIO_f_base64 Использование BIO для преобразования дайджеста в формат base64

Существует множество способов выполнить одну и ту же работу, используя варианты API OPENSSL, описанных выше, в зависимости от вашей ситуации.

Ниже приведено использование C ++ OpenSSL C API. При необходимости вы можете легко удалить биты C ++.

template<typename T, typename D>
std::unique_ptr<T, D> make_handle(T* handle, D deleter)
{
    return std::unique_ptr<T, D>{handle, deleter};
}

bool load_rsa_private_key_and_base64_sha256_hash_public_key()
{
    // load rsa private key in PEM format
    auto bio = make_handle(BIO_new_file("privatekey.pem", "rb"), BIO_free);
    if(!bio) return false;
    auto const key = make_handle(PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, (void*)("password")), EVP_PKEY_free);
    bio.reset();

    if(!key) return false;

    // extract private key from loaded certificate
    auto const rsa = EVP_PKEY_get0_RSA(key.get());
    if (!rsa) return false;

    // setup sha256 bio chain
    auto const bmd = make_handle(BIO_new(BIO_f_md()), BIO_free);
    if(!bmd) return false;
    if (!BIO_set_md(bmd.get(), EVP_sha256())) return false;

    auto const null_bio = make_handle(BIO_new(BIO_s_null()), BIO_free);
    auto in = BIO_push(bmd.get(), null_bio.get());

    // write RSA Public Key into DER format to the SHA256 digest BIO chain
    i2d_RSA_PUBKEY_bio(in, rsa);

    // extract the SHA256 digest
    auto mdtmp = BIO_find_type(in, BIO_TYPE_MD);
    if (!mdtmp) return false;
    std::array<char, EVP_MAX_MD_SIZE> buffer;
    auto const length = BIO_gets(mdtmp, buffer.data(), buffer.size());

    if(length <= 0)  return false;

    // convert the digest to base64 and output to the stdio
    auto const b64 = make_handle(BIO_new(BIO_f_base64()), BIO_free);
    auto const bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
    auto out = BIO_push(b64.get(), bio_out);

    BIO_write(out, buffer.data(), length);
    BIO_flush(out);

    return true;
}
...