1package OpenXPKI::Server::API2::Plugin::Crypto::generate_key; 2use OpenXPKI::Server::API2::EasyPlugin; 3 4=head1 NAME 5 6OpenXPKI::Server::API2::Plugin::Crypto::generate_key 7 8=cut 9 10# Project modules 11use OpenXPKI::Debug; 12use OpenXPKI::Server::Context qw( CTX ); 13use OpenXPKI::Server::API2::Types; 14 15 16 17=head1 COMMANDS 18 19=head2 generate_key 20 21Creates a new cryptographic key and returns it encrypted representation in PEM 22format. 23 24B<Parameters> 25 26=over 27 28=item * C<password> I<Str> - passwort for key encryption. Required. 29 30=item * C<key_alg> I<Str> - key algorithm, e.g. "RSA", "DSA", "EC" etc. Default: "RSA" 31 32=item * C<enc_alg> I<Str> - encryption algorithm, e.g. "AES256" etc. Default: 33crypto backend's default 34 35=item * C<key_length> I<Int> - only RSA/DSA: key length. Default: 2048 36 37=item * C<curve> I<Str> - only EC: curve name. Required. 38 39=item * C<pkeyopt> I<HashRef>|I<ArrayRef> - more options to directly pass to OpenSSL. 40If specified, these option win over other parameters 41(e.g. C<options-E<gt>{rsa_keygen_bits}> wins over C<key_length>) 42For some combinations openssl needs a defined order of the option params, 43if this is required pass a list of hashes. Otherwise a hash with key/values 44will also do. 45 46=item * C<paramset> I<Str> - PEM encoded parameter set whose contents will be 47passed to C<openssl genpkey -paramfile ...> 48 49B<Changes compared to API v1:> 50 51The previous parameter C<PARAMS> was removed. The hash keys used in it are now 52"first class" parameters: 53 54 # old 55 PARAMS => { 56 PKEYOPT => { ... }, 57 KEY_LENGTH => $len, 58 ECPARAM => $pem_ec_param, 59 DSAPARAM => $pem_dsa_param, 60 CURVE_NAME => $curve, 61 } 62 # new 63 key_length => $len, 64 pkeyopt => { p1 => v1, p2 => v2 } or [{ p1 => v1 }, { p2 => v2 }], 65 paramset => $pem_ec_param, # or $pem_dsa_param 66 curve => $curve, 67 68The previously unused parameter C<ISSUER> was removed. 69 70=back 71 72=cut 73command "generate_key" => { 74 password => { isa => 'Str', required => 1, }, 75 key_alg => { isa => 'Str', default => 'rsa' }, 76 key_length => { isa => 'Int', default => 2048 }, 77 curve => { isa => 'Str', }, 78 enc_alg => { isa => 'Str', }, 79 pkeyopt => { isa => 'HashRef|ArrayRef', }, 80 paramset => { isa => 'PEM', }, 81} => sub { 82 my ($self, $params) = @_; 83 my $key_alg = lc($params->key_alg); 84 my $paramset = $params->paramset; 85 86 my $token = $self->api->get_default_token(); 87 88 # prepare command definition 89 my $command = { 90 COMMAND => 'create_pkey', 91 KEY_ALG => $key_alg, 92 $params->has_enc_alg ? (ENC_ALG => $params->enc_alg) : (), 93 PASSWD => $params->password, 94 }; 95 96 # RSA 97 if ($key_alg eq "rsa") { 98 $command->{PKEYOPT} = [{ rsa_keygen_bits => $params->key_length }]; 99 } 100 # EC 101 elsif ($key_alg eq "ec") { 102 # explicit parameter set is given 103 if ($paramset) { 104 $command->{PARAM} = $paramset; 105 delete $command->{KEY_ALG}; 106 # curve name is given, also forces named_curve to be set 107 } elsif ($params->curve) { 108 $command->{PKEYOPT} = [{ ec_paramgen_curve => $params->curve }, { ec_param_enc => "named_curve" }]; 109 } elsif (!$params->has_pkeyopt) { 110 OpenXPKI::Exception->throw(message => 'Either curve, paramset or pkeyopts must be given for EC'); 111 } 112 } 113 # DSA 114 elsif ($key_alg eq "dsa") { 115 if (not $paramset) { 116 $paramset = $token->command({ 117 COMMAND => 'create_params', 118 TYPE => 'DSA', 119 PKEYOPT => [{ dsa_paramgen_bits => $params->key_length }] 120 }) 121 or OpenXPKI::Exception->throw(message => 'Error generating DSA parameter set'); 122 } 123 $command->{PARAM} = $paramset; 124 delete $command->{KEY_ALG}; 125 } 126 127 # add additional options 128 if ($params->has_pkeyopt) { 129 my $opt = $params->pkeyopt; 130 if (ref $opt eq 'ARRAY') { 131 push @{$command->{PKEYOPT}}, @{$opt}; 132 } elsif (ref $opt eq 'HASH') { 133 push @{$command->{PKEYOPT}}, $opt ; 134 } else { 135 OpenXPKI::Exception->throw(message => 'Unsupported format for pkeyopt'); 136 } 137 } 138 139 CTX('log')->audit('key')->info("generating private key", { key_alg => $key_alg }); 140 141 ##! 16: $command 142 return $token->command($command); 143}; 144 145__PACKAGE__->meta->make_immutable; 146