Skip to content

Commit

Permalink
Add KeyName to XML if specified
Browse files Browse the repository at this point in the history
  • Loading branch information
timlegge committed Dec 27, 2024
1 parent 082f822 commit bf1c0fd
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
4 changes: 4 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ METHODS

* sha512 <http://www.w3.org/2001/04/xmlenc#sha512>

key_name
Specify a key name to add to the KeyName element. If it is not
specified then no KeyName element is added to the KeyInfo

decrypt( ... )
Main decryption function.

Expand Down
31 changes: 30 additions & 1 deletion lib/XML/Enc.pm
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,13 @@ The default is sha1. Supported algorithms are:
=back
=item B<key_name>
Specify a key name to add to the KeyName element. If it is not specified then no
KeyName element is added to the KeyInfo
=back
=cut

sub new {
Expand Down Expand Up @@ -267,6 +274,8 @@ sub new {

$self->{'oaep_params'} = exists($params->{'oaep_params'}) ? $params->{'oaep_params'} : '';

$self->{'key_name'} = $params->{'key_name'} if exists($params->{'key_name'});

return $self;
}

Expand Down Expand Up @@ -539,6 +548,11 @@ sub encrypt {
my $base64_key = encode_base64($key);
my $base64_data = encode_base64($encrypteddata);

# Insert KeyName into the XML
if (defined $self->{key_name} and $self->{key_name} ne '') {
$encrypted = $self->_setKeyName($encrypted, $xpc, $self->{key_name});
}

# Insert OAEPparams into the XML
if ($self->{oaep_params} ne '') {
$encrypted = $self->_setOAEPparams($encrypted, $xpc, encode_base64($self->{oaep_params}));
Expand Down Expand Up @@ -570,6 +584,19 @@ sub _setEncryptionMethod {
return exists($methods{$method}) ? $methods{$method} : $methods{'aes256-cbc'};
}

sub _setKeyName {
my $self = shift;
my $context = shift;
my $xpc = shift;
my $keyname = shift;

my $node = $xpc->findnodes('//xenc:EncryptedKey/dsig:KeyInfo/dsig:KeyName', $context);

$node->[0]->removeChildNodes();
$node->[0]->appendText(defined $keyname ? $keyname : 'key_name');
return $context;
}

sub _setOAEPparams {
my $self = shift;
my $context = shift;
Expand Down Expand Up @@ -1177,12 +1204,14 @@ sub _create_encrypted_data_xml {
'dsig:KeyInfo',
);

my $keyname = $self->_create_node(
if (defined $self->{key_name}) {
my $keyname = $self->_create_node(
$doc,
$dsigns,
$keyinfo2,
'dsig:KeyName',
);
};

my $keycipherdata = $self->_create_node(
$doc,
Expand Down
17 changes: 10 additions & 7 deletions t/06-test-encryption-methods.t
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ my $xml = <<'XML';
</foo>
XML

my $key_name = 'mykey';
my @key_methods = qw/rsa-1_5 rsa-oaep-mgf1p/;
my @data_methods = qw/aes128-cbc aes192-cbc aes256-cbc tripledes-cbc aes128-gcm aes192-gcm aes256-gcm/;
my @oaep_mgf_algs = qw/rsa-oaep-mgf1p mgf1sha1 mgf1sha224 mgf1sha256 mgf1sha384 mgf1sha512/;
Expand All @@ -28,6 +29,7 @@ foreach my $km (@key_methods) {
{
key => 't/sign-private.pem',
cert => 't/sign-certonly.pem',
key_name => $key_name,
data_enc_method => $dm,
key_transport => $km,
no_xml_declaration => 1
Expand All @@ -42,17 +44,16 @@ foreach my $km (@key_methods) {
SKIP: {
skip "xmlsec1 not installed", 2 unless $xmlsec->{installed};
skip "xmlsec version 1.2.27 minimum for GCM", 2 if ! $xmlsec->{aes_gcm};
ok( open XML, '>', 'tmp.xml' );
ok( open XML, '>', "enc-xml-$km-$dm.xml" );
print XML $encrypted;
close XML;
my $verify_response = `xmlsec1 --decrypt $lax_key_search --privkey-pem t/sign-private.pem tmp.xml 2>&1`;
my $verify_response = `xmlsec1 --decrypt $lax_key_search --privkey-pem:$key_name t/sign-private.pem,t/sign-certonly.pem enc-xml-$km-$dm.xml 2>&1`;
like($verify_response, qr/XML-SIG_1/, "Successfully decrypted with xmlsec1" )
or warn "calling xmlsec1 failed: '$verify_response'\n";
unlink 'tmp.xml';
unlink "enc-xml-$km-$dm.xml";
}
}
}

foreach my $om (@oaep_mgf_algs) {
foreach my $omdig (@oaep_label_hashes) {
SKIP: {
Expand All @@ -67,6 +68,7 @@ foreach my $om (@oaep_mgf_algs) {
{
key => 't/sign-private.pem',
cert => 't/sign-certonly.pem',
key_name => $key_name,
data_enc_method => $dm,
key_transport => $km,
oaep_mgf_alg => $om,
Expand All @@ -82,13 +84,14 @@ foreach my $om (@oaep_mgf_algs) {
SKIP: {
skip "xmlsec1 not installed", 2 unless $xmlsec->{installed};
skip "xmlsec version 1.2.27 minimum for GCM", 2 if ! $xmlsec->{aes_gcm};
ok( open XML, '>', "$km-$om-$omdig-$dm-tmp.xml" );
skip "xmlsec version 1.3.00 minimum for rsa-oeap", 2 if ! $xmlsec->{rsa_oaep};
ok( open XML, '>', "enc-xml-$km-$om-$omdig-$dm.xml" );
print XML $encrypted;
close XML;
my $verify_response = `xmlsec1 --decrypt $lax_key_search --privkey-pem t/sign-private.pem $km-$om-$omdig-$dm-tmp.xml 2>&1`;
my $verify_response = `xmlsec1 --decrypt $lax_key_search --privkey-pem:$key_name t/sign-private.pem,t/sign-certonly.pem enc-xml-$km-$om-$omdig-$dm.xml 2>&1`;
ok( $verify_response =~ m/XML-SIG_1/, "Successfully decrypted with xmlsec1" )
or warn "calling xmlsec1 failed: '$verify_response'\n";
unlink "$km-$om-$omdig-$dm-tmp.xml";
unlink "enc-xml-$km-$om-$omdig-$dm.xml";
}
ok($encrypter->decrypt($encrypted) =~ /XML-SIG_1/, "Successfully Decrypted with XML::Enc");
}
Expand Down
1 change: 1 addition & 0 deletions t/lib/Test/XML/Enc/Util.pm
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ sub get_xmlsec_features {
ripemd160 => ($major >= 1 and $minor >= 3) ? 1 : 0,
aes_gcm => ($major <= 1 and $minor <= 2 and $patch <= 27) ? 0 : 1,
lax_key_search => ($major >= 1 and $minor >= 3) ? 1 : 0,
rsa_oaep => ($major >= 1 and $minor >= 3) ? 1 : 0,
);
return \%xmlsec;
}
Expand Down

0 comments on commit bf1c0fd

Please sign in to comment.