Skip to content

New interface for PKCS8 key encryption - #4593

Draft
randombit wants to merge 1 commit into
masterfrom
jack/pkcs8-enc
Draft

randombit wants to merge 1 commit into
masterfrom
jack/pkcs8-enc

Conversation

@randombit

Copy link
Copy Markdown
Owner

Quite a few interfaces exist for this but there really are only two things that change between them: if the PBKDF runtime is specified in "iterations" or in a duration, and if the result is PEM encoded or not.

Add a new single interface for PKCS8 encryption, PKCS8::encrypt_private_key, then define all of the previously existing functions in terms of that.

@randombit randombit added this to the Botan 3.8.0 milestone Jan 25, 2025
@randombit
randombit requested a review from reneme January 25, 2025 16:27
@randombit

Copy link
Copy Markdown
Owner Author

Some things to work out

  • Best name for EncryptedPrivateKey. Perhaps reflecting the PKCS8 structure name?
  • Should we take the opportunity to move this to Private_Key

@coveralls

coveralls commented Jan 25, 2025 •

Copy link
Copy Markdown

Coverage Status

coverage: 90.699% (+0.006%) from 90.693%
when pulling d70034d on jack/pkcs8-enc
into 72deba4 on master.

@randombit
randombit force-pushed the jack/pkcs8-enc branch 2 times, most recently from 34c7c9f to 212e628 Compare January 25, 2025 23:33

@reneme reneme left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very much in favor of simplifying this. It is actually quite hard to find how asymmetric keys are exported into containers in our API.

Should we take the opportunity to move this to Private_Key

This would be more in line with what #4318 currently proposes for signing. If we were to fully embrace this API design for key export, we'd probably end up with something like:

auto sk = create_private_key("RSA", rng);

auto pkcs8 = sk.export()
               .with_cipher("AES-128/CBC")
               .with_pbkdf("Scrypt")
               .with_rng(rng)
               .as_pem();

... admittedly, this would add quite a bit of (internal) boilerplate for the Options-builder plumbing. But, to my mind, such an API is quite ergonomic for the user, since they don't have to learn much library-specific type vocabulary. Just type sk. and your IDE will suggest .export(), just type . again and you'll be presented with the different options you could use.

Such an API would also conveniently cover "unencrypted export". Though, for safety reasons, I'd suggest to guard that like so:

auto unencrypted = sk.export()
                     .without_encryption() // to deliberately request "unsafe"
                     .as_pem();

Comment thread src/lib/pubkey/pkcs8.h Outdated
Comment on lines +58 to +73
// The default encryption cipher
//
// This may change over time
static std::string default_cipher();

// The default password hash
//
// This may change over time
//
// TODO(Botan4) Consider changing this to Scrypt
static std::string default_pwhash();

// The default password hash duration
//
// This may change over time
static std::chrono::milliseconds default_pwhash_duration();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do those need to be public?

Comment thread src/lib/pubkey/pkcs8.h
#include <optional>
#include <span>
#include <string_view>
#include <variant>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems orphaned and unused. I'm guessing you considered it to distinguish duration and iterations.

@randombit

Copy link
Copy Markdown
Owner Author

I toyed with a builder idea during development but I figured I would let you be the one to suggest it :P

@reneme

reneme commented Jan 28, 2025

Copy link
Copy Markdown
Collaborator

Perhaps we should pull the reusable portions of the PK_Options draft (which won't be exposed publicly anyway) into a separate PR/branch. It would certainly make it easier to prototype on API such as this one. Given that this builder paradigm would bring quite a big API shift I'd love to toy with it on different aspects of the API before fully committing on it.

@reneme

reneme commented Feb 17, 2025

Copy link
Copy Markdown
Collaborator

Note: #4694 acts on my last comment and proposes an alternative API based on the facilities proposed last year in #4318 for PK_Signature_Options.

@randombit randombit modified the milestones: Botan 3.8.0, Botan 3.9.0 May 6, 2025
Quite a few interfaces exist for this but there really are only two
things that change between them: if the PBKDF runtime is specified in
"iterations" or in a duration, and if the result is PEM encoded or not.

Add a new single interface for PKCS8 encryption, PKCS8::encrypt_private_key,
then define all of the previously existing functions in terms of that.
@randombit randombit modified the milestones: Botan 3.9.0, Botan 3.10.0 Jul 25, 2025
@randombit randombit modified the milestones: Botan 3.10.0, Botan 3.11 Nov 4, 2025
@reneme reneme removed this from the Botan 3.11 milestone Jan 20, 2026
@randombit randombit mentioned this pull request Sep 15, 2026
36 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants