File Coverage

blib/lib/Apertur/SDK/Crypto.pm
Criterion Covered Total %
statement 12 30 40.0
branch 0 4 0.0
condition n/a
subroutine 4 5 80.0
pod 1 1 100.0
total 17 40 42.5


line stmt bran cond sub pod time code
1             package Apertur::SDK::Crypto;
2              
3 1     1   7 use strict;
  1         3  
  1         47  
4 1     1   5 use warnings;
  1         2  
  1         93  
5              
6 1     1   7 use MIME::Base64 qw(encode_base64);
  1         2  
  1         85  
7              
8 1     1   6 use Exporter 'import';
  1         2  
  1         395  
9             our @EXPORT_OK = qw(encrypt_image);
10              
11             sub encrypt_image {
12 0     0 1   my ($image_data, $public_key_pem) = @_;
13              
14             # These modules are optional; only required when encryption is used.
15 0 0         eval { require Crypt::OpenSSL::RSA }
  0            
16             or die "Crypt::OpenSSL::RSA is required for encryption features. "
17             . "Install it with: cpanm Crypt::OpenSSL::RSA\n";
18 0 0         eval { require CryptX; require Crypt::AuthEnc::GCM; require Crypt::PRNG }
  0            
  0            
  0            
19             or die "CryptX is required for encryption features. "
20             . "Install it with: cpanm CryptX\n";
21              
22             # Generate random AES-256 key (32 bytes) and IV (12 bytes)
23 0           my $aes_key = Crypt::PRNG::random_bytes(32);
24 0           my $iv = Crypt::PRNG::random_bytes(12);
25              
26             # Encrypt image data with AES-256-GCM
27 0           my $gcm = Crypt::AuthEnc::GCM->new('AES', $aes_key, $iv);
28 0           my $encrypted = $gcm->encrypt_add($image_data);
29 0           my $auth_tag = $gcm->encrypt_done();
30 0           my $encrypted_with_tag = $encrypted . $auth_tag;
31              
32             # Wrap AES key with RSA-OAEP (SHA-256)
33 0           my $rsa = Crypt::OpenSSL::RSA->new_public_key($public_key_pem);
34 0           $rsa->use_pkcs1_oaep_padding();
35 0           $rsa->use_sha256_hash();
36 0           my $wrapped_key = $rsa->encrypt($aes_key);
37              
38             return {
39 0           encrypted_key => encode_base64($wrapped_key, ''),
40             iv => encode_base64($iv, ''),
41             encrypted_data => encode_base64($encrypted_with_tag, ''),
42             algorithm => 'RSA-OAEP+AES-256-GCM',
43             };
44             }
45              
46             1;
47              
48             __END__