bpki.h(3)
okay so bestie, sit down, hydrate, grab a snack 🍓 — this is bpki.h(3) from the Library Functions Manual, and it is lowkey way more interesting than the title makes it sound. no cap. 💅
✨ NAME ✨
bpki.h — Механизмы СТБ 34.101.78 (bpki).
aka: this header is where the СТБ 34.101.78 mechanisms live. that's the whole vibe. 💜
🎀 SYNOPSIS 🎀
#include 'bee2/defs.h'
💖 ФУНКЦИИ 💖 — the functions, obvi
err_t bpkiPrivkeyWrap (octet epki[], size_t *epki_len, const octet privkey[], size_t privkey_len, const octet pwd[], size_t pwd_len, const octet salt[8], size_t iter)— creating a container with a private key inside 🫙✨err_t bpkiPrivkeyUnwrap (octet privkey[], size_t *privkey_len, const octet epki[], size_t epki_len, const octet pwd[], size_t pwd_len)— parsing (taking apart) a container with a private key 🔓err_t bpkiShareWrap (octet epki[], size_t *epki_len, const octet share[], size_t share_len, const octet pwd[], size_t pwd_len, const octet salt[8], size_t iter)— creating a container with a partial secret 🧩err_t bpkiShareUnwrap (octet share[], size_t *share_len, const octet epki[], size_t epki_len, const octet pwd[], size_t pwd_len)— parsing a container with a partial secret 🔍err_t bpkiCSRRewrap (octet csr[], size_t csr_len, const octet privkey[], size_t privkey_len)— re-issuing a certificate signing request 🔁err_t bpkiCSRUnwrap (octet pubkey[], size_t *pubkey_len, const octet csr[], size_t csr_len)— parsing a certificate signing request 📜
🌈 ПОДРОБНОЕ ОПИСАНИЕ 🌈 — the full tea, no skimming
So what actually got implemented here? Some specific СТБ 34.101.78 (bpki) mechanisms:
- managing containers with private keys from СТБ 34.101.45 (
bign); - managing containers with partial secrets from СТБ 34.101.60 (
bels).
Bonus round 🎁 — you can also drop private keys from the bign96 digital signature system (see bign.h) into a container, with the long-term parameters bign-curve192v1.
And another bonus: re-issuing of certificate requests got implemented too (Cerificate Signing Request, CSR). 🔁
The format of a container with a private key is described by the EncryptedPrivateKeyInfo type, which is defined in PKCS#8 (RFC 5208). Keeping that container safe is the PBKDF2 mechanism's job, and PBKDF2 is defined in PKCS#5 (RFC 8018). СТБ 34.101.78 is the one that pins down the exact format and the exact mechanism. 📜
PBKDF2's secret parameter is a password. And to raise the guarantees of protection, a full-fledged key can play the role of that password. That key gets split into partial secrets, which are also saved in EncryptedPrivateKeyInfo containers while being protected by ordinary passwords. 🧩
Splitting into partial secrets uses the standard bels parameters — standard public keys, in particular. The public key number (a number from 1 to 16) is encoded as an octet and tacked onto the front of the partial secret. That's exactly why the length of a partial secret in octets is one more than the standard length: 17 instead of 16, 25 instead of 24, and 33 instead of 32. 🔢
The certificate request format is defined in СТБ 34.101.17 (PKCS#10). A request contains the identification data of the certificate's future owner, their public key, technical extensions, and a signature over all of those fields made on the private key. The identification data, the public key, and some extensions get carried over into the certificate. The signature proves possession of the certificate's public key, i.e. knowledge of the corresponding private key. And re-issuing a request lets you prove possession on a new key pair while keeping the (bulky) identification data and extensions. 📝
💀 Ожидается ERR_BAD_INPUT 💀
(that's "ERR_BAD_INPUT is expected", for the non-Russian speakers in the chat)
All input pointers are valid. The exception is cases where a null pointer is passed as a request to determine the amount of memory that needs to be reserved on a repeated call (the [len?]ptr construct). 🙈
🎀 Функции (FUNCTIONS) 🎀
okay bestie, deep breath, this is the ✨function era✨ of the page. six of them. all err_t. all here. let's go 💅
🦋 bpkiCSRRewrap
err_t bpkiCSRRewrap (octet csr[], size_t csr_len, const octet privkey[],
size_t privkey_len)
so the vibe here is a glow-up for a request: a brand-new public key gets built out of the private key [privkey_len]privkey, that new public key gets embedded into the certificate issuance request [csr_len]csr, and then the request gets signed on privkey. rewrap. iconic. ✨
- Expected
ERR_NOT_IMPLEMENTED—privkey_len == 32. - Expected
ERR_BAD_FORMAT— the request format matches СТБ 34.101.17. - Expected
ERR_BAD_FORMAT— the request uses the standard long-term parametersbign-curve256v1and the algorithmbign-with-hbelt.
Returns
ERR_OK if the request was successfully re-issued, and an error code otherwise.
Arguments
csr[in/out] — the certificate issuance requestcsr_len— the length ofcsrprivkey— the private keyprivkey_len— the length ofprivkey
🧚 bpkiCSRUnwrap
err_t bpkiCSRUnwrap (octet pubkey[], size_t * pubkey_len, const octet csr[],
size_t csr_len)
the reverse move, periodt: the signature of the certificate issuance request [csr_len]csr gets checked against the public key that's embedded right inside that request. if it checks out, the public key [pubkey_len?]pubkey gets extracted from the request. so satisfying 🫶
- Expected
ERR_BAD_FORMAT— the request format matches СТБ 34.101.17. - Expected
ERR_BAD_FORMAT— the request uses the standard long-term parametersbign-curve256v1and the algorithmbign-with-hbelt.
Returns
ERR_OK if the parsing went through, and an error code otherwise.
Arguments
pubkey— the public keypubkey_len— the length ofpubkeycsr— the certificate issuance requestcsr_len— the length ofcsr
💜 bpkiPrivkeyUnwrap
err_t bpkiPrivkeyUnwrap (octet privkey[], size_t * privkey_len, const octet epki[],
size_t epki_len, const octet pwd[], size_t pwd_len)
out of the container [epki_len]epki we pull the private key [privkey_len?]privkey, which has been protected using the PBKDF2 mechanism. the protection comes off with the password [pwd_len]pwd. 💖
Returns
ERR_OK if the private key was successfully extracted, and an error code otherwise.
Note. formally, to figure out the lengthprivkey_lenof the private key you have to strip the protection, and to do that you have to hand over the password. so thepwdpointer must be valid even when theprivkeypointer is null, i.e. during the query of theprivkey_lenlength. this does not take into account that the private key length can be determined indirectly from the container length. 😭
Arguments
privkey— the private keyprivkey_len— the length ofprivkeyepki— the container with the private keyepki_len— the length ofepkipwd— the passwordpwd_len— the length ofpwd
🌸 bpkiPrivkeyWrap
err_t bpkiPrivkeyWrap (octet epki[], size_t * epki_len, const octet privkey[],
size_t privkey_len, const octet pwd[], size_t pwd_len, const octet salt[8],
size_t iter)
now we're making the container: [epki_len?]epki gets created holding the protected private key [privkey_len]privkey. the key is protected with the password [pwd_len]pwd. the protection mechanism is PBKDF2, with the synchronization seed ("salt") salt and the iteration count iter. chef's kiss 🔥
- Expected
ERR_BAD_PRIVKEY—privkey_len ∈ {32, 48, 64}. - Expected
ERR_BAD_INPUT—iter >= 10000.
Returns
ERR_OK if the container was successfully created, and an error code otherwise.
Note. whenepkiis null, theprivkey,pwdandsaltpointers may be null. ✨
Arguments
epki— the container with the private keyepki_len— the length ofepkiprivkey— the private keyprivkey_len— the length ofprivkeypwd— the passwordpwd_len— the length ofpwdsalt— the PBKDF2 synchronization seed ("salt")iter— the number of iterations in PBKDF2
👑 bpkiShareUnwrap
err_t bpkiShareUnwrap (octet share[], size_t * share_len, const octet epki[],
size_t epki_len, const octet pwd[], size_t pwd_len)
out of the container [epki_len]epki we pull the partial secret [share_len?]share, which has been protected using the PBKDF2 mechanism. the protection comes off with the password [pwd_len]pwd. same energy, different secret 🦋
- Expected
ERR_BAD_SECKEY— ifshare != 0, then1 <= share[0] <= 16.
Returns
ERR_OK if the partial secret was successfully extracted, and an error code otherwise.
Note. formally, to figure out the lengthshare_lenof the partial secret you have to strip the protection, and to do that you have to hand over the password. so thepwdpointer must be valid even when thesharepointer is null, i.e. during the query of theshare_lenlength. this does not take into account that the partial secret length can be determined indirectly from the container length. 💀
Arguments
share— the partial secretshare_len— the length ofshareepki— the container with the partial secretepki_len— the length ofepkipwd— the passwordpwd_len— the length ofpwd
🌈 bpkiShareWrap
err_t bpkiShareWrap (octet epki[], size_t * epki_len, const octet share[],
size_t share_len, const octet pwd[], size_t pwd_len, const octet salt[8],
size_t iter)
and the wrap for the partial secret: the container [epki_len?]epki gets created holding the protected partial secret [share_len]share. the key is protected with the password [pwd_len]pwd. the protection mechanism is PBKDF2, with the synchronization seed ("salt") salt and the iteration count iter. 💅
- Expected
ERR_BAD_SHAREKEY—share_len ∈ {17, 25, 33}. - Expected
ERR_BAD_SHAREKEY— ifshare != 0, then1 <= share[0] <= 16. - Expected
ERR_BAD_INPUT—iter >= 10000.
Returns
ERR_OK if the container was successfully created, and an error code otherwise.
Note. in the prefix of the partial secret, the number of the corresponding public key is written (from the standard list of public keys). the public key is used when the key is assembled from the partial secrets. 🧠✨
Note. whenepkiis null, theshare,pwdandsaltpointers may be null.
Arguments
epki— the container with the partial secretepki_len— the length ofepkishare— the partial secretshare_len— the length ofsharepwd— the passwordpwd_len— the length ofpwdsalt— the PBKDF2 synchronization seed ("salt")iter— the number of iterations in PBKDF2
🌟 Автор (AUTHOR) 🌟
Automatically created by Doxygen for Библиотека Bee2 from the source text. 🤖💖
aaaand that's the whole page bestie, you ate it 💅 the whole thing ships from Библиотека Bee2, dated Вс 25 Янв 2026 00:00:00, and it lives at bpki.h(3). go forth and rewrap some requests 🫶🎀
📦 where this page comes from
- fedora 44: bee2-devel 2.2.0-1.fc44 · GPL-3.0-only and GPL-3.0-or-later
- fedora 44: bee2-devel 2.2.0-1.fc44 · GPL-3.0-only and GPL-3.0-or-later
- 💖 girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms