Crypt::PKCS11::Easy - Wrapper around Crypt::PKCS11 to make using a HSM not suck
version 0.161530
use Crypt::PKCS11::Easy; use IO::Prompter; my $file = '/file/to/sign'; my $hsm = Crypt::PKCS11::Easy->new( module => 'libCryptoki2_64', key => 'MySigningKey', slot => '0', pin => sub { prompt 'Enter PIN: ', -echo=>'*' }, ); my $base64_signature = $hsm->sign_and_encode(file => $file); my $binary_signature = $hsm->decode_signature(data => $base64_signature); $hsm->verify(file => $data_file, sig => $binary_signature) or die "VERIFICATION FAILED\n";
This module is an OO wrapper around Crypt::PKCS11, designed primarily to make using a HSM as simple as possible.
Crypt::PKCS11
use IO::Prompter; use Crypt::PKCS11; use Crypt::PKCS11::Attributes; my $pkcs11 = Crypt::PKCS11->new; $pkcs11->load('/usr/safenet/lunaclient/lib/libCryptoki2_64.so'); $pkcs11->Initialize; # assuming there is only one slot my @slot_ids = $pkcs11->GetSlotList(1); my $slot_id = shift @slot_ids; my $session = $pkcs11->OpenSession($slot_id, CKF_SERIAL_SESSION) or die "Error" . $pkcs11->errstr; $session->Login(CKU_USER, sub { prompt 'Enter PIN: ', -echo=>'*' } ) or die "Failed to login: " . $session->errstr; my $object_template = Crypt::PKCS11::Attributes->new->push( Crypt::PKCS11::Attribute::Label->new->set('MySigningKey'), Crypt::PKCS11::Attribute::Sign->new->set(1), ); $session->FindObjectsInit($object_template); my $objects = $session->FindObjects(1); my $key = shift @$objects; my $sign_mech = Crypt::PKCS11::CK_MECHANISM->new; $sign_mech->set_mechanism(CKM_SHA1_RSA_PKCS); $session->SignInit($sign_mech, $key) or die "Failed to set init signing: " . $session->errstr; my $sig = $session->Sign('SIGN ME') or die "Failed to sign: " . $session->errstr;
Crypt::PKCS11::Easy
use Crypt::PKCS11::Easy; use IO::Prompter; my $hsm = Crypt::PKCS11::Easy->new( module => 'libCryptoki2_64', key => 'MySigningKey', slot => '0', pin => sub { prompt 'Enter PIN: ', -echo=>'*' }, ); my $sig = $hsm->sign(data => 'SIGN ME');
To make that conciseness possible a Crypt::PKCS11::Object can only be used for one function, e.g. signing OR verifying, and cannot be set to use a different key or a different token after instantiation. A new object should be created for each function.
Crypt::PKCS11::Object
module
String. Required.
The name of the PKCS#11 module to use. Either pass the full path to the module, or just pass the base name of the library and the rest will be handled automagically. e.g.
libsofthsm2 => /usr/lib64/pkcs11/libsofthsm2.so libCryptoki2_64 => /usr/lib64/pkcs11/libCryptoki2_64.so gnome-keyring-pkcs11 => /usr/lib64/pkcs11/gnome-keyring-pkcs11.so
rw
Boolean. Controls whether a session will be opened in Read/Write mode or not. Defaults to off. Writing is only needed to make modifications to a token or the objects on it.
key
String. The label of the you want to use.
function
String. The function that will be performed with this object. Can be 'sign' or 'verify'. Defaults to 'sign'. It affects how the key can be used. If function is sign and you try to verify a signature, the underlying library will return an error.
slot
Integer. The id number of the slot to use.
token
String. Instead of specifying the "slot", find and use the slot that contains a token with this label.
pin
String, Coderef or Path::Tiny object. This is either the PIN/password required to access a token, a coderef that returns it, or a file that contains it.
use IO::Prompter; $pin = sub { prompt 'Enter PIN: ', -echo=>'*' }; use Path::Tiny; $pin = path '/secure/file/with/password' $pin = '1234';
module_dirs
Array of paths to check for PKCS#11 modules.
get_info
Returns a hashref containing basic info about the PKCS#11 implementation, currently the manufacturer, library description and Cryptoki version that is implemented.
get_token_info(Int $slot_id)
Returns a hashref containing details on the token in slot identified by $slot_id.
$slot_id
get_slot(id =
Returns a hashref containing details on the slot identified by $id OR the slot which contains a token with the label $string. If a token is present in the slot, its details will also be retrieved.
$id
$string
my $slot = $pkcs11->get_slot(id => 1); my $slot = $pkcs11->get_slot(token => 'Build Signer'); say $slot->{token}->{serialNumber};
get_slots(Bool $with_token?)
Returns an arrayref of all visible slots. Each element in the array will be a hashref returned by "get_slot".
If $with_token is true then only slots that contain a token will be returned.
$with_token
login
Attempts to login to the HSM. In most use cases, this will be handled automatically when needed.
get_signing_key(Str $label)
Will look for a key matching with a label matching $label which can be used for signing.
$label
The returned key is a Crypt::PKCS11::Object.
get_verification_key(Str $label)
Will look for a key matching with a label matching $label which can be used for signature verification.
sign((data =
Returns a binary signature. The data to be signed is either passed as a scalar in data, or in file which can be a string path or a Path::Tiny object.
data
file
A PKCS#11 mechanism can optionally be specified as a string and without the leading 'CKM_'.
my $sig = $hsm->sign(file => $file, mech => 'RSA_PKCS'); my $sig = $hsm->sign(data => 'SIGN ME');
sign_and_encode(...)
Wrapper around "sign" which will return the signature data as base64 PEM, e.g.
-----BEGIN SIGNATURE----- YHXMbvdWyUXeNvgfMzQA+9FjytOWPZCik/H3GS6t72xtk1gvHNfQpKdURKvgBeJM QdUJ7ceujzGX5v/UJRJ4oSpLLiptn2BYaeAn/gUg7yKDFg4YuVN7RU7MbrN2jjlw RfKHq6h6G4FP8LJz5jQWlKKIPoiJ2g3a9M7dq0+hG/kPOv4pBLm7G30uaiSpi/3O hhV+aw87HB7H7i09NSIHoWRxXqw8BeFse7jWTjbj5X1j9uNxD+W6+sxyERawfqFP 3WuzDIcD8kgMA7cM7a6z+h1bEgUt2FUKGytcTX4ymAz9+aS+u24V81mg0Ia3pZQd Pth2532FY0z+Ajn3GojNVw== -----END SIGNATURE-----
verify((data =
Verifies a signature. Parameters are the same as "sign", and also requires a binary signature. Returns true or false.
$hsm->verify(file => $file_to_check, sig => $binary_sig, mech => 'RSA_PKCS') or die "Signature verification failed!\n";
digest((data =
Returns a binary digest. Parameters are the same as "sign".
$hsm->digest(file => $file_to_check, mech => 'RSA_PKCS')
decode_signature((data =
get_mechanism_info($mech, $slot_id?)
Will return a details of a mechanism as a hashref. If a slot id is specifed, the mechanisms for that slot will be retrieved. Otherwise, the slot id in "slot" will be used if there is one.
get_mechanisms($slot_id?)
Will return a hashref of available mechanisms. If a slot id is specifed, the mechanisms for that slot will be retrieved. Otherwise, the slot id in "slot" will be used if there is one.
Crypt::PKCS11::Easy uses Log::Any for logging. To see debug output on STDOUT, for example, in your application use:
STDOUT
use Log::Any::Adapter 'Stdout', log_level => 'debug';
Unless stated otherwise, methods will die when encountering an error.
The default mechanisms are:
PKCS#11 v2.40 Mechanisms Crypt::PKCS11 SoftHSM2
Ioan Rogers <ioan.rogers@sophos.com>
This software is copyright (c) 2016 by Sophos Ltd.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
To install Crypt::PKCS11::Easy, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Crypt::PKCS11::Easy
CPAN shell
perl -MCPAN -e shell install Crypt::PKCS11::Easy
For more information on module installation, please visit the detailed CPAN module installation guide.