AES128
view release on metacpan or search on metacpan
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "aes.h"
#include "aes.c"
void make_aes_key(char *key, char *secret, size_t secret_size)
{
uint8_t i, m, n;
// make a 32 bytes key from secret.
if(secret_size >= 32) {
memcpy(key, secret, 32);
}
else {
m = 32 % secret_size;
n = (32 - m) / secret_size;
for(i = 0; i < n; i++) {
memcpy(key + secret_size * i, secret, secret_size);
}
memcpy(key + secret_size * i, secret, m);
}
}
MODULE = AES128 PACKAGE = AES128
TYPEMAP: <<END
const char * T_PV
const uint8_t * T_PV
uint8_t * T_PV
END
SV *
AES128_CTR_encrypt(SV *sv_plain_text, SV *sv_secret)
CODE:
STRLEN text_size, secret_size;
uint8_t i;
struct AES_ctx ctx;
char *plain_text, *secret, *output;
plain_text = (char *)SvPVbyte(sv_plain_text, text_size);
secret = (char *)SvPVbyte(sv_secret, secret_size);
char key[32];
make_aes_key(key, secret, secret_size);
uint8_t padding_len = 16 - text_size % 16;
output = (char *)malloc(text_size + padding_len);
memcpy(output, plain_text, text_size);
for(i = 0; i < padding_len; i++)
output[text_size + i] = padding_len;
AES_init_ctx_iv(&ctx, key, key + 16);
AES_CTR_xcrypt_buffer(&ctx, output, text_size + padding_len);
RETVAL = newSVpv(output, text_size + padding_len);
free(output);
OUTPUT:
RETVAL
SV *
AES128_CTR_decrypt(SV *sv_cipher_text, SV *sv_secret)
CODE:
STRLEN text_size, secret_size;
char *cipher_text, *secret;
struct AES_ctx ctx;
char key[32];
cipher_text = (char *)SvPVbyte(sv_cipher_text, text_size);
secret = (char *)SvPVbyte(sv_secret, secret_size);
if(text_size % 16 != 0)
croak("Corrupted cipher text!");
make_aes_key(key, secret, secret_size);
AES_init_ctx_iv(&ctx, key, key + 16);
AES_CTR_xcrypt_buffer(&ctx, cipher_text, text_size);
uint8_t padding_len = cipher_text[text_size -1];
RETVAL = newSVpv(cipher_text, text_size - padding_len);
OUTPUT:
RETVAL
lib/AES128.pm view on Meta::CPAN
=head1 NAME
AES128 - 128BIT CTR mode AES algorithm.
=head1 SYNOPSIS
# ------------------------ simple version ----------------------------------
use AES128 qw/:all/;
my $plain_text = "There's more than one way to do it.";
my $key = "my secret aes key.";
my $encrypted = AES128_CTR_encrypt($plain_text, $key);
my $plain = AES128_CTR_decrypt($encrypted, $key);
# ------------ server/client key exchange -----------------------------------
use MicroECC;
use AES128 qw/:all/;
use Digest::SHA qw/sha256/;
my $curve = MicroECC::secp256r1();
my ($server_pubkey, $server_privkey) = MicroECC::make_key($curve);
# Generate shared secret with client public key.
my $shared_secret = MicroECC::shared_secret($client_pubkey, $server_privkey);
my $key = sha256($shared_secret);
my $plain_text = "There's more than one way to do it.";
my $encrypted = AES128_CTR_encrypt($plain_text, $key);
my $plain = AES128_CTR_decrypt($encrypted, $key);
=head1 DESCRIPTION
Perl wrapper for the tiny-AES-c library (https://github.com/kokke/tiny-AES-c)
Since 128bit key length is secure enough for most applications and ECB is NOT secure,
this module supports 128bit key length and CTR mode only.
=head2 EXPORT
None by default.
=head1 SEE ALSO
The tiny-AES-c library: https://github.com/kokke/tiny-AES-c
macro. Just C<#define> the macro before including C<ppport.h>:
#define DPPP_NAMESPACE MyOwnNamespace_
#include "ppport.h"
The default namespace is C<DPPP_>.
=back
The good thing is that most of the above can be checked by running
F<ppport.h> on your source code. See the next section for
details.
=head1 EXAMPLES
To verify whether F<ppport.h> is needed for your module, whether you
should make any changes to your code, and whether any special defines
should be used, F<ppport.h> can be run as a Perl script to check your
source code. Simply say:
perl ppport.h
_add_range_to_invlist|||
_append_range_to_invlist|||
_core_swash_init|||
_get_encoding|||
_get_regclass_nonbitmap_data|||
_get_swash_invlist|||
_invlistEQ|||
_invlist_array_init|||n
_invlist_contains_cp|||n
_invlist_dump|||
_invlist_intersection_maybe_complement_2nd|||
_invlist_intersection|||
_invlist_invert|||
_invlist_len|||n
_invlist_populate_swatch|||n
_invlist_search|||n
_invlist_subtract|||
_invlist_union_maybe_complement_2nd|||
_invlist_union|||
_is_cur_LC_category_utf8|||
_is_in_locale_category||5.021001|
_is_uni_FOO||5.017008|
sortsv||5.007003|
space_join_names_mortal|||
ss_dup|||
ssc_add_range|||
ssc_and|||
ssc_anything|||
ssc_clear_locale|||n
ssc_cp_and|||
ssc_finalize|||
ssc_init|||
ssc_intersection|||
ssc_is_anything|||n
ssc_is_cp_posixl_init|||n
ssc_or|||
ssc_union|||
stack_grow|||
start_glob|||
start_subparse||5.004000|
stdize_locale|||
strEQ|||
strGE|||
* data from C. All statics in extensions should be reworked to use
* this, if you want to make the extension thread-safe. See ext/re/re.xs
* for an example of the use of these macros.
*
* Code that uses these macros is responsible for the following:
* 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
* 2. Declare a typedef named my_cxt_t that is a structure that contains
* all the data that needs to be interpreter-local.
* 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
* 4. Use the MY_CXT_INIT macro such that it is called exactly once
* (typically put in the BOOT: section).
* 5. Use the members of the my_cxt_t structure everywhere as
* MY_CXT.member.
* 6. Use the dMY_CXT macro (a declaration) in all the functions that
* access MY_CXT.
*/
#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT)
#ifndef START_MY_CXT
tiny-AES-c/aes.c view on Meta::CPAN
{
uint8_t temp;
// Rotate first row 1 columns to left
temp = (*state)[0][1];
(*state)[0][1] = (*state)[1][1];
(*state)[1][1] = (*state)[2][1];
(*state)[2][1] = (*state)[3][1];
(*state)[3][1] = temp;
// Rotate second row 2 columns to left
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;
temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;
// Rotate third row 3 columns to left
temp = (*state)[0][3];
tiny-AES-c/aes.c view on Meta::CPAN
{
uint8_t temp;
// Rotate first row 1 columns to right
temp = (*state)[3][1];
(*state)[3][1] = (*state)[2][1];
(*state)[2][1] = (*state)[1][1];
(*state)[1][1] = (*state)[0][1];
(*state)[0][1] = temp;
// Rotate second row 2 columns to right
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;
temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;
// Rotate third row 3 columns to right
temp = (*state)[0][3];
tiny-AES-c/aes.h view on Meta::CPAN
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
#endif
#if defined(ECB) && (ECB == 1)
// buffer size is exactly AES_BLOCKLEN bytes;
// you need only AES_init_ctx as IV is not used in ECB
// NB: ECB is considered insecure for most uses
void AES_ECB_encrypt(struct AES_ctx* ctx, uint8_t* buf);
void AES_ECB_decrypt(struct AES_ctx* ctx, uint8_t* buf);
#endif // #if defined(ECB) && (ECB == !)
#if defined(CBC) && (CBC == 1)
// buffer size MUST be mutile of AES_BLOCKLEN;
// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
( run in 1.055 second using v1.01-cache-2.11-cpan-39bf76dae61 )