トップへ(mam-mam.net/)

OpenSSLでAES256暗号化するAndroidアプリケーションを作成する ~Delphiでお手軽プログラミング

検索:

OpenSSLでAES256暗号化するAndroidアプリケーションを作成する ~Delphiでお手軽プログラミング

Android用OpenSSLコンパイル済みライブラリのダウンロード

以下のURLなどからAndroid用OpenSSLのコンパイル済みライブラリをダウンロードします
https://forums.embarcadero.com/thread.jspa?messageID=824565&#824565
https://github.com/emileb/OpenSSL-for-Android-Prebuilt
ダウンロードしたZIPファイルを解凍した以下2つのファイルが必要です
libcrypto.so
libssl.so

Delphiを起動し新規プロジェクトを作成

新規作成⇒マルチデバイス アプリケーションを選択します。

空のアプリケーションを選択してOKボタンをクリックします。

本ページ下部の「MamAndroidOpenSSLユニット」を MamAndroidOpenSSL.pasファイルとしてプロジェクトフォルダ内に配置します。

画面デザイン

以下のようにコンポーネントを配置ます。
ビューを Android 4インチに切り替えた場合。

ソースコード

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
  FMX.Edit, FMX.Controls.Presentation;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    Button1: TButton;
    Button2: TButton;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Button3: TButton;
    Button4: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { private 宣言 }
  public
    { public 宣言 }
  end;

var
  Form1: TForm1;
const
  //暗号化鍵
  key:string='12345678901234567890123456789012';
  //CBCの時に使う初期ベクトルIV
  iv :string='1234567890123456';

implementation

{$R *.fmx}
{$R *.NmXhdpiPh.fmx ANDROID}

uses MamAndroidOpenSSL;

procedure TForm1.Button1Click(Sender: TObject);
var keyb,decb:TBytes;
    enc:string;
begin
//Edit1.TextをAES256ECB暗号化してEdit2.Textに出力する

  //鍵のバイト配列を取得
  keyb:=TEncoding.ASCII.GetBytes(key);
  //暗号化したい文字列をUTF8のバイト配列に変換
  decb:=TEncoding.UTF8.GetBytes(Edit1.text);
  //AES256ECB暗号化してBase64エンコード
  MamEncAes256Ecb(decb,keyb,enc);
  //Edit2に暗号化したテキストを出力
  Edit2.text:=enc;
end;

procedure TForm1.Button2Click(Sender: TObject);
var keyb,decb:TBytes;
begin
//Edit2.TextをAES256ECB復号化してEdit1.Textに出力する

  //鍵のバイト配列を取得
  keyb:=TEncoding.ASCII.GetBytes(key);
  //AES256ECB復号化
  MamDecAes256Ecb(decb,keyb,Edit2.text);
  Edit1.Text:=TEncoding.UTF8.GetString(decb);
end;

procedure TForm1.Button3Click(Sender: TObject);
var keyb,ivb,decb:TBytes;
    enc:string;
begin
//Edit1.TextをAES256ECB暗号化してEdit2.Textに出力する

  //鍵のバイト配列を取得
  keyb:=TEncoding.ASCII.GetBytes(key);
  //初期ベクトルIVのバイト配列を取得
  ivb :=TEncoding.ASCII.GetBytes(key);
  //暗号化したい文字列をUTF8のバイト配列に変換
  decb:=TEncoding.UTF8.GetBytes(Edit1.text);
  //AES256CBC暗号化してBase64エンコード
  MamEncAes256Cbc(decb,keyb,ivb,enc);
  //Edit2に暗号化したテキストを出力
  Edit2.text:=enc;
end;

procedure TForm1.Button4Click(Sender: TObject);
var keyb,ivb,decb:TBytes;
begin
//Edit2.TextをAES256ECB復号化してEdit1.Textに出力する

  //鍵のバイト配列を取得
  keyb:=TEncoding.ASCII.GetBytes(key);
  //初期ベクトルIVのバイト配列を取得
  ivb :=TEncoding.ASCII.GetBytes(key);
  //AES256CBC復号化
  MamDecAes256Cbc(decb,keyb,ivb,Edit2.text);
  Edit1.Text:=TEncoding.UTF8.GetString(decb);
end;

end.

libcrypto.soとlibssl.soの配置

プロジェクト⇒配置 をクリックします。
「ファイルの追加」ボタンをクリックして「libcrypto.so」と「libssl.so」を追加します。
リモートパスを「assets\internal」に設定します。


配置でのリモートパス「assets\internal」とは内部ストレージを示し、
System.IOUtils.TPath.GetDocumentsPath()
関数で取得できるパスを示しています。
Androidのバージョンによって変わるかもしれませんが以下のディレクトリになります。
/data/user/0/[プロジェクト名]/files


配置でのリモートパス「assets」とは外部ストレージを示し、
System.IOUtils.TPath.GetSharedDocumentsPath
関数で取得できるパスを示しています。
Androidのバージョンによって変わるかもしれませんが以下のディレクトリになります。
/storage/emulated/0/Documents


openSSLライブラリのロード

プロジェクト⇒ソースの表示 をクリックします。
以下の赤字の部分のように、ソースコードを修正します。
program Project1;

uses
  System.StartUpCopy,
  FMX.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  MamAndroidOpenSSL in 'MamAndroidOpenSSL.pas',
  IdSSLOpenSSL,IdSSLOpenSSLHeaders,System.IOUtils;

{$R *.res}

begin
  IdOpenSSLSetLibPath(System.IOUtils.TPath.GetDocumentsPath);
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

プロジェクトの実行

MamAndroidOpenSSLユニット

MamAndroidOpenSSL.pas
unit MamAndroidOpenSSL;

interface
uses System.SysUtils,IdSSLOpenSSLHeaders,system.NetEncoding {,WinApi.Windows};

//AES-128-ECB暗号化(暗号化したいデータ,キー(16バイト) out:暗号化データ)
function MamEncAes128Ecb(
  DecData,Key:TBytes;out EncData:TBytes):Boolean;overload;
//AES-128-ECB暗号化(暗号化したいデータ,キー(16バイト) out:暗号化データのBASE64)
function MamEncAes128Ecb(
  DecData,Key:TBytes;out EncDataBase64:String):Boolean;overload;

//AES-192-ECB暗号化(暗号化したいデータ,キー(24バイト) out:暗号化データ)
function MamEncAes192Ecb(
  DecData,Key:TBytes;out EncData:TBytes):Boolean;overload;
//AES-192-ECB暗号化(暗号化したいデータ,キー(24バイト) out:暗号化データのBASE64)
function MamEncAes192Ecb(
  DecData,Key:TBytes;out EncDataBase64:String):Boolean;overload;

//AES-256-ECB暗号化(暗号化したいデータ,キー(32バイト) out:暗号化データ)
function MamEncAes256Ecb(
  DecData,Key:TBytes;out EncData:TBytes):Boolean;overload;
//AES-256-ECB暗号化(暗号化したいデータ,キー(32バイト) out:暗号化データのBASE64)
function MamEncAes256Ecb(
  DecData,Key:TBytes;out EncDataBase64:String):Boolean;overload;


//AES-128-ECB複合化(out:複合化されたデータ,キー(16バイト) ,暗号化データ)
function MamDecAes128Ecb(
  out DecData:TBytes;Key,EncData:TBytes):Boolean;overload;
//AES-128-ECB複合化(out:複合化されたデータ,キー(16バイト) ,暗号化データのBASE64)
function MamDecAes128Ecb(
  out DecData:TBytes;Key:TBytes;EncDataBase64:String):Boolean;overload;

//AES-192-ECB複合化(out:複合化されたデータ,キー(24バイト) ,暗号化データ)
function MamDecAes192Ecb(
  out DecData:TBytes;Key,EncData:TBytes):Boolean;overload;
//AES-192-ECB複合化(out:複合化されたデータ,キー(24バイト) ,暗号化データのBASE64)
function MamDecAes192Ecb(
  out DecData:TBytes;Key:TBytes;EncDataBase64:String):Boolean;overload;

//AES-256-ECB複合化(out:複合化されたデータ,キー(32バイト) ,暗号化データ)
function MamDecAes256Ecb(
  out DecData:TBytes;Key,EncData:TBytes):Boolean;overload;
//AES-256-ECB複合化(out:複合化されたデータ,キー(32バイト) ,暗号化データのBASE64)
function MamDecAes256Ecb(
  out DecData:TBytes;Key:TBytes;EncDataBase64:String):Boolean;overload;


//AES-128-CBC暗号化(暗号化したいデータ,キー(16バイト),初期ベクトル(16バイト) out:暗号化データ)
function MamEncAes128Cbc(
  DecData,Key,Iv:TBytes;out EncData:TBytes):Boolean;overload;
//AES-128-CBC暗号化(暗号化したいデータ,キー(16バイト),初期ベクトル(16バイト) out:暗号化データのBASE64)
function MamEncAes128Cbc(
  DecData,Key,Iv:TBytes;out EncDataBase64:String):Boolean;overload;

//AES-192-CBC暗号化(暗号化したいデータ,キー(24バイト),初期ベクトル(16バイト) out:暗号化データ)
function MamEncAes192Cbc(
  DecData,Key,Iv:TBytes;out EncData:TBytes):Boolean;overload;
//AES-192-CBC暗号化(暗号化したいデータ,キー(24バイト),初期ベクトル(16バイト) out:暗号化データのBASE64)
function MamEncAes192Cbc(
  DecData,Key,Iv:TBytes;out EncDataBase64:String):Boolean;overload;

//AES-256-CBC暗号化(暗号化したいデータ,キー(32バイト),初期ベクトル(16バイト) out:暗号化データ)
function MamEncAes256Cbc(
  DecData,Key,Iv:TBytes;out EncData:TBytes):Boolean;overload;
//AES-256-CBC暗号化(暗号化したいデータ,キー(32バイト),初期ベクトル(16バイト) out:暗号化データのBASE64)
function MamEncAes256Cbc(
  DecData,Key,Iv:TBytes;out EncDataBase64:String):Boolean;overload;


//AES-128-CBC複合化(out:複合化されたデータ,キー(16バイト),初期ベクトル(16バイト) ,暗号化データ)
function MamDecAes128Cbc(
  out DecData:TBytes;Key,Iv,EncData:TBytes):Boolean;overload;
//AES-128-CBC複合化(out:複合化されたデータ,キー(16バイト),初期ベクトル(16バイト) ,暗号化データのBASE64)
function MamDecAes128Cbc(
  out DecData:TBytes;Key,Iv:TBytes;EncDataBase64:String):Boolean;overload;

//AES-192-CBC複合化(out:複合化されたデータ,キー(24バイト),初期ベクトル(16バイト) ,暗号化データ)
function MamDecAes192Cbc(
  out DecData:TBytes;Key,Iv,EncData:TBytes):Boolean;overload;
//AES-192-CBC複合化(out:複合化されたデータ,キー(24バイト),初期ベクトル(16バイト) ,暗号化データのBASE64)
function MamDecAes192Cbc(
  out DecData:TBytes;Key,Iv:TBytes;EncDataBase64:String):Boolean;overload;

//AES-256-CBC複合化(out:複合化されたデータ,キー(32バイト),初期ベクトル(16バイト) ,暗号化データ)
function MamDecAes256Cbc(
  out DecData:TBytes;Key,Iv,EncData:TBytes):Boolean;overload;
//AES-256-CBC複合化(out:複合化されたデータ,キー(32バイト),初期ベクトル(16バイト) ,暗号化データのBASE64)
function MamDecAes256Cbc(
  out DecData:TBytes;Key,Iv:TBytes;EncDataBase64:String):Boolean;overload;

procedure AZeroMemory(p:Pointer;l:integer);


implementation

procedure AZeroMemory(p:Pointer;l:integer);
var b:PByte;
    i:integer;
begin
  b:=p;
  for i := 0 to l-1 do
  begin
    b^:=0;
    inc(b);
  end;
end;

function MamEncAes128Ecb(
  DecData,Key:TBytes;out EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Encl,Padl:integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<16 then
  begin
    l:=length(Key);
    SetLength(Key,16);
    AZeroMemory(@Key[l],16-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_EncryptInit_ex(ctx,EVP_aes_128_ecb,nil,@key[0],nil);
  setLength(EncData, (length(DecData) div 16+1)*16);
  EVP_EncryptUpdate(ctx,@EncData[0],@Encl,@DecData[0],length(DecData));
  EVP_EncryptFinal_ex(ctx,@EncData[Encl],@Padl);
  EVP_CIPHER_CTX_free(ctx);
  SetLength(EncData,Encl+Padl);
  unload;
  Result:=true;
end;
function MamEncAes128Ecb(
  DecData,Key:TBytes;out EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  result:=MamEncAes128Ecb(DecData,Key,EncData);
  EncData:=TNetEncoding.Base64.Encode(EncData);
  EncDataBase64:=TEncoding.ASCII.GetString(EncData);
end;

function MamEncAes192Ecb(
  DecData,Key:TBytes;out EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Encl,Padl:integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<24 then
  begin
    l:=length(Key);
    SetLength(Key,24);
    AZeroMemory(@Key[l],24-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_EncryptInit_ex(ctx,EVP_aes_192_ecb,nil,@key[0],nil);
  setLength(EncData, (length(DecData) div 16+1)*16);
  EVP_EncryptUpdate(ctx,@EncData[0],@Encl,@DecData[0],length(DecData));
  EVP_EncryptFinal_ex(ctx,@EncData[Encl],@Padl);
  EVP_CIPHER_CTX_free(ctx);
  SetLength(EncData,Encl+Padl);
  unload;
  Result:=true;
end;
function MamEncAes192Ecb(
  DecData,Key:TBytes;out EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  result:=MamEncAes192Ecb(DecData,Key,EncData);
  EncData:=TNetEncoding.Base64.Encode(EncData);
  EncDataBase64:=TEncoding.ASCII.GetString(EncData);
end;

function MamEncAes256Ecb(DecData,Key:TBytes;
  out EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Encl,Padl:integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<32 then
  begin
    l:=length(Key);
    SetLength(Key,32);
    AZeroMemory(@Key[l],32-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_EncryptInit_ex(ctx,EVP_aes_256_ecb,nil,@key[0],nil);
  setLength(EncData, (length(DecData) div 16+1)*16);
  EVP_EncryptUpdate(ctx,@EncData[0],@Encl,@DecData[0],length(DecData));
  EVP_EncryptFinal_ex(ctx,@EncData[Encl],@Padl);
  EVP_CIPHER_CTX_free(ctx);
  SetLength(EncData,Encl+Padl);
  unload;
  Result:=true;
end;
function MamEncAes256Ecb(DecData,Key:TBytes;
  out EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  result:=MamEncAes256Ecb(DecData,Key,EncData);
  EncData:=TNetEncoding.Base64.Encode(EncData);
  EncDataBase64:=TEncoding.ASCII.GetString(EncData);
end;




function MamDecAes128Ecb(
  out DecData:TBytes;Key,EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Decl,Padl:Integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<16 then
  begin
    l:=length(Key);
    SetLength(Key,16);
    AZeroMemory(@Key[l],16-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_DecryptInit_ex(ctx,EVP_aes_128_ecb,nil,@key[0],nil);
  setLength(DecData,length(EncData));
  EVP_DecryptUpdate(ctx,@DecData[0],LongWord(pointer(@Decl)),
    @EncData[0],Length(EncData));
  EVP_DecryptFinal_ex(ctx,@DecData[Decl],LongWord(Pointer(@Padl)));
  setlength(DecData,Decl+Padl);
  unload;
  Result:=True;
end;
function MamDecAes128Ecb(
  out DecData:TBytes;Key:TBytes;EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  EncData:=TEncoding.ASCII.GetBytes(EncDataBase64);
  EncData:=TNetEncoding.Base64.Decode(EncData);
  Result:=MamDecAes128Ecb(DecData,Key,EncData);
end;

function MamDecAes192Ecb(
  out DecData:TBytes;Key,EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Decl,Padl:Integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<24 then
  begin
    l:=length(Key);
    SetLength(Key,24);
    AZeroMemory(@Key[l],24-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_DecryptInit_ex(ctx,EVP_aes_192_ecb,nil,@key[0],nil);
  setLength(DecData,length(EncData));
  EVP_DecryptUpdate(ctx,@DecData[0],LongWord(pointer(@Decl)),
    @EncData[0],Length(EncData));
  EVP_DecryptFinal_ex(ctx,@DecData[Decl],LongWord(Pointer(@Padl)));
  setlength(DecData,Decl+Padl);
  unload;
  Result:=True;
end;
function MamDecAes192Ecb(
  out DecData:TBytes;Key:TBytes;EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  EncData:=TEncoding.ASCII.GetBytes(EncDataBase64);
  EncData:=TNetEncoding.Base64.Decode(EncData);
  Result:=MamDecAes192Ecb(DecData,Key,EncData);
end;

function MamDecAes256Ecb(
  out DecData:TBytes;Key,EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Decl,Padl:Integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<32 then
  begin
    l:=length(Key);
    SetLength(Key,32);
    AZeroMemory(@Key[l],32-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_DecryptInit_ex(ctx,EVP_aes_256_ecb,nil,@key[0],nil);
  setLength(DecData,length(EncData));
  EVP_DecryptUpdate(ctx,@DecData[0],LongWord(pointer(@Decl)),
    @EncData[0],Length(EncData));
  EVP_DecryptFinal_ex(ctx,@DecData[Decl],LongWord(Pointer(@Padl)));
  setlength(DecData,Decl+Padl);
  unload;
  Result:=True;
end;
function MamDecAes256Ecb(
  out DecData:TBytes;Key:TBytes;EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  EncData:=TEncoding.ASCII.GetBytes(EncDataBase64);
  EncData:=TNetEncoding.Base64.Decode(EncData);
  Result:=MamDecAes256Ecb(DecData,Key,EncData);
end;




function MamEncAes128Cbc(
  DecData,Key,Iv:TBytes;out EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Encl,Padl:integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<16 then
  begin
    l:=length(Key);
    SetLength(Key,16);
    AZeroMemory(@Key[l],16-l);
  end;
  if length(Iv)<16 then
  begin
    l:=length(Iv);
    SetLength(Iv,16);
    AZeroMemory(@Iv[l],16-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_EncryptInit_ex(ctx,EVP_aes_128_cbc,nil,@key[0],@Iv[0]);
  setLength(EncData, (length(DecData) div 16+1)*16);
  EVP_EncryptUpdate(ctx,@EncData[0],@Encl,@DecData[0],length(DecData));
  EVP_EncryptFinal_ex(ctx,@EncData[Encl],@Padl);
  EVP_CIPHER_CTX_free(ctx);
  SetLength(EncData,Encl+Padl);
  unload;
  Result:=true;
end;
function MamEncAes128Cbc(
  DecData,Key,Iv:TBytes;out EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  result:=MamEncAes128Cbc(DecData,Key,Iv,EncData);
  EncData:=TNetEncoding.Base64.Encode(EncData);
  EncDataBase64:=TEncoding.ASCII.GetString(EncData);
end;

function MamEncAes192Cbc(
  DecData,Key,Iv:TBytes;out EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Encl,Padl:integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<24 then
  begin
    l:=length(Key);
    SetLength(Key,24);
    AZeroMemory(@Key[l],24-l);
  end;
  if length(Iv)<16 then
  begin
    l:=length(Iv);
    SetLength(Iv,16);
    AZeroMemory(@Iv[l],16-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_EncryptInit_ex(ctx,EVP_aes_192_cbc,nil,@key[0],@Iv[0]);
  setLength(EncData, (length(DecData) div 16+1)*16);
  EVP_EncryptUpdate(ctx,@EncData[0],@Encl,@DecData[0],length(DecData));
  EVP_EncryptFinal_ex(ctx,@EncData[Encl],@Padl);
  EVP_CIPHER_CTX_free(ctx);
  SetLength(EncData,Encl+Padl);
  unload;
  Result:=true;
end;
function MamEncAes192Cbc(
  DecData,Key,Iv:TBytes;out EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  result:=MamEncAes192Cbc(DecData,Key,Iv,EncData);
  EncData:=TNetEncoding.Base64.Encode(EncData);
  EncDataBase64:=TEncoding.ASCII.GetString(EncData);
end;

function MamEncAes256Cbc(
  DecData,Key,Iv:TBytes;out EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Encl,Padl:integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<32 then
  begin
    l:=length(Key);
    SetLength(Key,32);
    AZeroMemory(@Key[l],32-l);
  end;
  if length(Iv)<16 then
  begin
    l:=length(Iv);
    SetLength(Iv,16);
    AZeroMemory(@Iv[l],16-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_EncryptInit_ex(ctx,EVP_aes_256_cbc,nil,@key[0],@Iv[0]);
  setLength(EncData, (length(DecData) div 16+1)*16);
  EVP_EncryptUpdate(ctx,@EncData[0],@Encl,@DecData[0],length(DecData));
  EVP_EncryptFinal_ex(ctx,@EncData[Encl],@Padl);
  EVP_CIPHER_CTX_free(ctx);
  SetLength(EncData,Encl+Padl);
  unload;
  Result:=true;
end;
function MamEncAes256Cbc(
  DecData,Key,Iv:TBytes;out EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  result:=MamEncAes256Cbc(DecData,Key,Iv,EncData);
  EncData:=TNetEncoding.Base64.Encode(EncData);
  EncDataBase64:=TEncoding.ASCII.GetString(EncData);
end;




function MamDecAes128Cbc(
  out DecData:TBytes;Key,Iv,EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Decl,Padl:Integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<16 then
  begin
    l:=length(Key);
    SetLength(Key,16);
    AZeroMemory(@Key[l],16-l);
  end;
  if length(Iv)<16 then
  begin
    l:=length(Iv);
    SetLength(Iv,16);
    AZeroMemory(@Iv[l],16-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_DecryptInit_ex(ctx,EVP_aes_128_cbc,nil,@key[0],@Iv[0]);
  setLength(DecData,length(EncData));
  EVP_DecryptUpdate(ctx,@DecData[0],LongWord(pointer(@Decl)),
    @EncData[0],Length(EncData));
  EVP_DecryptFinal_ex(ctx,@DecData[Decl],LongWord(Pointer(@Padl)));
  setlength(DecData,Decl+Padl);
  unload;
  Result:=True;
end;
function MamDecAes128Cbc(
  out DecData:TBytes;Key,Iv:TBytes;EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  EncData:=TEncoding.ASCII.GetBytes(EncDataBase64);
  EncData:=TNetEncoding.Base64.Decode(EncData);
  Result:=MamDecAes128Cbc(DecData,Key,Iv,EncData);
end;

function MamDecAes192Cbc(
  out DecData:TBytes;Key,Iv,EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Decl,Padl:Integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<24 then
  begin
    l:=length(Key);
    SetLength(Key,24);
    AZeroMemory(@Key[l],24-l);
  end;
  if length(Iv)<16 then
  begin
    l:=length(Iv);
    SetLength(Iv,16);
    AZeroMemory(@Iv[l],16-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_DecryptInit_ex(ctx,EVP_aes_192_cbc,nil,@key[0],@Iv[0]);
  setLength(DecData,length(EncData));
  EVP_DecryptUpdate(ctx,@DecData[0],LongWord(pointer(@Decl)),
    @EncData[0],Length(EncData));
  EVP_DecryptFinal_ex(ctx,@DecData[Decl],LongWord(Pointer(@Padl)));
  setlength(DecData,Decl+Padl);
  unload;
  Result:=True;
end;
function MamDecAes192Cbc(
  out DecData:TBytes;Key,Iv:TBytes;EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  EncData:=TEncoding.ASCII.GetBytes(EncDataBase64);
  EncData:=TNetEncoding.Base64.Decode(EncData);
  Result:=MamDecAes192Cbc(DecData,Key,Iv,EncData);
end;

function MamDecAes256Cbc(
  out DecData:TBytes;Key,Iv,EncData:TBytes):Boolean;overload;
var ctx:PEVP_CIPHER_CTX;
    Decl,Padl:Integer;
    l:integer;
begin
  Result:=false;
  if not load then exit;
  if length(Key)<32 then
  begin
    l:=length(Key);
    SetLength(Key,32);
    AZeroMemory(@Key[l],32-l);
  end;
  if length(Iv)<16 then
  begin
    l:=length(Iv);
    SetLength(Iv,16);
    AZeroMemory(@Iv[l],16-l);
  end;
  ctx:=EVP_CIPHER_CTX_new();
  EVP_CIPHER_CTX_init(ctx);
  EVP_DecryptInit_ex(ctx,EVP_aes_256_cbc,nil,@key[0],@Iv[0]);
  setLength(DecData,length(EncData));
  EVP_DecryptUpdate(ctx,@DecData[0],LongWord(pointer(@Decl)),
    @EncData[0],Length(EncData));
  EVP_DecryptFinal_ex(ctx,@DecData[Decl],LongWord(Pointer(@Padl)));
  setlength(DecData,Decl+Padl);
  unload;
  Result:=True;
end;
function MamDecAes256Cbc(
  out DecData:TBytes;Key,Iv:TBytes;EncDataBase64:String):Boolean;overload;
var EncData:TBytes;
begin
  EncData:=TEncoding.ASCII.GetBytes(EncDataBase64);
  EncData:=TNetEncoding.Base64.Decode(EncData);
  Result:=MamDecAes256Cbc(DecData,Key,Iv,EncData);
end;

end.