pub struct Pkcs11KeyStore { /* private fields */ }pkcs11 only.Expand description
A KeyStore over a token of a PKCS#11 module: an HSM, a smart card or a software token
such as SoftHSM2.
The key id is the object label (CKA_LABEL): a key is the private key object and the
public key object that share a label. Keys are referenced by label, so a label must name one
key; the store refuses a label that names several.
Signing happens in the module. The store hashes in-process and signs the hash with
CKM_ECDSA (ES256, ES256K), CKM_RSA_PKCS over a SHA-256 DigestInfo (RS256) or
CKM_RSA_PKCS_PSS with SHA-256, MGF1-SHA-256 and a 32-byte salt (PS256); EdDSA signs the
message itself with CKM_EDDSA. ECDSA signatures come back as raw r || s, the JWS form.
What the store signs with is read from the module’s mechanism list when it is opened:
EdDSA when the module has CKM_EDDSA, ES256 and (feature secp256k1) ES256K when it
has CKM_ECDSA, and rsa_algorithm when it has the
matching RSA mechanism. Pkcs11KeyStoreOptions::algorithms narrows the list. The store
generates and deletes keys unless the token is write-protected; a generated key is an
Ed25519, P-256, secp256k1 or RSA (65537) key pair stored on the token, the private key
sensitive and not extractable. The key id of a generated key is the spec’s label when set
and the RFC 7638 thumbprint of the public key otherwise; such a key is generated under a
label starting with STAGING_LABEL_PREFIX and relabelled once its thumbprint is known,
so a generation interrupted in between leaves a key with that prefix on the token, to be
removed with the module’s tools.
The module’s functions block, so every operation runs on tokio’s blocking thread pool;
the store needs a tokio runtime. It keeps a pool of logged-in sessions
(Pkcs11KeyStoreOptions::sessions) and an operation that finds all of them busy waits
for one. A module is loaded and initialized when the first store on it is opened, shared
by every later store on the same path, and never finalized or unloaded before the process
ends. The PIN is kept in memory for logging in
new sessions and zeroized when the store is dropped.
§Examples
use identity_kit::jose::{JwsAlgorithm, KeyType};
use identity_kit::keys::{KeySpec, KeyStore, Pkcs11KeyStore};
let store = Pkcs11KeyStore::open("/usr/lib/softhsm/libsofthsm2.so", "issuer", Some("1234"))?;
let key = store
.generate(KeySpec::new(KeyType::P256, JwsAlgorithm::ES256).with_label("issuer-2026"))
.await?;
let signature = store.sign(&key, JwsAlgorithm::ES256, b"payload").await?;
assert_eq!(signature.len(), 64);Implementations§
Source§impl Pkcs11KeyStore
impl Pkcs11KeyStore
Sourcepub fn open(
module: impl AsRef<Path>,
token: impl Into<Pkcs11Token>,
pin: Option<&str>,
) -> Result<Self, KeyStoreError>
pub fn open( module: impl AsRef<Path>, token: impl Into<Pkcs11Token>, pin: Option<&str>, ) -> Result<Self, KeyStoreError>
Opens token of the PKCS#11 module at module with the default options.
Loads the module, initializes it if needed, finds the token, reads its mechanism list and
opens one session, logging in as the user with pin when given. A token that needs no
login, or one with a protected authentication path, is opened with None. This blocks
while it talks to the module.
PKCS#11 logs the application in, not the session: when the process is logged in to the
token already (through another store, say), the module reports that instead of checking
pin, and a wrong PIN goes unnoticed until the process logs out.
§Errors
KeyStoreError::Backend carrying a Pkcs11Error: the module does not load, the token
is not there, the PIN is wrong, or the options are not usable.
Sourcepub fn open_with(
module: impl AsRef<Path>,
token: impl Into<Pkcs11Token>,
pin: Option<&str>,
options: Pkcs11KeyStoreOptions,
) -> Result<Self, KeyStoreError>
pub fn open_with( module: impl AsRef<Path>, token: impl Into<Pkcs11Token>, pin: Option<&str>, options: Pkcs11KeyStoreOptions, ) -> Result<Self, KeyStoreError>
Sourcepub fn token_label(&self) -> &str
pub fn token_label(&self) -> &str
The token’s label.
Sourcepub fn options(&self) -> &Pkcs11KeyStoreOptions
pub fn options(&self) -> &Pkcs11KeyStoreOptions
The options the store was opened with.
Trait Implementations§
Source§impl Clone for Pkcs11KeyStore
impl Clone for Pkcs11KeyStore
Source§impl Debug for Pkcs11KeyStore
impl Debug for Pkcs11KeyStore
Source§impl KeyStore for Pkcs11KeyStore
impl KeyStore for Pkcs11KeyStore
Source§fn capabilities(&self) -> KeyStoreCapabilities
fn capabilities(&self) -> KeyStoreCapabilities
Source§fn public_jwk<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 KeyId,
) -> Pin<Box<dyn Future<Output = Result<Jwk, KeyStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn public_jwk<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 KeyId,
) -> Pin<Box<dyn Future<Output = Result<Jwk, KeyStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
key, without private parameters. Read moreSource§fn sign<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 KeyId,
alg: JwsAlgorithm,
data: &'life2 [u8],
) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, KeyStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn sign<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 KeyId,
alg: JwsAlgorithm,
data: &'life2 [u8],
) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, KeyStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn exists<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 KeyId,
) -> Pin<Box<dyn Future<Output = Result<bool, KeyStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn exists<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 KeyId,
) -> Pin<Box<dyn Future<Output = Result<bool, KeyStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
key exists. Read more