Crypt-MagicSignatures-Envelope
view release on metacpan or search on metacpan
lib/Crypt/MagicSignatures/Envelope.pm view on Meta::CPAN
# Append all defined signatures
foreach ( @{$param{sigs}} ) {
# No value is given
next unless $_->{value};
# Create new array reference if not already existing
$self->{sigs} //= [];
# Start new signature value
my %sig = ( value => $_->{value} );
$sig{key_id} = $_->{key_id} if exists $_->{key_id};
# Add signature to signature array
push(@{$self->{sigs}}, \%sig);
};
}
# Envelope is defined as a string
else {
my $string = shift;
# Construct object
$self = bless { sigs => [] }, $class;
# Create empty object
return $self unless $string;
$string = trim $string;
# Message is me-xml
if (index($string, '<') == 0) {
# Parse xml string
my $dom = Mojo::DOM->new(xml => 1)->parse($string);
# Extract envelope from env or provenance
my $env = $dom->at('env');
$env = $dom->at('provenance') unless $env;
# Envelope doesn't exist or is in wrong namespace
if (!$env || $env->namespace ne $ME_NS) {
carp 'Invalid envelope data';
return;
};
# Retrieve and edit data
my $data = $env->at('data');
# The envelope is empty
unless (defined $data) {
carp 'No data payload defined';
return;
};
my $temp;
# Add data type if given
$self->data_type( $temp ) if $temp = $data->attr->{type};
# Add decoded data
$self->data( b64url_decode( $data->text ) );
# The envelope is empty
unless ($self->data) {
carp 'No data payload defined';
return;
};
# Check algorithm
if (($temp = $env->at('alg')) &&
(uc $temp->text ne 'RSA-SHA256')) {
carp 'Algorithm is not supported';
return;
};
# Check encoding
if (($temp = $env->at('encoding')) &&
(lc $temp->text ne 'base64url')) {
carp 'Encoding is not supported' and return;
};
# Find signatures
$env->find('sig')->each(
sub {
my $sig_text = $_->text or return;
my %sig = ( value => _trim_all $sig_text );
if ($temp = $_->attr->{key_id}) {
$sig{key_id} = $temp;
};
# Add sig to array
push( @{ $self->{sigs} }, \%sig );
});
}
# Message is me-json
elsif (index($string, '{') == 0) {
my $env;
# Parse json object
$env = decode_json $string;
unless (defined $env) {
return;
};
# Clone datastructure
foreach (qw/data data_type encoding alg sigs/) {
$self->{$_} = delete $env->{$_} if exists $env->{$_};
};
$self->data( b64url_decode( $self->data ));
# Envelope is empty
return unless $self->data;
# Unknown parameters
carp 'Unknown parameters: ' . join(',', %$env)
lib/Crypt/MagicSignatures/Envelope.pm view on Meta::CPAN
=pod
=head1 NAME
Crypt::MagicSignatures::Envelope - MagicEnvelopes for the Salmon Protocol
=head1 SYNOPSIS
use Crypt::MagicSignatures::Key;
use Crypt::MagicSignatures::Envelope;
# Generate a new MagicKey for signing messages
my $mkey = Crypt::MagicSignatures::Key->generate(size => 1024);
# Fold a new envelope
my $me = Crypt::MagicSignatures::Envelope->new(
data => 'Some arbitrary string.'
);
# Sign magic envelope
$me->sign($mkey);
# Extract the public key
my $mkey_public = $mkey->to_string;
# Verify the signature of the envelope
if ($me->verify($mkey_public)) {
print 'Signature is verified!';
};
=head1 DESCRIPTION
L<Crypt::MagicSignatures::Envelope> implements MagicEnvelopes
with MagicSignatures as described in the
L<MagicSignatures Specification|http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-magicsig-01.html>
to sign messages of the
L<Salmon Protocol|http://www.salmon-protocol.org/>.
MagicSignatures is a
"robust mechanism for digitally signing nearly arbitrary messages".
B<This module is an early release! There may be significant changes in the future.>
=head1 ATTRIBUTES
=head2 alg
my $alg = $me->alg;
The algorithm used for signing the MagicEnvelope.
Defaults to C<RSA-SHA256>, which is the only supported algorithm.
=head2 data
my $data = $me->data;
$me->data('Hello world!');
The decoded data folded in the MagicEnvelope.
=head2 data_type
my $data_type = $me->data_type;
$me->data_type('text/plain');
The Mime type of the data folded in the MagicEnvelope.
Defaults to C<text/plain>.
=head2 dom
# Fold an xml message
my $me = Crypt::MagicSignatures::Envelope->new( data => <<'XML' );
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns='http://www.w3.org/2005/Atom'>
<author><uri>alice@example.com</uri></author>
</entry>
XML
# Define an xml mime type
$me->data_type('application/atom+xml');
print $me->dom->at('author > uri')->text;
# alice@example.com
The L<Mojo::DOM> object of the decoded data,
in the case the MagicEnvelope contains XML.
B<This attribute is experimental and may change without warnings!>
=head2 encoding
my $encoding = $me->encoding;
The encoding of the MagicEnvelope.
Defaults to C<base64url>, which is the only encoding supported.
=head2 signature
my $sig = $me->signature;
my $sig = $me->signature('key-01');
A signature of the MagicEnvelope.
For retrieving a specific signature, pass a key id,
otherwise a default signature will be returned.
If a matching signature is found, the signature
is returned as a hash reference,
containing base64url encoded data for C<value>
and possibly a C<key_id>.
If no matching signature is found, a C<false> value is returned.
=head2 signature_base
my $base = $me->signature_base;
The L<signature base string|http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-magicsig-01.html#sbs>
of the MagicEnvelope.
=head2 signed
# With key id
if ($me->signed('key-01')) {
print 'MagicEnvelope is signed with key-01.';
}
# Without key id
elsif ($me->signed) {
print 'MagicEnvelope is signed.';
}
else {
print 'MagicEnvelope is not signed.';
};
Returns a C<true> value in case the MagicEnvelope is signed at least once.
Accepts optionally a C<key_id> and returns a C<true> value, if the
MagicEnvelope was signed with this specific key.
=head1 METHODS
( run in 1.357 second using v1.01-cache-2.11-cpan-5b529ec07f3 )