Apertur-SDK
view release on metacpan or search on metacpan
lib/Apertur/SDK/Crypto.pm view on Meta::CPAN
package Apertur::SDK::Crypto;
use strict;
use warnings;
use MIME::Base64 qw(encode_base64);
use Exporter 'import';
our @EXPORT_OK = qw(encrypt_image);
sub encrypt_image {
my ($image_data, $public_key_pem) = @_;
# These modules are optional; only required when encryption is used.
eval { require Crypt::OpenSSL::RSA }
or die "Crypt::OpenSSL::RSA is required for encryption features. "
. "Install it with: cpanm Crypt::OpenSSL::RSA\n";
eval { require CryptX; require Crypt::AuthEnc::GCM; require Crypt::PRNG }
or die "CryptX is required for encryption features. "
. "Install it with: cpanm CryptX\n";
# Generate random AES-256 key (32 bytes) and IV (12 bytes)
my $aes_key = Crypt::PRNG::random_bytes(32);
my $iv = Crypt::PRNG::random_bytes(12);
# Encrypt image data with AES-256-GCM
my $gcm = Crypt::AuthEnc::GCM->new('AES', $aes_key, $iv);
my $encrypted = $gcm->encrypt_add($image_data);
my $auth_tag = $gcm->encrypt_done();
my $encrypted_with_tag = $encrypted . $auth_tag;
# Wrap AES key with RSA-OAEP (SHA-256)
my $rsa = Crypt::OpenSSL::RSA->new_public_key($public_key_pem);
$rsa->use_pkcs1_oaep_padding();
$rsa->use_sha256_hash();
my $wrapped_key = $rsa->encrypt($aes_key);
return {
encrypted_key => encode_base64($wrapped_key, ''),
iv => encode_base64($iv, ''),
encrypted_data => encode_base64($encrypted_with_tag, ''),
algorithm => 'RSA-OAEP+AES-256-GCM',
};
}
1;
__END__
=head1 NAME
Apertur::SDK::Crypto - Image encryption for Apertur uploads
=head1 SYNOPSIS
use Apertur::SDK::Crypto qw(encrypt_image);
my $result = encrypt_image($image_bytes, $public_key_pem);
# $result->{encrypted_key} - Base64-encoded RSA-wrapped AES key
# $result->{iv} - Base64-encoded 12-byte IV
# $result->{encrypted_data} - Base64-encoded AES-256-GCM ciphertext + tag
# $result->{algorithm} - "RSA-OAEP+AES-256-GCM"
=head1 DESCRIPTION
Encrypts image data using AES-256-GCM with a random key, then wraps
the AES key using RSA-OAEP with SHA-256. Requires optional dependencies
C<Crypt::OpenSSL::RSA> and C<CryptX>; these are loaded at runtime only
when encryption is actually used.
=head1 FUNCTIONS
=over 4
=item B<encrypt_image($image_data, $public_key_pem)>
Encrypts the given image bytes with the provided PEM-encoded RSA public
key. Returns a hashref with C<encrypted_key>, C<iv>, C<encrypted_data>,
and C<algorithm> (all strings, base64-encoded where applicable).
=back
=cut
( run in 0.930 second using v1.01-cache-2.11-cpan-b16cb0d3907 )