PHP openssl des-ede3-cbc to Golang - php

I've following code in PHP:
$l = ceil(strlen($message) / 8) * 8;
$enc = substr(openssl_encrypt($message . str_repeat("\0", $l - strlen($message)), 'des-ede3-cbc', $key, OPENSSL_RAW_DATA, "\0\0\0\0\0\0\0\0"), 0, $l);
How can I implement it in Go?
I tried like this but got different result:
block, err := des.NewTripleDESCipher(key)
if err != nil {
fmt.Printf("err: %s", err)
return
}
// Create initialization vector from rand.reader
iv := make([]byte, des.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
fmt.Printf("err: %s", err)
return
}
// Encrypt with CBC mode
cipherText := make([]byte, len(plainText))
encryptMode := cipher.NewCBCEncrypter(block, iv)
encryptMode.CryptBlocks(cipherText, plainText)
str := hex.EncodeToString(cipherText)
fmt.Println("Cipher text: %s", str)

Found the mistake. I was using rand.Reader for iv but in PHP was different.
var iv = []byte{0, 0, 0, 0, 0, 0, 0, 0}

Related

convert mcrypt algorithm to openssl PHP (MCRYPT_TripleDES, MCRYPT_MODE_CBC)

I have got a decryption code that uses deprecated mcrypt, I need to convert this function to use openssl instead. There are many similar questions on Stackoverflow, but they did not help me.
here is the decryption function:
public function decrypt($str, $key){
//input
$str = '9ACF38C842B3522415364850EAD1909BD43FD590BE3CBD539AD5FF6C7465973ABD61E8371E03282605ED06C994DF394244B7E7DAD54A046510484FAA724330C4C95A527D7891151E7C195D4136CBD70A87D1BD1F75473CF6B45A3F2FA8231DD71FFB4150E0BF4B133ECAA5ACC82CFD74903E21BC6EECB4B33AF39B8AF0C183A64002CFC125A55685C69A13192F3A9A4FDAC860E90C3FB6D125285E9E687BEFBE05707E131FC7ABE25FE35AB114FAE8A247B8C0F3DBA8AA74396D10564B7A0617EED913ED';
$key = '10,10,10,10,10,10,10,10';
//expected output:
//'6706598320;67005551;100;00;YKB_TST_090519001330;0;0;https://setmpos.ykb.com/PosnetWebService/YKBTransactionService;posnettest.ykb.com;2225;N;0;Not authenticated;1557398383820;TL'
outputsrand((double) microtime() * 10000000);
$block = #mcrypt_get_block_size(MCRYPT_TripleDES, MCRYPT_MODE_CBC);
$td = #mcrypt_module_open(MCRYPT_TripleDES, '', MCRYPT_MODE_CBC, '');
$ks = #mcrypt_enc_get_key_size($td);
if (strlen($str) < 16 + 8) return false;
// Get IV
$iv = pack("H*", substr($str, 0, 16));
// Get Encrypted Data
$encrypted_data = pack("H*", substr($str, 16, strlen($str)-16-8));
// Get CRC
$crc = substr($str, -8);
// Check CRC
/*if (!$this->checkCrc(substr($str, 0, strlen($str)-8), $crc)) {
return "CRC is not valid! ($crc)";
}*/
// Initialize
#mcrypt_generic_init($td, substr(strtoupper(md5($key)), 0, $ks), $iv);
// Decrypt Data
$decrypted_data = #mdecrypt_generic($td, $encrypted_data);
$packing = ord($decrypted_data[strlen($decrypted_data) - 1]);
if ($packing and ($packing < $block)) {
for($P = strlen($decrypted_data) - 1; $P >= strlen($decrypted_data) - $packing; $P--) {
if (ord($decrypted_data[$P]) != $packing) {
$packing = 0;
}
}
}
return substr($decrypted_data, 0, strlen($decrypted_data) - $packing);
I tried:
$encrypted_data = pack("H*", substr($str, 16, strlen($str)-16-8));
$iv = pack("H*", substr($str, 0, 16));
/returns FALSE when sample input above given
$decrypted_data = openssl_decrypt($encrypted_data, 'des-ede3-cbc', $key, OPENSSL_RAW_DATA, $iv);
Can anybody help me please?
I missed key transformation step, doing this way worked:
$decrypted_data = openssl_decrypt($encrypted_data, 'des-ede3-cbc', substr(strtoupper(md5($key)), 0, 24), OPENSSL_RAW_DATA, $iv);

AES 128 encryption give special charcter

I am trying to do AES128 encryption with key and iv and then convert into hex string.My problem is that when I encrypt string into aes128 and convert into hex it give me a hex string.but when i try this same thing in php I am getting diffrent hex string.So when I try to decrypt php hex string, its decrypted successfully. But when I try to decrypt my hex string in php it's give me special characters.
NSString *str = #"hello";
NSString *key = #"1234abcd5678abcd1234abcd5678abcd";
NSString *IV = #"1234567812345678";
NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
NSData* responseData = [data AES128EncryptedDataWithKey:key iv:IV];
NSLog(#"%#",[self hexRepresentationWithSpaces_AS:NO withdata:responseData]);
- (NSData *)AES128Operation:(CCOperation)operation key:(NSString *)key iv:(NSString *)iv
{
char keyPtr[kCCKeySizeAES128 + 1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char ivPtr[kCCBlockSizeAES128 + 1];
bzero(ivPtr, sizeof(ivPtr));
if (iv) {
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
}
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmAES,
kCCOptionPKCS7Padding,
keyPtr,
kCCBlockSizeAES128,
ivPtr,
[self bytes],
dataLength,
buffer,
bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
-(NSString*)hexRepresentationWithSpaces_AS:(BOOL)spaces withdata:(NSData*)data
{
const unsigned char* bytes = (const unsigned char*)[data bytes];
NSUInteger nbBytes = [data length];
//If spaces is true, insert a space every this many input bytes (twice this many output characters).
static const NSUInteger spaceEveryThisManyBytes = 4UL;
//If spaces is true, insert a line-break instead of a space every this many spaces.
static const NSUInteger lineBreakEveryThisManySpaces = 4UL;
const NSUInteger lineBreakEveryThisManyBytes = spaceEveryThisManyBytes * lineBreakEveryThisManySpaces;
NSUInteger strLen = 2*nbBytes + (spaces ? nbBytes/spaceEveryThisManyBytes : 0);
NSMutableString* hex = [[NSMutableString alloc] initWithCapacity:strLen];
for(NSUInteger i=0; i<nbBytes; ) {
[hex appendFormat:#"%02X", bytes[i]];
//We need to increment here so that the every-n-bytes computations are right.
++i;
if (spaces) {
if (i % lineBreakEveryThisManyBytes == 0) [hex appendString:#"\n"];
else if (i % spaceEveryThisManyBytes == 0) [hex appendString:#" "];
}
}
return hex ;
}
and In php I am using
$td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);
mcrypt_generic_init($td, $key, $iv);
$encrypted = mcrypt_generic($td, $str);
mcrypt_generic_deinit($td);
// mcrypt_module_close($td);
echo $hexdata = bin2hex($encrypted);
echo "<br>";
$bindata = '';
for ($i = 0; $i < strlen($hexdata); $i += 2) {
$bindata .= chr(hexdec(substr($hexdata, $i, 2)));
}
echo $bindata;
echo "<br>";
mcrypt_generic_init($td, $key, $iv);
$decrypted = mdecrypt_generic($td,$encrypted);
mcrypt_generic_deinit($td);
echo "encrypted : ".$encrypted;
echo "<br>";
echo "decrypted : ".$decrypted;
mcrypt is a very old library that does not even implement PKCS#7 compatible padding, which you are obviously using in your iOS code. So at the end you are left with a character representation of the padding, which will probably replaced with replacement characters.
A wrong IV will result in 16 characters being wrong, a wrong key in all characters being wrong. You may also want to match the UTF-8 encoding to be able to display characters with a code point above 0x7F.

AES128 encryption in IOS and php

I am trying to AES128 encryption of a string or NSDictaionary, using following code
NSString *str =#"Hello";
NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
NSData *cipher = [data AES128EncryptWithKey:key];
//After that I converts nsdata into hex string
NSLog(#"%#",[self hexRepresentationWithSpaces_AS:NO withdata:cipher]);
-(NSData *)AES128EncryptWithKey:(NSString *)key
{
// ‘key’ should be 16 bytes for AES128
char keyPtr[kCCKeySizeAES128 + 1]; // room for terminator (unused)
bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That’s why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc( bufferSize );
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128,
#"1234567812345678" /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted );
if( cryptStatus == kCCSuccess )
{
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free( buffer ); //free the buffer
return nil;
}
-(NSString*)hexRepresentationWithSpaces_AS:(BOOL)spaces withdata:(NSData*)data
{
const unsigned char* bytes = (const unsigned char*)[data bytes];
NSUInteger nbBytes = [data length];
//If spaces is true, insert a space every this many input bytes (twice this many output characters).
static const NSUInteger spaceEveryThisManyBytes = 4UL;
//If spaces is true, insert a line-break instead of a space every this many spaces.
static const NSUInteger lineBreakEveryThisManySpaces = 4UL;
const NSUInteger lineBreakEveryThisManyBytes = spaceEveryThisManyBytes * lineBreakEveryThisManySpaces;
NSUInteger strLen = 2*nbBytes + (spaces ? nbBytes/spaceEveryThisManyBytes : 0);
NSMutableString* hex = [[NSMutableString alloc] initWithCapacity:strLen];
for(NSUInteger i=0; i<nbBytes; ) {
[hex appendFormat:#"%02X", bytes[i]];
//We need to increment here so that the every-n-bytes computations are right.
++i;
if (spaces) {
if (i % lineBreakEveryThisManyBytes == 0) [hex appendString:#"\n"];
else if (i % spaceEveryThisManyBytes == 0) [hex appendString:#" "];
}
}
return hex ;
}
On server side following decryption code added
function decrypt($code) {
//$key = $this->hex2bin($key);
$code = $this->hex2bin($code);
$iv = $this->iv;
$td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);
mcrypt_generic_init($td, $this->key, $iv);
$decrypted = mdecrypt_generic($td, $code);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return utf8_encode(trim($decrypted));
}
protected function hex2bin($hexdata) {
$bindata = '';
for ($i = 0; $i < strlen($hexdata); $i += 2) {
$bindata .= chr(hexdec(substr($hexdata, $i, 2)));
}
return $bindata;
}
I problem is that on generated encrypt string not decrypting in php
WE are trying to follow this link
Take a look at this code, it will decrypt & encrypt clear text in both ways using AES128 (Rijndael) with CBC and PKCS7 Padding in PHP and C using CommonCrypto in OSX/iOS and MCRYPT in PHP:
OSX/iOS Code in C:
#include <CommonCrypto/CommonCryptor.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Encrypt text */
char *encryptText(const unsigned char *clearText, char myKey[20], char myIv[20])
{
CCCryptorStatus status;
unsigned char cipherKey[kCCKeySizeAES128];
unsigned char cipherIv[kCCKeySizeAES128];
unsigned char cipherText[strlen((const char *)clearText) + kCCBlockSizeAES128];
size_t nEncrypted;
for (int i=0 ; i<kCCKeySizeAES128; i++)
{
cipherKey[i] = myKey[i];
cipherIv[i] = myIv[i];
}
status = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, cipherKey, kCCKeySizeAES128, cipherIv, clearText, strlen((const char *)clearText), cipherText, sizeof(cipherText), &nEncrypted);
if (status != kCCSuccess)
{
printf("CCCrypt() failed with error %d\n", status);
}
size_t cipherSize = nEncrypted;
char *encoded_data = b64_encode((const unsigned char*)cipherText, cipherSize);
return encoded_data;
}
/* Decrypt text */
int decode(unsigned char *dest, const char *buf)
{
char b[3];
int i;
b[2] = 0;
for(i=0; buf[i] ;i+=2)
{
b[0] = buf[i];
b[1] = buf[i+1];
dest[i/2] = (int) strtol(b, NULL, 0x10);
}
return 0;
}
char *decryptText(const unsigned char *cipherText, char myKey[20], char myIv[20])
{
unsigned char cipherKey[kCCKeySizeAES128];
unsigned char cipherIv[kCCKeySizeAES128];
for (int i=0 ; i<kCCKeySizeAES128; i++)
{
cipherKey[i] = myKey[i];
cipherIv[i] = myIv[i];
}
int lenKey = strlen((const char *)cipherKey);
char hex_key[(lenKey*2)+1];
char2hex((char *)cipherKey, hex_key);
int lenIv = strlen((const char *)cipherIv);
char hex_iv[(lenIv*2)+1];
char2hex((char *)cipherIv, hex_iv);
size_t cipherSize = strlen((const char *)cipherText);
unsigned char *decoded_data = b64_decode((const char*)cipherText, cipherSize);
int lenData = strlen((const char *)decoded_data);
char *hexcipherText;
hexcipherText = bin2hex(decoded_data, lenData);
CCCryptorStatus status;
int len = strlen((const char *)hexcipherText) / 2;
unsigned char clearText[len];
unsigned char decodedCipherText[len];
unsigned char decodedKey[len];
unsigned char decodedIv[len];
size_t nDecrypted;
int i;
decode(decodedKey, (const char *)hex_key);
decode(decodedCipherText, (const char *)hexcipherText);
decode(decodedIv, (const char *)hex_iv);
status = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, decodedKey, kCCKeySizeAES128, decodedIv, decoded_data, len, clearText, sizeof(clearText), &nDecrypted);
if (status != kCCSuccess)
{
printf("CCCrypt() failed with error %d\n", status);
}
int extraInfo = strlen((const char *)clearText);
char* toReturn = malloc(extraInfo + 1);
strcpy(toReturn, (const char *)clearText);
strcat(toReturn, "\0");
return toReturn;
}
Note the base64 encode & decode function (b64_encode, b64_decode):
#ifdef b64_USE_CUSTOM_MALLOC
extern void* b64_malloc(size_t);
#endif
#ifdef b64_USE_CUSTOM_REALLOC
extern void* b64_realloc(void*, size_t);
#endif
int bufc = 0;
char* b64_buf_malloc()
{
char* buf = b64_malloc(B64_BUFFER_SIZE);
bufc = 1;
return buf;
}
char* b64_buf_realloc(unsigned char* ptr, size_t size)
{
if (size > bufc * B64_BUFFER_SIZE)
{
while (size > bufc * B64_BUFFER_SIZE) bufc++;
char* buf = b64_realloc(ptr, B64_BUFFER_SIZE * bufc);
if (!buf) return NULL;
return buf;
}
return (char *)ptr;
}
/* Encode in b64 */
char *b64_encode(const unsigned char *src, size_t len)
{
int i = 0;
int j = 0;
char *enc = NULL;
size_t size = 0;
unsigned char buf[4];
unsigned char tmp[3];
enc = (char *) b64_buf_malloc();
if (NULL == enc) { return NULL; }
while (len--)
{
tmp[i++] = *(src++);
if (3 == i)
{
buf[0] = (tmp[0] & 0xfc) >> 2;
buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4);
buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6);
buf[3] = tmp[2] & 0x3f;
enc = (char *) b64_buf_realloc((unsigned char *)enc, size + 4);
for (i = 0; i < 4; ++i)
{
enc[size++] = b64_table[buf[i]];
}
i = 0;
}
}
if (i > 0)
{
for (j = i; j < 3; ++j)
{
tmp[j] = '\0';
}
buf[0] = (tmp[0] & 0xfc) >> 2;
buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4);
buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6);
buf[3] = tmp[2] & 0x3f;
for (j = 0; (j < i + 1); ++j)
{
enc = (char *) b64_buf_realloc((unsigned char *)enc, size + 1);
enc[size++] = b64_table[buf[j]];
}
while ((i++ < 3))
{
enc = (char *) b64_buf_realloc((unsigned char *)enc, size + 1);
enc[size++] = '=';
}
}
enc = (char *) b64_buf_realloc((unsigned char *)enc, size + 1);
enc[size] = '\0';
return enc;
}
/* Decode b64 */
unsigned char *b64_decode(const char *src, size_t len)
{
return b64_decode_ex(src, len, NULL);
}
unsigned char *b64_decode_ex(const char *src, size_t len, size_t *decsize)
{
int i = 0;
int j = 0;
int l = 0;
size_t size = 0;
unsigned char *dec = NULL;
unsigned char buf[3];
unsigned char tmp[4];
dec = (unsigned char *) b64_buf_malloc();
if (NULL == dec) { return NULL; }
while (len--)
{
if ('=' == src[j]) { break; }
if (!(isalnum(src[j]) || '+' == src[j] || '/' == src[j])) { break; }
tmp[i++] = src[j++];
if (4 == i)
{
for (i = 0; i < 4; ++i)
{
for (l = 0; l < 64; ++l)
{
if (tmp[i] == b64_table[l])
{
tmp[i] = l;
break;
}
}
}
buf[0] = (tmp[0] << 2) + ((tmp[1] & 0x30) >> 4);
buf[1] = ((tmp[1] & 0xf) << 4) + ((tmp[2] & 0x3c) >> 2);
buf[2] = ((tmp[2] & 0x3) << 6) + tmp[3];
dec = (unsigned char *) b64_buf_realloc(dec, size + 3);
if (dec != NULL)
{
for (i = 0; i < 3; ++i)
{
dec[size++] = buf[i];
}
}
else
{
return NULL;
}
i = 0;
}
}
if (i > 0)
{
for (j = i; j < 4; ++j)
{
tmp[j] = '\0';
}
for (j = 0; j < 4; ++j)
{
for (l = 0; l < 64; ++l)
{
if (tmp[j] == b64_table[l])
{
tmp[j] = l;
break;
}
}
}
buf[0] = (tmp[0] << 2) + ((tmp[1] & 0x30) >> 4);
buf[1] = ((tmp[1] & 0xf) << 4) + ((tmp[2] & 0x3c) >> 2);
buf[2] = ((tmp[2] & 0x3) << 6) + tmp[3];
dec = (unsigned char *)b64_buf_realloc(dec, size + (i - 1));
if (dec != NULL)
{
for (j = 0; (j < i - 1); ++j)
{
dec[size++] = buf[j];
}
}
else
{
return NULL;
}
}
dec = (unsigned char *)b64_buf_realloc(dec, size + 1);
if (dec != NULL)
{
dec[size] = '\0';
}
else
{
return NULL;
}
if (decsize != NULL)
{
*decsize = size;
}
return dec;
}
Also note the bin2hex & char2hex function:
/* Char to Hex conversion */
void char2hex(char* input, char* output)
{
int loop;
int i;
i=0;
loop=0;
while(input[loop] != '\0')
{
sprintf((char*)(output+i),"%02X", input[loop]);
loop+=1;
i+=2;
}
output[i++] = '\0';
}
/* Bin to Hex conversion */
static char hexconvtab[] = "0123456789abcdef";
static char* bin2hex(const unsigned char *old, const size_t oldlen)
{
char *result = (char*) malloc(oldlen * 2 + 1);
size_t i, j;
for (i = j = 0; i < oldlen; i++)
{
result[j++] = hexconvtab[old[i] >> 4];
result[j++] = hexconvtab[old[i] & 15];
}
result[j] = '\0';
return result;
}
Now, the PHP Code:
/* Encrypt text */
function encRijndael($text, $key, $iv)
{
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$padding = $block - (strlen($text) % $block);
$text .= str_repeat(chr($padding), $padding);
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);
return base64_encode($crypttext);
}
/* Decrypt Text */
function decRijndael($encrypted, $key, $iv)
{
$iv_utf = mb_convert_encoding($iv, 'UTF-8');
$toreturn = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($encrypted), MCRYPT_MODE_CBC, $iv_utf);
$toreturn = filter_var($toreturn, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
return $toreturn;
}
I learned this code reading the book O'Reilly, Hacking and Securing iOS Applications from Jonathan Zdziarski.

PHP function to decrypt a VB.NET RijndaelManaged class encryption

I have the following Visual Basic .NET function that is used to encrypt a file. This function is from third party so I cannot alter the original code.
Dim bytes As Byte() = New UnicodeEncoding().GetBytes("12345678")
Dim fileStream1 As FileStream = New System.IO.FileStream(txtInput.Text, FileMode.Create)
Dim rijndaelManaged As RijndaelManaged = New RijndaelManaged
Dim cryptoStream1 As CryptoStream = New CryptoStream(fileStream1, rijndaelManaged.CreateEncryptor(bytes, bytes), CryptoStreamMode.Write)
Dim fileStream2 As FileStream = New System.IO.FileStream(txtOutput.Text, FileMode.Open)
Dim BytesRead As Integer
Dim buffer(4096) As Byte
Do
BytesRead = fileStream2.Read(buffer, 0, buffer.Length)
If BytesRead > 0 Then
cryptoStream1.Write(buffer, 0, BytesRead)
End If
Loop While BytesRead > 0
I need help creating a PHP to decrypt the above function. Currently I tried to decrypt using this function in PHP:
function decrypt($text) {
$key = mb_convert_encoding("12345678","utf-16");
$iv = mb_convert_encoding("12345678","utf-16");
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv), "\0");
}
$decrypted=decrypt(file_get_contents("tes_encrypted.xml"));
$nfile = fopen("test.xml", 'w');
fwrite($nfile, $decrypted);
fclose($nfile);
As you can see the encryption function in VB.NET use a predefined Key and IV. It also doesn't specify a padding method. The PHP function generates different result.
Finally I got the answer. Here the correct PHP code to decrypt the VB.NET encryption above:
function unpad($value)
{
$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$packing = ord($value[strlen($value) - 1]);
if($packing && $packing < $blockSize)
{
for($P = strlen($value) - 1; $P >= strlen($value) - $packing; $P--)
{
if(ord($value{$P}) != $packing)
{
$packing = 0;
}
}
}
return substr($value, 0, strlen($value) - $packing);
}
function decrypt($text) {
$key= mb_convert_encoding("12345678","ucs-2LE");
$iv= mb_convert_encoding("12345678","ucs-2LE");
return unpad(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv));
}

PHP DES Encryption compatible with Delphi - encryption function

I am trying to create the encrypt PHP algorithm from this thread:
how to sync encryption between delphi and php using dcpcrypt (see shunty's reply)
Here is what I have so far:
function encrypt($str, $key)
{
$keysize = mcrypt_get_key_size(MCRYPT_DES, MCRYPT_MODE_CBC);
$ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);
$iv = implode(array_map("chr", $ivbytes));
$pad = ord($str[strlen($str) - 1]);
$enc = substr($str, 0, strlen($str) - $pad);
$enc = base64_encode($str);
$k = mhash(MHASH_SHA1, $key);
//return substr($dec, 0, strlen($dec) - $pad);
$dec = mcrypt_encrypt(MCRYPT_DES, substr($k, 0, $keysize), $enc, MCRYPT_MODE_CBC, $iv);
return $dec;
}
I'm not sure what I'm doing wrong but testing it with this:
echo encrypt("this is a test", "test");
Gives the output: =ž«RCdrç­b˜hý’¯á·OÊ
when it should give: WRaG/8xlxqqcTAJ5UAk4DA==
Can anyone help me out in explaining where I am going wrong, would really appreciate the help I can get.
EDIT:
function encrypt_SO($str, $key)
{
$keysize = mcrypt_get_key_size(MCRYPT_DES, MCRYPT_MODE_CBC);
$ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);
$iv = implode(array_map("chr", $ivbytes));
$pad = ord($str[strlen($str) - 1]);
$enc = substr($str, 0, strlen($str) - $pad);
$k = mhash(MHASH_SHA1, $key);
//return substr($dec, 0, strlen($dec) - $pad);
$dec = mcrypt_encrypt(MCRYPT_DES, substr($k, 0, $keysize), $enc, MCRYPT_MODE_CBC, $iv);
return base64_encode($dec);
}
Moved the encoding to the end.
EDIT 2: Solution thanks to everyone's helpful posts:
function encrypt_SO($str, $key)
{
$keysize = mcrypt_get_key_size(MCRYPT_DES, MCRYPT_MODE_CBC);
$ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);
$iv = implode(array_map("chr", $ivbytes));
$k = mhash(MHASH_SHA1, $key);
$blocksize = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC);
$padsize = $blocksize - (strlen($str) % $blocksize);
$str .= str_repeat(chr($padsize), $padsize);
return base64_encode(mcrypt_encrypt(MCRYPT_DES, substr($k, 0, $keysize), $str, MCRYPT_MODE_CBC, $iv));
}
To answer your comment above:
Encrypt:
Get keysize and blocksize
Get IV - this should really be something random and properly generated but to work with DCPcrypt without specifying an IV manually you need to use the one provided.
Hash the key
Add the padding - you've got this bit wrong. For this example you need something like:
$blocksize = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC);
$padsize = $blocksize - (strlen($str) % $blocksize);
$str .= str_repeat(chr($padsize), $padsize);
Encrypt
Base64 encode
Decrypt:
Get keysize
Get IV - as above (must be the same as the one used to encrypt but, again, should really be properly cryptographically generated).
Hash the key
Base64 decode
Decrypt
Remove the padding

Categories