PHP to Delphi and back Encryption-Decryption using Rijndael - php

I have problems with decrypting strings sent from PHP to Delphi using the rijndael cipher.
I'm using mcrypt on the PHP side and DCP_rijndael on the Delphi side.
At the moment I have the below code.
PHP:
function encRJ($key, $iv, $data)
{
$r = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv);
$r = base64_encode($r);
return $r;
}
And in Delphi:
function decRJ(Data: string; Key: string; IV: string): string;
var ciph: TDCP_rijndael;
begin
Data := Base64DecodeStr(Data);
ciph:= TDCP_rijndael.Create(Self);
ciph.Init(Key[1], 256, #IV[1]);
ciph.DecryptCBC(Data[1], Data[1], Length(Data));
ciph.Free;
Result := Data;
end;
I have tried using several Units on the Internet implementing the cipher, and found out most people are saying about the DCP components. Even so, I haven't managed to make it correctly decrypt. I've tried using Byte arrays for the parameters, AnsiStrings, WideStrings, etc, but unfortunately no luck.
Excuse me if I'm missing something really obvious here, as my mind isn't in good shape atm, after hours of searching for the matter.

I seem to have spent too long on this but...
Your problem is the block size. TDCP_rijndael is equivalent to MCRYPT_RIJNDAEL_128 (not _256). The '256' value in ciph.Init(...) call is still correct though. Other than that it looks pretty much ok. That is, assuming you're using ansistrings for key/iv or you're using non-unicode Delphi.
For unicode Delphi versions I'd be inclined to use TBytes and key[0] / iv[0].
Padding may still be an issue. If so, then here's what I've mangled up based on the PHP manual pages and some trial and error.
PHP:
function Encrypt($src, $key, $iv)
{
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, 'cbc');
//echo "Block size: " . $block . "\r\n";
$pad = $block - (strlen($src) % $block);
$src .= str_repeat(chr($pad), $pad);
$enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $src, MCRYPT_MODE_CBC, $iv);
$r = base64_encode($enc);
return $r;
}
function Decrypt($src, $key, $iv)
{
$enc = base64_decode($src);
$dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $enc, MCRYPT_MODE_CBC, $iv);
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, 'cbc');
$pad = ord($dec[($len = strlen($dec)) - 1]);
return substr($dec, 0, strlen($dec) - $pad);
}
Delphi:
function DecryptData(Data: string; AKey: AnsiString; AIv: AnsiString): string;
var
key, iv, src, dest: TBytes;
cipher: TDCP_rijndael;
slen, pad: integer;
begin
//key := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AKey));
//iv := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AIv));
key := TEncoding.ASCII.GetBytes(AKey);
iv := TEncoding.ASCII.GetBytes(AIv);
src := Base64DecodeBytes(TEncoding.UTF8.GetBytes(Data));
cipher := TDCP_rijndael.Create(nil);
try
cipher.CipherMode := cmCBC;
slen := Length(src);
SetLength(dest, slen);
cipher.Init(key[0], 256, #iv[0]); // DCP uses key size in BITS not BYTES
cipher.Decrypt(src[0], dest[0], slen);
// Remove the padding. Get the numerical value of the last byte and remove
// that number of bytes
pad := dest[slen - 1];
SetLength(dest, slen - pad);
// Base64 encode it
result := TEncoding.Default.GetString(dest);
finally
cipher.Free;
end;
end;
function EncryptData(Data: string; AKey: AnsiString; AIv: AnsiString): string;
var
cipher: TDCP_rijndael;
key, iv, src, dest, b64: TBytes;
index, slen, bsize, pad: integer;
begin
//key := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AKey));
//iv := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AIv));
key := TEncoding.ASCII.GetBytes(AKey);
iv := TEncoding.ASCII.GetBytes(AIv);
src := TEncoding.UTF8.GetBytes(Data);
cipher := TDCP_rijndael.Create(nil);
try
cipher.CipherMode := cmCBC;
// Add padding.
// Resize the Value array to make it a multiple of the block length.
// If it's already an exact multiple then add a full block of padding.
slen := Length(src);
bsize := (cipher.BlockSize div 8);
pad := bsize - (slen mod bsize);
Inc(slen, pad);
SetLength(src, slen);
for index := pad downto 1 do
begin
src[slen - index] := pad;
end;
SetLength(dest, slen);
cipher.Init(key[0], 256, #iv[0]); // DCP uses key size in BITS not BYTES
cipher.Encrypt(src[0], dest[0], slen);
b64 := Base64EncodeBytes(dest);
result := TEncoding.Default.GetString(b64);
finally
cipher.Free;
end;
end;
The PHP and Delphi functions now give me the same answer.
EDIT
Base64DecodeBytes was a bit of code I added to the DCP Base64 unit:
function Base64DecodeBytes(Input: TBytes): TBytes;
var
ilen, rlen: integer;
begin
ilen := Length(Input);
SetLength(result, (ilen div 4) * 3);
rlen := Base64Decode(#Input[0], #result[0], ilen);
// Adjust the length of the output buffer according to the number of valid
// b64 characters
SetLength(result, rlen);
end;
EDIT 2018 (Raising the dead...):
As requested, here is the encoding method, unchecked and pulled straight from an old source file I found.
DISCLAIMER: It is many years old and untested in recent memory and not used since Delphi 2010. There are probably many better alternatives now. Use at your own risk.
function Base64EncodeBytes(Input: TBytes): TBytes;
var
ilen: integer;
begin
ilen := Length(Input);
SetLength(result, ((ilen + 2) div 3) * 4);
Base64Encode(#Input[0], #result[0], ilen);
end;

Neither your PHP nor your Delphi methods appear to specify any padding. If the default paddings are different then you will get problems. Explicitly specify PKCS7 (or PKCS5) for both.
GregS' comment about the result of decoding Base64 is correct. You are supplying encrypted cyphertext to your decRJ() method. That will be random appearing bytes. Attempting to convert it to UTF-8 will mangle it enough that it cannot be decrypted. The incoming cyphertext must be converted from Base64 direct to a byte array. Cyphertext is not a character string, which is why it needs to be converted to Base64 to be transmitted as text. It will only be text again after it has been decrypted back to plaintext.

Related

How to decrypt a string in PL/SQL that is encrypted using PHP?

I am new to encryption and decryption techniques. I have a requirement to decrypt the response in PL/SQL received from the PHP server. The encryption method is AES128 CBC.
PHP Code
$clear_text = "Secret Message";
$str = "0962774221568619";
$key = "0962774221568619";
$iv = str_pad($iv, 16, "\0");
$encrypt_text = openssl_encrypt($clear_text, "AES-128-CBC", $key, OPENSSL_RAW_DATA, $iv);
$data = base64_encode($encrypt_text);
echo $data;
The encrypted string from the above code is: 87UMyOAog3rlmzorneakjA==
Now I want to decrypt this string in PL/SQL. Before decrypting, first I tried to encrypt the same message by replicating PHP code in PL/SQL as below.
Encryption using PL/SQL
DECLARE
input_string VARCHAR2 (200) := 'Secret Message';
output_string VARCHAR2 (200);
encrypted_raw RAW (2000); -- stores encrypted binary text
decrypted_raw RAW (2000); -- stores decrypted binary text
encrypted_string VARCHAR2(1000);
num_key_bytes NUMBER := 128/8; -- key length 256 bits (32 bytes)
key_bytes_raw RAW (32); -- stores 256-bit encryption key
encryption_type PLS_INTEGER := -- total encryption type
DBMS_CRYPTO.ENCRYPT_AES128
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
iv_raw RAW (16);
BEGIN
key_bytes_raw := UTL_I18N.STRING_TO_RAW ('0962774221568619', 'UTF8');
iv_raw := UTL_I18N.STRING_TO_RAW ('0962774221568619', 'UTF8');
encrypted_raw := DBMS_CRYPTO.ENCRYPT
(
src => UTL_I18N.STRING_TO_RAW (input_string, 'UTF8'),
typ => encryption_type,
key => key_bytes_raw,
iv => iv_raw
);
DBMS_OUTPUT.PUT_LINE ('encrypted_raw: ' || encrypted_raw);
encrypted_string:= utl_raw.cast_to_varchar2(UTL_ENCODE.BASE64_ENCODE(encrypted_raw));
DBMS_OUTPUT.PUT_LINE ('encrypted_string: ' || encrypted_string);
END;
Output
encrypted_raw: 0C36016A23FE45D8C62C50615336E5C6
encrypted_string: DDYBaiP+RdjGLFBhUzblxg=
Here I got different encrypted strings from PHP and PL/SQL. I am not sure but seems like the PHP code replication in PL/SQL is not correct to me.
Using the below code, I am able to decrypt the string encrypted from PL/SQL.
DECLARE
output_string VARCHAR2 (200);
encrypted_raw RAW (2000); -- stores encrypted binary text
decrypted_raw RAW (2000); -- stores decrypted binary text
num_key_bytes NUMBER := 128/8; -- key length 256 bits (32 bytes)
key_bytes_raw RAW (32); -- stores 256-bit encryption key
encryption_type PLS_INTEGER := -- total encryption type
DBMS_CRYPTO.ENCRYPT_AES128
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
iv_raw RAW (16);
BEGIN
encrypted_raw := '0C36016A23FE45D8C62C50615336E5C6';
key_bytes_raw := UTL_I18N.STRING_TO_RAW ('0962774221568619', 'UTF8');
iv_raw := UTL_I18N.STRING_TO_RAW ('0962774221568619', 'UTF8');
decrypted_raw := DBMS_CRYPTO.DECRYPT
(
src => encrypted_raw,
typ => encryption_type,
key => key_bytes_raw,
iv => iv_raw
);
output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');
DBMS_OUTPUT.PUT_LINE ('Decrypted string: ' || output_string);
END;
Output: Secret Message
This is fine but I am facing challenges while decrypting the string encrypted from PHP.
Update
I forgot to assign a value of IV in the PHP code that I used to encrypt the string. Thanks to #topaco and #BartoszOlchowik for pointing out this mistake.
Updated code
PHP
$clear_text = "Secret Message";
$iv = "0962774221568619";
$key = "0962774221568619";
$iv = str_pad($iv, 16, "\0");
$encrypt_text = openssl_encrypt($clear_text, "AES-128-CBC", $key, OPENSSL_RAW_DATA, $iv);
$data = base64_encode($encrypt_text);
echo $data;
Encrypted String: DDYBaiP+RdjGLFBhUzblxg==
PL/SQL
DECLARE
encrypted_string VARCHAR2(1000):= 'DDYBaiP+RdjGLFBhUzblxg=='; -- Encrypted string from php
output_string VARCHAR2 (200);
encrypted_raw RAW (2000); -- stores encrypted binary text
decrypted_raw RAW (2000); -- stores decrypted binary text
num_key_bytes NUMBER := 128/8; -- key length 256 bits (32 bytes)
key_bytes_raw RAW (32); -- stores 256-bit encryption key
encryption_type PLS_INTEGER := -- total encryption type
DBMS_CRYPTO.ENCRYPT_AES128
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
iv_raw RAW (16);
BEGIN
key_bytes_raw := UTL_I18N.STRING_TO_RAW ('0962774221568619', 'UTF8');
iv_raw := UTL_I18N.STRING_TO_RAW ('0962774221568619', 'UTF8');
--convert base64 encrypted string from php to raw
encrypted_raw:= UTL_ENCODE.BASE64_DECODE(utl_raw.cast_to_raw(encrypted_string));
decrypted_raw := DBMS_CRYPTO.DECRYPT
( src => encrypted_raw,
typ => encryption_type,
key => key_bytes_raw,
iv => iv_raw );
output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');
DBMS_OUTPUT.PUT_LINE ('Decrypted string: ' || output_string);
END;
Output: Decrypted string: Secret Message
You have to declare same cryptographic data to be able to decrypt it correctly.
In your PLSQL code IV variable has different value from IV declared in PHP, so you wont be able to decrypt data in PLSQL, which you encrypted with different IV in PHP.
Using the same IV value in PLSQL as in PHP will solve the problem.

AES-256-CBC encryption Golang and PHP

I am trying to achieve AES-256-CBC encryption in golang. I have a working PHP code that has been used for years. I am getting encrypted values in Golang, but the values don't match the output from PHP one, for the same payload/key/iv combination.
For simplification I am hardcoding the payload/key/iv in below codes. I have also removed verbose error messaging from my go code.
This is my GO code
func encryption() {
plaintext := []byte("12345678912345678912345678900000")
key, _ := base64.StdEncoding.DecodeString("cidRgzwfcgztwae/mccalIeedOAmA/CbU3HEqWz1Ejk=")
iv, _ := hex.DecodeString("162578ddce177a4a7cb2f7c738fa052d")
/*php seem to use PKCS7 padding to make the source string match the blocksize
requirement for AES-256-CBC.
From what I understand, I need to do padding manually in Golang.
Correct me if wrong */
plaintext, _ = Pkcs7Pad(plaintext, aes.BlockSize)
block, _ := aes.NewCipher(key)
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
fmt.Printf("EncryptedText %v\n", string(ciphertext))
fmt.Printf("EncryptedText as hex %v\n", hex.EncodeToString(ciphertext))
}
func Pkcs7Pad(b []byte, blocksize int) ([]byte, error) {
if blocksize <= 0 {
return nil, errors.New("Invalid block size")
}
if b == nil || len(b) == 0 {
return nil, errors.New("Invalid block size")
}
n := blocksize - (len(b) % blocksize)
pb := make([]byte, len(b)+n)
copy(pb, b)
copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
return pb, nil
}
And my Go output is
EncryptedText |8??X?z??F ?0ĺe?,??G?V?
Gce??dM????z?,*ȁҼ
EncryptedText as hex 7c38bad658907a81d14620c930c4ba658c1f022cdb1392479856cc0a471d6365dfc5644db6b28cef7ac02c2ac881d2bc
I have a PHP code to do the same task, which gives me a different output.
function encryption() {
$plaintext = "12345678912345678912345678900000";
$key = base64_decode("cidRgzwfcgztwae/mccalIeedOAmA/CbU3HEqWz1Ejk=");
$iv = hex2bin("162578ddce177a4a7cb2f7c738fa052d");
//php openssl_encrypt function seem to use pkcs7pad to make the source string match the blocksize requirement for AES-256-CBC
$ciphertext = openssl_encrypt($plaintext, 'AES-256-CBC', $key, 0, $iv );
print $ciphertext;
}
and the PHP output is
fDi61liQeoHRRiDJMMS6ZYwfAizbE5JHmFbMCkcdY2XfxWRNtrKM73rALCrIgdK8
Obviously, I would like to get my Golang implementation to get the same output as PHP. As I require communication with my Golang code and existing PHP code, I would like to get encryption and decryption work same in both PHP and Golang.
Any ideas?
There are a few issues with your approach:
openssl_encrypt, by default, outputs a base 64 encoded string (not hex)
I suspect your pkcs7Pad (which you did not include) is doing something unexpected (due to the fact that you are skipping the start of ciphertext in mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
Note: I cannot replicate your result because you did not include your pkcs7Pad (a link to the playground is a good idea because it ensures others will be able to replicate your issue).
I believe the code below will give what you are looking for (the result matches the php - I have not done any further testing):
func main() {
plaintext := []byte("12345678912345678912345678900000")
key, err := base64.StdEncoding.DecodeString("cidRgzwfcgztwae/mccalIeedOAmA/CbU3HEqWz1Ejk=")
if err != nil {
panic(err)
}
iv, err := hex.DecodeString("162578ddce177a4a7cb2f7c738fa052d")
if err != nil {
panic(err)
}
plaintext = pkcs7Pad(plaintext, aes.BlockSize)
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
ciphertext := make([]byte, len(plaintext))
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, plaintext)
fmt.Printf("EncryptedText %v\n", string(ciphertext))
fmt.Printf("EncryptedText as hex %v\n", hex.EncodeToString(ciphertext))
fmt.Printf("EncryptedText as base 64 %v\n", base64.StdEncoding.EncodeToString(ciphertext))
}
func pkcs7Pad(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
Try it in the playground

Different results when encrypting with "same" method in Delphi and PHP

I am trying to exchange encrypted messages between Delphi and PHP.
From the Delphi side I downloaded DCPcrypt v2 Beta 3 from here:
http://www.cityinthesky.co.uk/opensource/dcpcrypt/
For encrypting I use this function:
function TForm1.Encrypt3DES(psData, psKey: string): string;
var
Cipher: TDCP_3des;
begin
Cipher:= TDCP_3des.Create(nil);
Cipher.InitStr(psKey,TDCP_sha256);
result:=Cipher.EncryptString(psData);
Cipher.Burn;
Cipher.Free;
end;
And I am testing it like this:
ShowMessage(Encrypt3DES('test','SecretKeySecretKeySecret'));
The result that I get is Z74E0Q== and I can successfully decrypt it with another similar delphi function:
function TForm1.Decrypt3DES(psData, psKey: string): string;
var
Cipher: TDCP_3des;
begin
Cipher:= TDCP_3des.Create(nil);
Cipher.InitStr(psKey, TDCP_sha256);
result:=Cipher.DecryptString(psData);
Cipher.Burn;
Cipher.Free;
end;
From PHP side I tried several function to encrypt the same string ('test') with the same key ('SecretKeySecretKeySecret') but the result is different from what I get in Delphi. Again I can successfully decrypt the messages in PHP with similar functions but I need to decrypt messages in Delphi.
This is what I do in PHP, I even tried to hash the key as I see Delphi function is using TDCP_sha256 but still results are diferent.
$key = "SecretKeySecretKeySecret";
echo base64_encode(mcrypt_encrypt(MCRYPT_3DES, $key, 'test', 'ecb')).'<BR><BR>';
echo openssl_encrypt('test', 'des-ede3', $key).'<BR><BR>';
$key = hash('sha256', $key);
echo openssl_encrypt('test', 'des-ede3', $key).'<BR><BR>';
This is the result:
Z05z5Bp4/vY=
L5qmk5nJOzs=
bm7yRdrMs5g=
What am I doing wrong? BTW I am using Delphi 7 and DCPcrypt is the only library for now that I managed to make it run.
I think that this will help you. TDCP_3des is blockcipher and EncryptString method uses EncryptCFB8bit method (Encrypt size bytes of data using the CFB (8 bit) method of encryption).
Two things are important:
use the same initialisation vector
hash the key in PHP part.
Delphi part:
function TForm1.Encrypt3DES(psData, psKey: string): string;
var
Cipher: TDCP_3des;
i: integer;
begin
Cipher := TDCP_3des.Create(nil);
try
Cipher.InitStr(psKey, TDCP_sha256);
Cipher.SetIV('00000000');
Result := Cipher.EncryptString(psData);
Cipher.Burn;
finally
Cipher.Free;
end{try};
end;
procedure TForm1.btnEncryptClick(Sender: TObject);
var
input, key: string;
begin
input := 'Some words in English';
key := 'SecretKeySecretKeySecret';
ShowMessage(Encrypt3DES(input, key));
end;
PHP part:
<?
$key = "SecretKeySecretKeySecret";
$key = hash('sha256', $key, true);
$key = substr($key, 0, 24);
$iv = '00000000';
$message = 'Some words in English';
$result = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CFB, $iv);
$result = base64_encode($result);
echo 'Input text: '.$message.'</br>';
echo 'Encrypted text: '.$result.'</br>';
?>
Output:
Input: Some words in English
Encrypted text: hTpdn+USolFTgv/4HnBEvo4scgmp
Input: This will test Delphi7 and PHP encryption.
Encrypted text: gik2Iw/m2rtMA9gdKqvFqDg3kuUSb4rnAieyZ8unIvt510Rbt1jLPO+/
Input: I hope this will work.
Encrypted text: n/JxW12zORaI7TSCAF4/6cBxqC3mZg==
Notes:
Tested with Delphi 7, DCPcrypt v2, PHP 5.2.10, mcrypt 2.5.7.
The length of your base64 ciphertext shows that DCPCrypt does not use ECB. With a minimal program I can reproduce your result and stepping through the code indeed shows that ECB is not used. The relevant parts are
function TDCP_blockcipher.EncryptString(const Str: string): string;
begin
SetLength(Result,Length(Str));
EncryptCFB8bit(Str[1],Result[1],Length(Str));
Result:= Base64EncodeStr(Result);
end;
function TDCP_blockcipher.DecryptString(const Str: string): string;
begin
Result:= Base64DecodeStr(Str);
DecryptCFB8bit(Result[1],Result[1],Length(Result));
end;

different Delphi / PHP Encryption-Decryption using Rijndael

I am trying to encrypt / decrypt a string using Rijndael from php to Delphi and back.
If I decrypt a PHP string from Delphi ... works fine.
If I encrypt a string with Delphi the result string is ok but shorter
for test I used a string with 62 character. the encrypted string with delphi is long 4 char less of PHP
these the strings ... last characters:
PHP: GyLWj1anBJRmE8mBsaO5cvTrcbvvA==
Delphi: GyLWj1anBJRmE8mBsaO5cvTrcbv
thanks for any advices
I use this source code example:
PHP:
function encrypt ($key, $value)
{
$padSize = 16 - (strlen ($value) % 16) ;
$value = $value . str_repeat (chr ($padSize), $padSize) ;
$output = mcrypt_encrypt (MCRYPT_RIJNDAEL_128, $key, $value, MCRYPT_MODE_CBC, 'xxxxxxx') ;
return base64_encode ($output) ;
}
Delphi encrypt:
function EncryptData3(Data: string; AKey: AnsiString; AIv: AnsiString): string;
var
cipher: TDCP_rijndael;
key, iv, src, dest, b64: TBytes;
index, slen, bsize, pad: integer;
begin
//key := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AKey));
//iv := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AIv));
key := TEncoding.ASCII.GetBytes(AKey);
iv := TEncoding.ASCII.GetBytes(AIv);
src := TEncoding.ascii.GetBytes(Data);
cipher := TDCP_rijndael.Create(nil);
try
cipher.CipherMode := cmCBC;
// Add padding.
// Resize the Value array to make it a multiple of the block length.
// If it's already an exact multiple then add a full block of padding.
slen := Length(src);
bsize := (cipher.BlockSize div 8);
pad := bsize - (slen mod bsize);
Inc(slen, pad);
SetLength(src, slen);
for index := pad downto 1 do
begin
src[slen - index] := pad;
end;
SetLength(dest, slen);
cipher.Init(key[0], 256, #iv[0]); // DCP uses key size in BITS not BYTES
cipher.Encrypt(src[0], dest[0], slen);
b64 := Base64EncodeBytes(dest);
result := TEncoding.Default.GetString(b64);
finally
cipher.Free;
end;
end;
Delphi decrypt ... not works:
function DecryptData3(Data: string; AKey: AnsiString; AIv: AnsiString): string;
var
key, iv, src, dest: TBytes;
cipher: TDCP_rijndael;
slen, pad: integer;
begin
//key := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AKey));
//iv := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AIv));
key := TEncoding.ASCII.GetBytes(AKey);
iv := TEncoding.ASCII.GetBytes(AIv);
src := Base64DecodeBytes(TEncoding.UTF8.GetBytes(Data));
cipher := TDCP_rijndael.Create(nil);
try
cipher.CipherMode := cmCBC;
slen := Length(src);
SetLength(dest, slen);
cipher.Init(key[0], 256, #iv[0]); // DCP uses key size in BITS not BYTES
cipher.Decrypt(src[0], dest[0], slen);
// Remove the padding. Get the numerical value of the last byte and remove
// that number of bytes
pad := dest[slen - 1];
SetLength(dest, slen - pad);
// Base64 encode it
result := TEncoding.Default.GetString(dest);
finally
cipher.Free;
end;
end;
I don't know if I used a correct way ... but if I convert the Bytes Value in String and I use this Base64Encode in this link:
Simple code to encrypt an .INI file string using a password
now I encrypt correctly. this is the example:
SetString(stringValue, PAnsiChar(#dest[0]), slen);
result := Base64Encode2(stringValue);

Aes|Rijndael-128 Hashed Text Decode in Delphi XE2

We have php code:
define('myaesKey', 'znwoq8fq0jf2qjve8laper9f'); // 192 bits and 25 ch.
function encode($CodeTo) {
$Type = 'rijndael-128';
$Mode = 'ecb';
$IV = "1234567890123450";
$Object = mcrypt_module_open($Type, '', $Mode, '');
mcrypt_generic_init($Object , myaesKey, $IV);
$Enc2Code = mcrypt_generic($Object , $CodeTo);
mcrypt_generic_deinit($Object);
mcrypt_module_close($Object);
return bin2hex($secEncCode);
}
Length of $CodeTo is 5, CodeTo is readable symbols of English Alphabet, function send somethind like this
1e49651ba23801907e1d67c5a7c18e06
aefdc02bbcb8ed8e8209a935aa62be53
I tried to decode by diff. ways, one of this :
const
KeySize = 24; // 32 bytes = 256 bits 24 - 192
BlockSize = 16; // 16 bytes = 128 bits
function Decrypt(AText:AnsiString):String;
var
Cipher : TDCP_rijndael; i:Integer;
Data, Key, IV,NewStr : ansistring;
begin
// Pad Key and IV with zeros as appropriate
Key := PadWithZeros(ansistring('znwoq8fq0jf2qjve8laper9f'),KeySize);
IV := PadWithZeros(ansistring('1234567890123450'),BlockSize);
// Decode the Base64 encoded string
NewStr:='';
for i:=1 to (Length(AText) div 2) do
NewStr:=NewStr+chr(byte(StrToInt('$'+Copy(AText,(i-1)*2+1,2))));
Data := NewStr;
// Create the cipher and initialise according to the key length
Cipher := TDCP_rijndael.Create(nil);
if Length(ansistring('znwoq8fq0jf2qjve8laper9f')) <= 16 then
Cipher.Init(Key[1],128,#IV[1])
else if Length(ansistring('znwoq8fq0jf2qjve8laper9f')) <= 24 then
Cipher.Init(Key[1],192,#IV[1])
else
Cipher.Init(Key[1],256,#IV[1]);
// Decrypt the data
// Cipher.DecryptCBC(Data[1],Data[1],Length(Data));
Cipher.DecryptECB(Data[1],Data[1]);
// Free the cipher and clear sensitive information
Cipher.Free;
FillChar(Key[1],Length(Key),0);
// Display the result
result:= Data;
end;
but the decoded text is wrong
6d309aab9887deed8da964cca8818eb4
µ€ц‰ъиTDHQ ЮB№еП
Why?
Can someone help? Easy to decode it by http://www.tools4noobs.com/online_tools/decrypt/ withot IV ...
Try to use this
function AESDecrypt(AData, AKey: String): string;
var
KeyByte,Data,Dest:TBytes;
KeyBlock:integer;
Cipher:TDCP_rijndael;
begin
KeyByte:=TEncoding.UTF8.GetBytes(AKey);
while (Length(KeyByte) mod 16 <> 0) do begin
SetLength(KeyByte,Length(KeyByte)+1);
KeyByte[Length(KeyByte)-1]:=0;
end;
SetLength(Data,Length(AData) div 2);
SetLEngth(Dest,Length(AData) div 2);
Data:=GetBytesFromHex(AData);
Cipher:= TDCP_rijndael.Create(nil);
KeyBlock:=192; //by PHP code comment
Cipher.Init(KeyByte[0],KeyBlock,nil); //for ECB method IV is optional
try
for i := 1 to (Length(AData) div 16) do
begin
Cipher.DecryptECB(Data[(i-1)*16],Dest[(i-1)*16]);
end;
finally
Cipher.Burn;
end;
AData:=TEncoding.UTF8.GetString(Dest);
Result:=AData;
end;

Categories